简体   繁体   English

在 backtrader 上运行回测,我收到了许多订单取消/保证金/拒绝,而他们不应该这样做

[英]Running backtest on backtrader I get many BUY ORDERS CANCELLED/MARGIN/REJECTED when they should not

Many buy orders are cancelled in the backtests and I cannot find why.许多买单在回测中被取消,我找不到原因。 Looking at the Writefile log it seems the buy orders are created at the next day's close.查看 Writefile 日志,似乎购买订单是在第二天收盘时创建的。 In most cases the buy price is in the day's range but still not executed.在大多数情况下,买入价在当天的范围内,但仍未执行。

I have tried on different assets, different sizes of the data feed, different strategies, with the same result.我尝试了不同的资产、不同大小的数据源、不同的策略,但结果相同。

Running on Jupyter notebook.在 Jupyter 笔记本上运行。 I include the code and the log.我包括代码和日志。

Finally I changed the default parameter ('100') in AllInSizerInt() below 100 and it worked.最后,我将 AllInSizerInt() 中的默认参数 ('100') 更改为低于 100 并且它起作用了。 I do not really understand why, I thought the sizer would get the cash position from the broker and adjust the order.我真的不明白为什么,我以为sizer会从经纪人那里得到现金position并调整订单。

Here is the fix:这是修复:

''''
python
#Add the sizer.  We plan to go 'all in' every time  
cerebro.addsizer(bt.sizers.AllInSizerInt, percents = 95)  

''''

And here is the original code:这是原始代码:

''''
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)
###

''''

Here is the log:这是日志:

>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

The reason your adjustment from 100% size trade to 95% size trade corrected the problem is that trying to by all in 100% on a portfolio will always result in some margins along the way.您从 100% 规模交易调整到 95% 规模交易纠正了问题的原因是,在投资组合中尝试全部 100% 总是会在此过程中产生一些利润。 This can be seen here in your logs:这可以在您的日志中看到:

>2019-06-19, Order Canceled/Margin/Rejected

The problem is you are calculating the number of shares to trade off the previous close.问题是您正在计算与前一收盘价交易的股票数量。 If the market price gaps up on the next bar, you won't have enough cash to buy.如果市场价格在下一根柱线上跳空,您将没有足够的现金购买。 There is an option called cheat-on-open that allows a peak at the next open price to permit sizing of the shares.有一种称为cheat-on-open的选项,它允许在下一个开盘价达到峰值以允许调整股票规模。 This helps.这有帮助。

But in reality, it's best to trade below 100%.但实际上,最好在 100% 以下进行交易。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在运行回测和购买时,我总是收到订单取消/保证金/拒绝 - when running backtest and buying I always get Order Canceled/Margin/Rejected 如何使用 backtrader 回测投资组合组合? - How to backtest portfolio compositions using backtrader? 在 zipline 上运行回测时如何解决 AssertionError - How to solve AssertionError when running backtest on zipline 策略买入并持有每月反向交易者 - Strategy Buy and Hold Monthly Backtrader 当多个条件等于 True(股票数据)时设置“买入”信号/回测的最佳方法 - Best way to setup 'Buy' signal/backtest when multiple conditions equal True (stock data) 重新运行单元格时,Jupiter笔记本中的BackTrader图形图消失 - BackTrader graph plots in Jupiter notebook disappear when re-running cell 运行 Cerebro 后,我在 backtrader 中的投资组合价值没有发生任何变化,我如何检查它是否正常工作 - After running Cerebro nothing is happening to my portfolio value in backtrader, how do i check if it is working or not 为什么我在运行这个程序时得到“ValueError: too many values to unpack”? - Why do I get “ValueError: too many values to unpack” when running this program? 如果ID之前取消订单,请填写True/False - Fill in True/False If ID Cancelled Orders Before 为什么backtrader在回测时没有显示时间? - Why does backtrader not display time when backtesting?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM