@@ -66,15 +66,15 @@ def __str__(self):
66
66
map (_as_str , self ._params .values ())))
67
67
if params :
68
68
params = '(' + params + ')'
69
- return '{}{}' . format ( self .__class__ .__name__ , params )
69
+ return f' { self .__class__ .__name__ } { params } '
70
70
71
71
def _check_params (self , params ):
72
72
for k , v in params .items ():
73
73
if not hasattr (self , k ):
74
74
raise AttributeError (
75
- "Strategy '{}' is missing parameter '{}'. Strategy class "
75
+ f "Strategy '{ self . __class__ . __name__ } ' is missing parameter '{ k } '. Strategy class "
76
76
"should define parameters as class variables before they "
77
- "can be optimized or run with." . format ( self . __class__ . __name__ , k ) )
77
+ "can be optimized or run with." )
78
78
setattr (self , k , v )
79
79
return params
80
80
@@ -121,15 +121,15 @@ def init():
121
121
if name is None :
122
122
params = ',' .join (filter (None , map (_as_str , chain (args , kwargs .values ()))))
123
123
func_name = _as_str (func )
124
- name = ('{ }({})' if params else '{}' ). format ( func_name , params )
124
+ name = (f' { func_name } ({ params } )' if params else f' { func_name } ' )
125
125
else :
126
126
name = name .format (* map (_as_str , args ),
127
127
** dict (zip (kwargs .keys (), map (_as_str , kwargs .values ()))))
128
128
129
129
try :
130
130
value = func (* args , ** kwargs )
131
131
except Exception as e :
132
- raise RuntimeError ('Indicator "{}" errored with exception: {}' . format ( name , e ) )
132
+ raise RuntimeError (f 'Indicator "{ name } " errored with exception: { e } ' )
133
133
134
134
if isinstance (value , pd .DataFrame ):
135
135
value = value .values .T
@@ -145,8 +145,7 @@ def init():
145
145
if not is_arraylike or not 1 <= value .ndim <= 2 or value .shape [- 1 ] != len (self ._data .Close ):
146
146
raise ValueError (
147
147
'Indicators must return (optionally a tuple of) numpy.arrays of same '
148
- 'length as `data` (data shape: {}; indicator "{}" shape: {}, returned value: {})'
149
- .format (self ._data .Close .shape , name , getattr (value , 'shape' , '' ), value ))
148
+ f'length as `data` (data shape: { self ._data .Close .shape } ; indicator "{ name } " shape: { getattr (value , 'shape' , '' )} , returned value: { value } )' )
150
149
151
150
if plot and overlay is None and np .issubdtype (value .dtype , np .number ):
152
151
x = value / self ._data .Close
@@ -293,10 +292,9 @@ def __getattr__(self, item):
293
292
removed_attrs = ('entry' , 'set_entry' , 'is_long' , 'is_short' ,
294
293
'sl' , 'tp' , 'set_sl' , 'set_tp' )
295
294
if item in removed_attrs :
296
- raise AttributeError ('Strategy.orders.{} were removed in Backtesting 0.2.0. '
297
- 'Use `Order` API instead. See docs.'
298
- .format ('/.' .join (removed_attrs )))
299
- raise AttributeError ("'tuple' object has no attribute {!r}" .format (item ))
295
+ raise AttributeError (f'Strategy.orders.{ "/." .join (removed_attrs )} were removed in Backtesting 0.2.0. '
296
+ 'Use `Order` API instead. See docs.' )
297
+ raise AttributeError (f"'tuple' object has no attribute { item !r} " )
300
298
301
299
302
300
class Position :
@@ -351,7 +349,7 @@ def close(self, portion: float = 1.):
351
349
trade .close (portion )
352
350
353
351
def __repr__ (self ):
354
- return '<Position: {} ({} trades)>' . format ( self .size , len (self .__broker .trades ))
352
+ return f '<Position: { self .size } ( { len (self .__broker .trades )} trades)>'
355
353
356
354
357
355
class _OutOfMoneyError (Exception ):
@@ -518,9 +516,7 @@ def __init__(self, broker: '_Broker', size: int, entry_price: float, entry_bar):
518
516
self .__tp_order = None # type: Optional[Order]
519
517
520
518
def __repr__ (self ):
521
- return '<Trade size={} time={}-{} price={}-{} pl={:.0f}>' .format (
522
- self .__size , self .__entry_bar , self .__exit_bar or '' ,
523
- self .__entry_price , self .__exit_price or '' , self .pl )
519
+ return f'<Trade size={ self .__size } time={ self .__entry_bar } -{ self .__exit_bar or "" } price={ self .__entry_price } -{ self .__exit_price or "" } pl={ self .pl :.0f} >'
524
520
525
521
def _replace (self , ** kwargs ):
526
522
for k , v in kwargs .items ():
@@ -665,9 +661,9 @@ def __set_contingent(self, type, price):
665
661
class _Broker :
666
662
def __init__ (self , * , data , cash , commission , margin ,
667
663
trade_on_close , hedging , exclusive_orders , index ):
668
- assert 0 < cash , "cash shosuld be >0, is {}" . format ( cash )
669
- assert 0 <= commission < .1 , "commission should be between 0-10%, is {}" . format ( commission )
670
- assert 0 < margin <= 1 , "margin should be between 0 and 1, is {}" . format ( margin )
664
+ assert 0 < cash , f "cash shosuld be >0, is { cash } "
665
+ assert 0 <= commission < .1 , f "commission should be between 0-10%, is { commission } "
666
+ assert 0 < margin <= 1 , f "margin should be between 0 and 1, is { margin } "
671
667
self ._data = data # type: _Data
672
668
self ._cash = cash
673
669
self ._commission = commission
@@ -683,8 +679,7 @@ def __init__(self, *, data, cash, commission, margin,
683
679
self .closed_trades = [] # type: List[Trade]
684
680
685
681
def __repr__ (self ):
686
- return '<Broker: {:.0f}{:+.1f} ({} trades)>' .format (
687
- self ._cash , self .position .pl , len (self .trades ))
682
+ return f'<Broker: { self ._cash :.0f} { self .position .pl :+.1f} ({ len (self .trades )} trades)>'
688
683
689
684
def new_order (self ,
690
685
size : float ,
@@ -707,12 +702,10 @@ def new_order(self,
707
702
708
703
if is_long :
709
704
if not (sl or - np .inf ) <= (limit or stop or self .last_price ) <= (tp or np .inf ):
710
- raise ValueError ("Long orders require: SL ({}) < LIMIT ({}) < TP ({})" .format (
711
- sl , limit or stop or self .last_price , tp ))
705
+ raise ValueError (f"Long orders require: SL ({ sl } ) < LIMIT ({ limit or stop or self .last_price } ) < TP ({ tp } )" )
712
706
else :
713
707
if not (tp or - np .inf ) <= (limit or stop or self .last_price ) <= (sl or np .inf ):
714
- raise ValueError ("Short orders require: TP ({}) < LIMIT ({}) < SL ({})" .format (
715
- tp , limit or stop or self .last_price , sl ))
708
+ raise ValueError (f"Short orders require: TP ({ tp } ) < LIMIT ({ limit or stop or self .last_price } ) < SL ({ sl } )" )
716
709
717
710
order = Order (self , size , limit , stop , sl , tp , trade )
718
711
# Put the new order in the order queue,
@@ -1237,8 +1230,8 @@ def _tuple(x):
1237
1230
1238
1231
for k , v in kwargs .items ():
1239
1232
if len (_tuple (v )) == 0 :
1240
- raise ValueError ("Optimization variable '{0 }' is passed no "
1241
- "optimization values: {0 }={1}" . format ( k , v ) )
1233
+ raise ValueError (f "Optimization variable '{ k } ' is passed no "
1234
+ f "optimization values: { k } ={ v } " )
1242
1235
1243
1236
class AttrDict (dict ):
1244
1237
def __getattr__ (self , item ):
@@ -1253,7 +1246,7 @@ def __getattr__(self, item):
1253
1246
raise ValueError ('No admissible parameter combinations to test' )
1254
1247
1255
1248
if len (param_combos ) > 300 :
1256
- warnings .warn ('Searching for best of {} configurations.' . format ( len ( param_combos )) ,
1249
+ warnings .warn (f 'Searching for best of { len ( param_combos ) } configurations.' ,
1257
1250
stacklevel = 2 )
1258
1251
1259
1252
heatmap = pd .Series (np .nan ,
0 commit comments