1212import warnings
1313from abc import ABCMeta , abstractmethod
1414from copy import copy
15+ from difflib import get_close_matches
1516from functools import lru_cache , partial
1617from itertools import chain , product , repeat
1718from math import copysign
@@ -64,10 +65,12 @@ def __str__(self):
6465 def _check_params (self , params ):
6566 for k , v in params .items ():
6667 if not hasattr (self , k ):
68+ suggestions = get_close_matches (k , (attr for attr in dir (self ) if not attr .startswith ('_' )))
69+ hint = f" Did you mean: { ', ' .join (suggestions )} ?" if suggestions else ""
6770 raise AttributeError (
68- f"Strategy '{ self .__class__ .__name__ } ' is missing parameter '{ k } '."
71+ f"Strategy '{ self .__class__ .__name__ } ' is missing parameter '{ k } '. "
6972 "Strategy class should define parameters as class variables before they "
70- "can be optimized or run with." )
73+ "can be optimized or run with." + hint )
7174 setattr (self , k , v )
7275 return params
7376
@@ -964,8 +967,9 @@ def _process_orders(self):
964967 # Not enough cash/margin even for a single unit
965968 if not size :
966969 warnings .warn (
967- f'time={ self ._i } : Broker canceled the relative-sized '
968- f'order due to insufficient margin.' , category = UserWarning )
970+ f'time={ self ._i } : Broker canceled the relative-sized order due to insufficient margin '
971+ f'(equity={ self .equity :.2f} , margin_available={ self .margin_available :.2f} ).' ,
972+ category = UserWarning )
969973 # XXX: The order is canceled by the broker?
970974 self .orders .remove (order )
971975 continue
@@ -998,6 +1002,10 @@ def _process_orders(self):
9981002 # If we don't have enough liquidity to cover for the order, the broker CANCELS it
9991003 if abs (need_size ) * adjusted_price_plus_commission > \
10001004 self .margin_available * self ._leverage :
1005+ warnings .warn (
1006+ f'time={ self ._i } : Broker canceled the order due to insufficient margin '
1007+ f'(equity={ self .equity :.2f} , margin_available={ self .margin_available :.2f} ).' ,
1008+ category = UserWarning )
10011009 self .orders .remove (order )
10021010 continue
10031011
@@ -1121,7 +1129,7 @@ class Backtest:
11211129
11221130 `cash` is the initial cash to start with.
11231131
1124- `spread` is the the constant bid-ask spread rate (relative to the price).
1132+ `spread` is the constant bid-ask spread rate (relative to the price).
11251133 E.g. set it to `0.0002` for commission-less forex
11261134 trading where the average spread is roughly 0.2‰ of the asking price.
11271135
@@ -1151,7 +1159,7 @@ class Backtest:
11511159
11521160 `margin` is the required margin (ratio) of a leveraged account.
11531161 No difference is made between initial and maintenance margins.
1154- To run the backtest using e.g. 50:1 leverge that your broker allows,
1162+ To run the backtest using e.g. 50:1 leverage that your broker allows,
11551163 set margin to `0.02` (1 / leverage).
11561164
11571165 If `trade_on_close` is `True`, market orders will be filled
0 commit comments