Short order not triggering
-
I have a strategy that enters both long and short positions (one open position at a time) based on some conditions that are in my CSV.
The long positions are opening and closing without issue but the short positions are not.
I think there is an issue with the def next(self) method but I can't figure it out.
Can someone offer any advice?
import backtrader as bt
import datetimeclass PercentSizer(bt.Sizer):
params = (('percent', 0.05), ('leverage', 2.0))def _getsizing(self, comminfo, cash, data, isbuy): """Returns the proper sizing""" if isbuy: # Buying size = cash * self.params.leverage / data.close[0] * self.params.percent else: # Selling size = self.broker.getposition(data).size * self.params.percent return size
class CustomCSVData(bt.feeds.GenericCSVData):
# Add lines
lines = ('psar', 'trend', 'ma',)# Add parameters params = (('psar', 5), ('trend', 6), ('ma', 7)) # Specify the timeframe timeframe = bt.TimeFrame.Minutes
class MyStrategy(bt.Strategy):
def init(self):
self.datapsar = self.datas[0].psar
self.datatrend = self.datas[0].trend
self.datama = self.datas[0].ma
self.dataclose = self.datas[0].close
self.order = None # To keep track of pending orders
self.trade_count = 0 # To count number of trades
self.tradeid = 1 # Trade IDdef log(self, txt, dt=None): ''' Logging function for this strategy''' dt = dt or self.data.datetime.datetime(0) # Changed from .date to .datetime print(f'{dt.isoformat()}, {txt}') def notify_order(self, order): if order.status in [order.Submitted, order.Accepted]: return if order.status in [order.Completed]: if order.isbuy(): self.log('Trade ID: %d, BUY EXECUTED, Price: %.2f, Cost: %.2f, Size: %.2f' % (self.tradeid, order.executed.price, order.executed.value, order.executed.size)) else: self.log('Trade ID: %d, SELL EXECUTED, Price: %.2f, Cost: %.2f, Size: %.2f' % (self.tradeid, order.executed.price, order.executed.value, order.executed.size)) self.order = None # No pending orders elif order.status in [order.Canceled, order.Margin, order.Rejected]: self.log('Order Canceled/Margin/Rejected') self.order = None # No pending orders def notify_trade(self, trade): if trade.isclosed: self.trade_count += 1 self.log(f'Operation profit, gross {trade.pnl:.2f}, net {trade.pnlcomm:.2f}, Trade ID: {self.tradeid}') self.tradeid += 1 # Increment trade ID when trade is closed def next(self): if self.order: # If there is a pending order, don't place another one return if not self.position: # If we are not in the market self.log('datatrend: {}, dataclose: {}, datama: {}'.format(self.datatrend[0], self.dataclose[0], self.datama[0])) if self.datatrend[0] == 1 and self.dataclose[0] > self.datama[0]: # Long entry condition self.log('Long entry condition met') self.order = self.buy(exectype=bt.Order.Market) elif self.datatrend[0] == 2 and self.dataclose[0] < self.datama[0]: # Short entry condition self.log('Short entry condition met') self.order = self.sell(exectype=bt.Order.Market) else: # If we are already in the market if self.position.size > 0 and (self.datatrend[0] == 2 or self.dataclose[0] < self.datapsar[0]): # Long exit condition self.log('Long exit condition met') self.order = self.close(exectype=bt.Order.Market) elif self.position.size < 0 and (self.datatrend[0] == 1 or self.dataclose[0] > self.datapsar[0]): # Short exit condition self.log('Short exit condition met') self.order = self.close(exectype=bt.Order.Market)
if name == 'main':
cerebro = bt.Cerebro()
cerebro.addstrategy(MyStrategy)data = CustomCSVData( dataname='ETH.csv', nullvalue=0.0, dtformat=('%Y-%m-%dT%H:%M:%S'), datetime=0, high=2, low=3, open=1, close=4, volume=-1, openinterest=-1, timeframe=bt.TimeFrame.Minutes, compression=30 ) cerebro.adddata(data) cerebro.broker.setcash(10000.0) # cerebro.addsizer(bt.sizers.FixedSize, stake=10) cerebro.addsizer(PercentSizer, percent=0.05, leverage=10.0) # Use 10% of available cash cerebro.addwriter(bt.WriterFile, out='mylog.csv', csv=True) strats = cerebro.run() print(f"Final Portfolio Value: {cerebro.broker.getvalue()}") print(f"Number of trades: {strats[0].trade_count}")
-
I managed to fix this issue. My position size was trying to place a positive stake amount for a short trade and it needs to be a negative amount.