| 61 | |
| 62 | |
| 63 | class BackTesting: |
| 64 | |
| 65 | def __init__( |
| 66 | self, |
| 67 | cash: float, |
| 68 | commission: float = 0.0004, |
| 69 | slippage_perc: float = 0.0001, |
| 70 | leverage: float = 10.0, |
| 71 | ) -> None: |
| 72 | |
| 73 | self.cerebro = bt.Cerebro() |
| 74 | |
| 75 | # 永续合约手续费与保证金 |
| 76 | comminfo = PerpCommission( |
| 77 | commission=commission, |
| 78 | margin=1.0 / leverage, |
| 79 | mult=1.0, |
| 80 | ) |
| 81 | self.cerebro.broker.addcommissioninfo(comminfo) |
| 82 | |
| 83 | # 滑点(双边) |
| 84 | self.cerebro.broker.set_slippage_perc(perc=slippage_perc) |
| 85 | |
| 86 | # 初始资金 |
| 87 | self.cerebro.broker.set_cash(cash) |
| 88 | |
| 89 | |
| 90 | self.cerebro.broker.set_shortcash(True) |
| 91 | |
| 92 | # 存储原始数据 |
| 93 | self.datas = pd.DataFrame() |
| 94 | |
| 95 | def load_data( |
| 96 | self, |
| 97 | data: pd.DataFrame, |
| 98 | start_dt: str = None, |
| 99 | end_dt: str = None, |
| 100 | datafeed_cls: bt.feeds.PandasData = None, |
| 101 | ) -> None: |
| 102 | |
| 103 | if start_dt is not None: |
| 104 | data = data.loc[pd.to_datetime(start_dt):] |
| 105 | |
| 106 | if end_dt is not None: |
| 107 | data = data.loc[:pd.to_datetime(end_dt)] |
| 108 | |
| 109 | if (start_dt is None) and (end_dt is None): |
| 110 | start_dt, end_dt = data.index.min(), data.index.max() |
| 111 | data = data.loc[start_dt:end_dt] |
| 112 | |
| 113 | self.datas = data |
| 114 | |
| 115 | logger.info("开始加载数据...") |
| 116 | |
| 117 | for code, df in track( |
| 118 | data.groupby("code"), |
| 119 | desc="数据加载到回测引擎..." |
| 120 | ): |
no outgoing calls