Navigation

    Backtrader Community

    • Register
    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    1. Home
    2. jabbarabdullah
    3. Topics
    For code/output blocks: Use ``` (aka backtick or grave accent) in a single line before and after the block. See: http://commonmark.org/help/
    J
    • Profile
    • Following 0
    • Followers 0
    • Topics 3
    • Posts 8
    • Best 0
    • Groups 0

    Topics created by jabbarabdullah

    • J

      ZeroDivisionError not on RSI
      General Discussion • • jabbarabdullah

      6
      0
      Votes
      6
      Posts
      701
      Views

      vladisld

      Please create a regular PR in the main Backtrader GitHub repository: https://github.com/mementum/backtrader

      It would be great if the test could be provided validating the fix. Ideally the test should fail before and pass after applying the fix :-).

    • J

      Assigning independent value for multi assets
      General Discussion • • jabbarabdullah

      4
      0
      Votes
      4
      Posts
      462
      Views

      B

      Sincerely: you need to make up your mind as to what you want. What you post makes no sense. You probably have an idea about the direction in which you want to go.

      If your take-profit/stop-loss is based on the value increase/decrease of an asset you have acquired, record the initial value and exit when the value has gone beyond your limits.

    • J

      Multi Assets Multi Order Executions Problem
      General Discussion • • jabbarabdullah

      6
      0
      Votes
      6
      Posts
      771
      Views

      J

      @backtrader said in Multi Assets Multi Order Executions Problem:

      @jabbarabdullah said in Multi Assets Multi Order Executions Problem:

      Appreciate if you could explain further on what do you mean by 'NO'.

      You say the orders are getting executed twice and the answer is: NO

      @ab_trader said in Multi Assets Multi Order Executions Problem:

      You have two data feeds, you cycle thru them twice and print same info twice. Check if data name is same as order data name, then print.
      On the other side you don't need to go thru all data feeds. Just print order info.

      I quoted the code in notify_order where you do exactly what @ab_trader is telling you. You print the execution twice (which is not the same as two executions), because you loop through the datas in notify_order

      I see, got it. Removed the loop in notify_order and it worked. Thanks @backtrader and @ab_trader !

      Just one more thing. when I tried executing the code with different date which the take profit and stop loss in my code should work, the numbers went crazy and it did not really stop the trade as expected. It worked great for a single asset data feed code but when I change it to multi assets data feeds, it went haywire. What went wrong? The single data feed code for comparison as follows:

      from __future__ import (absolute_import, division, print_function, unicode_literals) import backtrader as bt import datetime as dt import pytz import math cn1='UUUU' cn2='VVVV' csh=100000 stdt=dt.datetime(2019,06,28,9,30) enddt=dt.datetime(2019,06,28,16,00) SL=0.01 TP=2*SL SU=0.005 SUpct=SU*100 prop=1 #proportion of portfolio batch=10 #rounding entrytime = dt.time(9,45) exittime = dt.time(15,55) stakesize=10 lwbnd=40 upbnd=85 commis=0.05 TPpct=TP*100 SLpct=SL*100 def rounddown(x): return int(math.floor(x / 1)) * 1 class IBCommission(bt.CommInfoBase): """A :class:`IBCommision` charges the way interactive brokers does. """ params = (('stocklike', True), ('commtype', bt.CommInfoBase.COMM_FIXED),) def _getcommission(self, size, price, pseudoexec): return self.p.commission class PropSizer(bt.Sizer): """A position sizer that will buy as many stocks as necessary for a certain proportion of the portfolio to be committed to the position, while allowing stocks to be bought in batches (say, 100)""" params = {"prop": prop, "batch": batch} def _getsizing(self, comminfo, cash, data, isbuy): """Returns the proper sizing""" if isbuy: # Buying target = csh * self.params.prop # Ideal total value of the position price = data.close[0] shares_ideal = target / price # How many shares are needed to get target batches = int(shares_ideal / self.params.batch) # How many batches is this trade? shares = batches * self.params.batch # The actual number of shares bought if shares * price > cash: return 0 # Not enough money for this trade else: return shares else: # Selling return self.broker.getposition(data).size # Clear the position class TestStrategy(bt.Strategy): data_live = False def notify_data(self, data, status, *args, **kwargs): print('*' * 5, 'DATA NOTIF:', data._getstatusname(status), *args) if status == data.LIVE: self.data_live = True def log(self, txt, dt=None, vlm=None): dt = dt or self.datas[0].datetime.datetime(0) vlm = vlm or self.data.volume[0] print('%s, %s, %s, Volume, %s' % (len(self), dt.isoformat(), txt, vlm)) def __init__(self): self.dataclose = self.datas[0].close self.order = None self.buyprice = None self.buycomm = None self.sma0 = bt.indicators.SimpleMovingAverage(self.datas[0], period=20) self.sma = bt.indicators.SimpleMovingAverage(self.datas[0], period=54) self.rsi = bt.indicators.RelativeStrengthIndex(period=14,safediv=True, upperband=upbnd,lowerband=lwbnd) def notify_order(self, order): if order.status in [order.Submitted, order.Accepted]: return self.last_executed_price = order.executed.price 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 self.last_executed_price = order.executed.price else: # Sell self.log('SELL EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f' % (order.executed.price, order.executed.value, order.executed.comm)) self.last_executed_price = order.executed.price self.bar_executed = len(self) elif order.status in [order.Canceled, order.Margin, order.Rejected]: self.log('Order Canceled/Margin/Rejected') # Write down: no pending order 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): pv = self.broker.get_value() self.stakes = abs(rounddown(pv/self.dataclose[0])) target = csh * prop # Ideal total value of the position price = self.data.close[0] shares_ideal = target / price # How many shares are needed to get target batches = int(shares_ideal / batch) # How many batches is this trade? shares = batches * batch if self.order: return if not self.position: if (pv >= csh*(1+TP)): return if (pv <= csh*(1-SL)): return if (self.data.datetime.time(0) >= exittime): return if ((self.rsi[0] <= lwbnd)and(pv > csh*(1-SL))and(self.data.datetime.time(0) >= entrytime)): print('rsi:', self.rsi[0]) print('pv: ', pv) self.log('BUY CREATE, %.2f, VLM BOUGHT: %.2f' % (self.dataclose[0], shares)) self.order = self.buy() else: if (self.dataclose[0] >= (self.last_executed_price*(1+SU))): print('rsi:', self.rsi[0]) print('pv: ', pv) self.log('SELL CREATE (>%.2fpct), %.2f, VLM BOUGHT: %.2f' % (SUpct, self.dataclose[0], self.position.size)) self.order = self.sell(exectype=bt.Order.Stop) else: if (self.rsi[0] >= upbnd): print('rsi:', self.rsi[0]) print('pv: ', pv) self.log('SELL CREATE (RSI>Upbnd), %.2f, VLM BOUGHT: %.2f' % (self.dataclose[0], self.position.size)) self.order = self.close() else: if (pv >= csh*(1+TP)): print('rsi:', self.rsi[0]) print('pv: ', pv) self.log('TAKE PROFIT VAL CREATE (>%.2fpct), %.2f, VLM BOUGHT: %.2f' % (TPpct, self.dataclose[0], self.position.size)) self.order = self.sell(exectype=bt.Order.StopLimit, price=self.dataclose[0]) else: if (pv <= csh*(1-SL)): print('rsi:', self.rsi[0]) print('pv: ', pv) self.log('STOPLOSS VAL CREATE (<%.2fpct), %.2f, VLM BOUGHT: %.2f' % (SLpct, self.dataclose[0], self.position.size)) self.order = self.sell(exectype=bt.Order.StopLimit, price=self.dataclose[0]) return else: if (self.data.datetime.time(0) >= exittime): print('rsi:', self.rsi[0]) print('pv: ', pv) self.log('EOD STOP, %.2f, VLM BOUGHT: %.2f' % (self.dataclose[0], self.position.size)) self.order = self.close(exectype=bt.Order.Stop) def runstrat(): # Get a pandas dataframe cerebro = bt.Cerebro() ibstore = bt.stores.IBStore(port=7497, host='127.0.0.1', clientId=12345) data0 = ibstore.getdata(dataname=cn1,fromdate=stdt, historical =True, useRTH=True, tz = pytz.timezone('US/Eastern'), todate=enddt, timeframe=bt.TimeFrame.Seconds, compression=15) cerebro.adddata(data0, name=cn1) data1 = ibstore.getdata(dataname=cn2,fromdate=stdt, historical =True, useRTH=True, tz = pytz.timezone('US/Eastern'), todate=enddt, timeframe=bt.TimeFrame.Seconds, compression=15) cerebro.adddata(data1, name=cn2) data1.plotinfo.plotmaster = data0 cerebro.broker.setcash(csh) comminfo = IBCommission(commission=commis) cerebro.broker.addcommissioninfo(comminfo) cerebro.addwriter(bt.WriterFile, csv=True, rounding=2, out="C:\\Users\\User\\Desktop\\Backtest Library\\TestResults.csv") start_value = cerebro.broker.getvalue() cerebro.addstrategy(TestStrategy) cerebro.addsizer(PropSizer) # Run over everything cerebro.run() # Plot the result cerebro.plot(volume=False) # Print out the starting conditions print(' ') print('--',cn1,'--') print('Start capital: %.2f' % start_value) # Print out the final result print('Final Portfolio Value: %.2f' % cerebro.broker.getvalue()) print('Final PnL Value: %.2f' % (cerebro.broker.getvalue()-start_value)) if __name__ == '__main__': runstrat()

      Appreciate your comment on this. Thanks!

    • 1 / 1