许多买单在回测中被取消,我找不到原因。查看 Writefile 日志,似乎购买订单是在第二天收盘时创建的。在大多数情况下,买入价在当天的范围内,但仍未执行。
我尝试了不同的资产、不同大小的数据源、不同的策略,但结果相同。
在 Jupyter 笔记本上运行。我包括代码和日志。
最后,我将 AllInSizerInt() 中的默认参数 ('100') 更改为低于 100 并且它起作用了。我真的不明白为什么,我以为sizer会从经纪人那里得到现金头寸并调整订单。
这是修复:
''''
python
#Add the sizer. We plan to go 'all in' every time
cerebro.addsizer(bt.sizers.AllInSizerInt, percents = 95)
''''
这是原始代码:
''''
python
#### Import databases
from datetime import datetime
import backtrader as bt
import backtrader.indicators as btind
abspath = '/mypath/'
logfile = 'abs_momentum.csv'
# Create a Strategy
class Abs_momentum(bt.Strategy):
alias = ('Abs_momentum',)
params = (
# period for momentum calculation
('lookback', 252),
('range', 100))
def __init__(self):
# keep track of close price in the series
self.data_close = self.datas[0].close
# keep track of pending orders/buy price/buy commission
self.order = None
self.price = None
self.comm = None
# add a momentum indicator
self.mom = btind.MomentumOsc(self.data_close, \
period = self.p.lookback, \
band = self.p.range)
self.buysig = self.mom
def log(self, txt, dt=None):
''' Logging function fot this strategy'''
dt = dt or self.datas[0].datetime.date(0)
print('%s, %s' % (dt.isoformat(), txt))
def notify_order(self, order):
if order.status in [order.Submitted, order.Accepted]:
# Buy/Sell order submitted/accepted to/by broker - Nothing to do
return
# Check if an order has been completed
# Attention: broker could reject order if not enough cash
if order.status in [order.Completed]:
if order.isbuy():
self.log(
'BUY EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f' %
(order.executed.price,
order.executed.value,
order.executed.comm))
self.buyprice = order.executed.price
self.buycomm = order.executed.comm
else: # Sell
self.log('SELL EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f' %
(order.executed.price,
order.executed.value,
order.executed.comm))
#self.bar_executed = len(self)
elif order.status in [order.Canceled, order.Margin, order.Rejected]:
self.log('Order Canceled/Margin/Rejected')
self.order = None
def notify_trade(self, trade):
if not trade.isclosed:
return
self.log('OPERATION PROFIT, GROSS %.2f, NET %.2f' %
(trade.pnl, trade.pnlcomm))
def next(self):
# do nothing if an order is pending
if self.order:
return
# check if there is already a position
if not self.position:
# buy condition
if self.buysig > 100:
self.log(f'BUY CREATED --- Price: {self.data_close[0]:.2f}')
self.order = self.buy(size = None)
else:
# sell condition
if self.buysig < 100:
self.log(f'SELL CREATED --- Price: {self.data_close[0]:.2f}')
self.order = self.sell(Size = None)
###
#### Download data from Yahoo Finance
data = bt.feeds.YahooFinanceData(dataname= 'SPY', \
fromdate=datetime(2018, 6, 15),\
todate=datetime(2021, 3, 17),\
reverse = False)
####
# create a Cerebro entity
cerebro = bt.Cerebro(stdstats = False)
### Set up the backtest
# Add the Data Feed to Cerebro
cerebro.adddata(data)
# Set our desired cash start
cerebro.broker.setcash(100000.0)
# Set the commission - 0.1% ... divide by 100 to remove the %
cerebro.broker.setcommission(commission=0.001)
#Add the sizer. We plan to go 'all in' every time
cerebro.addsizer(bt.sizers.AllInSizerInt)
#Add the strategy
cerebro.addstrategy(Abs_momentum)
#Add the observers to the plot
cerebro.addobserver(bt.observers.BuySell)
cerebro.addobserver(bt.observers.Value)
#Write to a csv file
cerebro.addwriter(bt.WriterFile, out = (abspath + logfile), csv=True,\ data(csv) = False)
# Print out the starting conditions
print('Starting Portfolio Value: %.2f' % cerebro.broker.getvalue())
# Run over everything
cerebro.run()
# Print out the final result
print('Final Portfolio Value: %.2f' % cerebro.broker.getvalue())
###
### Plot the results
cerebro.plot(iplot=True, volume=False)
###
''''
这是日志:
>Starting Portfolio Value: 100000.00
>2019-06-18, BUY CREATED --- Price: 282.95
>2019-06-19, Order Canceled/Margin/Rejected
>2019-06-19, BUY CREATED --- Price: 283.58
>2019-06-20, Order Canceled/Margin/Rejected
>2019-06-20, BUY CREATED --- Price: 286.29
>2019-06-21, Order Canceled/Margin/Rejected
>2019-06-21, BUY CREATED --- Price: 285.88
>2019-06-24, BUY EXECUTED, Price: 286.10, Cost: 99848.90, Comm 99.85
>2020-03-12, SELL CREATED --- Price: 243.56
>2020-03-13, SELL EXECUTED, Price: 258.27, Cost: 99848.90, Comm 90.14
>2020-03-13, OPERATION PROFIT, GROSS -9712.67, NET -9902.66
>2020-04-17, BUY CREATED --- Price: 283.04
>2020-04-20, BUY EXECUTED, Price: 279.06, Cost: 88741.08, Comm 88.74
>2020-04-20, SELL CREATED --- Price: 278.05
>2020-04-21, SELL EXECUTED, Price: 273.25, Cost: 88741.08, Comm 86.89
>2020-04-21, OPERATION PROFIT, GROSS -1847.58, NET -2023.21
>2020-04-29, BUY CREATED --- Price: 289.53
>2020-04-30, Order Canceled/Margin/Rejected
>2020-04-30, BUY CREATED --- Price: 286.83
>2020-05-01, Order Canceled/Margin/Rejected
>2020-05-06, BUY CREATED --- Price: 280.68
>2020-05-07, Order Canceled/Margin/Rejected
>2020-05-07, BUY CREATED --- Price: 284.07
>2020-05-08, Order Canceled/Margin/Rejected
>2020-05-08, BUY CREATED --- Price: 288.77
>2020-05-11, BUY EXECUTED, Price: 286.69, Cost: 87153.76, Comm 87.15
>Final Portfolio Value: 121189.86