Navigation

    Backtrader Community

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

    t3chap

    @t3chap

    1
    Reputation
    99
    Profile views
    10
    Posts
    0
    Followers
    0
    Following
    Joined Last Online

    t3chap Unfollow Follow

    Best posts made by t3chap

    • RE: How to extract historical account value from backtrader or its results

      @run-out said in How to extract historical account value from backtrader or its results:

      Dictionary

      dictionary = results[0].analyzers.getbyname("cash_market").get_analysis()
      df = pd.DataFrame(dictionary).T
      df.columns = ["Date", "Cash", "Value"]
      

      It works, thank you so much.

      I guess the system double_unders can't be reached from outside of the object

      posted in Indicators/Strategies/Analyzers
      T
      t3chap

    Latest posts made by t3chap

    • reducing cash in the account seemingly not working

      I have a trading bot using Oanda that I'm trying to get working. Oanda for the pair that I'm considering using 50x leverage, and I want to reduce this to 5. The easiest way that I've though of is to reduce the cash available to the system to the actual trading results achievable on oanda will be simulated by backtrader. Essentially I want to remove cash from the broker and add it to the fund, making a backup account that is used to adjust the size of the actual account I'm using for trading calculations.

      As the first step to implementing this, I use the following code:

          def nextstart(self):
              des_leverage = 5
              act_leverage = 50
              starting_cash = self.broker.get_cash()
              use_cash = starting_cash * des_leverage / act_leverage
              adjustment = use_cash - starting_cash
              self.broker.add_cash(adjustment)
              current_cash = self.broker.get_cash()
              print('starting cash:$ {}' . format(starting_cash))
              print('desired cash due to leverage:$ {}' . format(use_cash))
              print('adjustment: $ {}' . format(adjustment))
              print('current cash: $ {}' . format(current_cash))
      

      The results are below. I haven't implemented the adding the subtracted money to the fund, but it doesn't look like my add_cash is working. Any ideas?

      starting cash:$ 1000.0
      desired cash due to leverage:$ 100.0
      adjustment: $ -900.0
      current cash: $ 1000.0
      

      Thanks.

      posted in General Code/Help
      T
      t3chap
    • Exiting trades due to margin closeout

      Am I correct in assuming that backtrader doesn't exit trades when a margin call would have happened? I have a system I'm testing in forex which can be highly leveraged but I want to use a lesser amount. I've set the leverage to 4 (from 50 that is available at many forex outlets) but I'm not able to see that any trades have been exited for a margin exceedance if the market goes against the trade and the account value falls below the required amount for leverage.

      It appears that new trades are rejected due to margin if there is insufficient money in the trading account, but I don't see where existing trades are exited due to margin.

      I haven't seen this explicitly stated in the documentation yet but I might have missed it.

      Thanks.

      posted in General Discussion
      T
      t3chap
    • RE: How to extract historical account value from backtrader or its results

      @run-out said in How to extract historical account value from backtrader or its results:

      Dictionary

      dictionary = results[0].analyzers.getbyname("cash_market").get_analysis()
      df = pd.DataFrame(dictionary).T
      df.columns = ["Date", "Cash", "Value"]
      

      It works, thank you so much.

      I guess the system double_unders can't be reached from outside of the object

      posted in Indicators/Strategies/Analyzers
      T
      t3chap
    • How to extract historical account value from backtrader or its results

      I know this should be fairly easy to do but I'm stumped. I want to get the account value by bar from a cerebro instance so I can do analysis on a spreadsheet.

      For some reason I can't seem to figure out how to make this happen. I have this observer:

      class AcctValue(bt.Observer):
          alias = ('Value',)
          lines = ('value',)
       
          plotinfo = {"plot": True, "subplot": True}
       
          def next(self):
              self.lines.value[0] = self._owner.broker.getvalue()    # Get today's account value (cash + stocks)
       
      

      which I call with this code block:

      # Create an instance of cerebro
      cerebro = bt.Cerebro()
      # Input a starting broker account value
      cerebro.broker.setcash(startcash)
      
      
      # Add our strategy
      cerebro.addstrategy(Boll)
      
      
       
      comminfo = forexSpreadCommisionScheme(spread = spread, leverage = leverage)
      comminfo.show_spread_leverage()
      cerebro.broker.addcommissioninfo(comminfo)
       
      # Add the data to Cerebro
      cerebro.adddata(data)
       
      # Add a sizer
      
      cerebro.addsizer(ForexSizer,risk_per_trade=.0025,ATR_mult=6)
      
      #cerebro.addobserver(OrderObserver) 
      cerebro.addobserver(AcctValue)
      cerebro.addobservermulti(bt.observers.BuySell, markersize=4.0)    # Plots up/down arrows
      
      
      # Add the analyzers we are interested in
      #cerebro.addanalyzer(bt.analyzers.GrossLeverage, _name="gl")
      cerebro.addanalyzer(bt.analyzers.TradeAnalyzer, _name="ta")
      cerebro.addanalyzer(bt.analyzers.SQN, _name="sqn")
      cerebro.addanalyzer(bt.analyzers.Returns, _name="ret")
      cerebro.addanalyzer(bt.analyzers.SharpeRatio, _name='mysharpe')
      cerebro.addanalyzer(bt.analyzers.AnnualReturn, _name='ann')
      cerebro.addanalyzer(bt.analyzers.DrawDown, _name='dd')   
      cerebro.addanalyzer(bt.analyzers.Transactions, _name = 'transactions')
      #cerebro.addanalyzer(AcctStats)
      
      # Run over everything
      strategies = cerebro.run()
      
      firstStrat = strategies[0]
      result=strategies[0]
      
       
      #Get final portfolio Value
      portvalue = cerebro.broker.getvalue()
      pnl = portvalue - startcash
       
      #Print out the final result
      print('Final Portfolio Value: ${}'.format(round(portvalue,2)))
      print('P/L: ${}'.format(round(pnl,2)))
      printSharpe(firstStrat.analyzers.mysharpe.get_analysis())
      printTradeAnalysis(firstStrat.analyzers.ta.get_analysis())
      printSQN(firstStrat.analyzers.sqn.get_analysis())
      printAnnualReturns(result.analyzers.ann.get_analysis())
      printReturns(result.analyzers.ret.get_analysis())
      printDD(result.analyzers.dd.get_analysis())
      

      using

      b= cerebro.Observer.AccountValue()
      b
      

      doesn't work.
      When I look at the vars(result) I see:
      <main.AcctValue at 0x7f931b97a610>
      but I don't know how to access this.

      Can anyone help me?

      posted in Indicators/Strategies/Analyzers
      T
      t3chap
    • RE: btoandav20 cancel all orders

      @run-out

      I tried that solution as well as various permutations of the docs. It seems like there is something different from the way bactrader works vs the btoandav20 works.

      I may just have to roll my own solutions for some of these, I'm not sure. I'm able to stream the data, enter new orders, but the cancel stuff I can't seem to do.

      posted in General Code/Help
      T
      t3chap
    • btoandav20 cancel all orders

      I'm trying to code something to test with OANDA. I want to ensure that any existing orders are closed before I begin.

      I'm working with btoandav20. I can't seem to find an example of canceling an order and my guesses aren't getting me anywhere.
      Thanks. Code follows.

      import backtrader as bt
      import btoandav20 as bto
      import json
      import datetime
      import math
      
      ''' Order info '''
      class TestStrategy(bt.Strategy):
      
          params = (
              ("period", 20),
              ("devfactor", 2.5),
              ("atr_length", 50),
              #("size", 9000),
              ("debug", False),
              ("verbose", False),
              ('atr_stop', 1),
              ('atr_profit', 2)        
              )
       
          
          
          def __init__(self):
              self.orders = None
              self.prev_size = 0
      
                          
      
          #Provides any notificaitons about the data.
          def notify_data(self, data, status, *args, **kwargs):
              #print('*' * 5, 'DATA NOTIF:', data._getstatusname(status), *args)
              pass
      
          def notify_store(self, msg, *args, **kwargs):
              #print('*' * 5, 'STORE NOTIF:', msg)
              pass
      
          def notify_order(self, order):
              if order.status in [order.Completed, order.Cancelled, order.Rejected]:
                  self.order = None
      
              print('-' * 50, 'ORDER BEGIN', datetime.datetime.now())
              print(order)
              print('-' * 50, 'ORDER END')        
              
      
          def notify_trade(self, trade):
              print('-' * 50, 'TRADE BEGIN', datetime.datetime.now())
              print(trade)
              print('-' * 50, 'TRADE END')        
              
              
              
              
          def next(self):
              print('trying to cancel orders')
              #orders = self.orders()
              #print(orders)
              
              for o in self.broker.orders:
                  print("order info:  {} " . format(o))
                  self.broker.cancel(o)
                  bt.Order.cancel(o)
                      
              #for o in bt.broker.orders:
              #    print('order info: {} ' .format(o))
                      
                      
              txt = list()
              #txt.append('Data0')
              #txt.append('%04d' % len(self.data0))
              dtfmt = '%Y-%m-%dT%H:%M:%S.%f'
              #txt.append('{:f}'.format(self.data.datetime[0]))
              txt.append('%s' % self.data.datetime.datetime(0).strftime(dtfmt))
              txt.append('{:f}'.format(self.data.open[0]))
              txt.append('{:f}'.format(self.data.high[0]))
              txt.append('{:f}'.format(self.data.low[0]))
              txt.append('{:f}'.format(self.data.close[0]))
              txt.append('{:6d}'.format(int(self.data.volume[0])))
              txt.append('{:d}'.format(int(self.data.openinterest[0])))
              #txt.append('{:f}'.format(self.atr[0]))
              print(', '.join(txt))
      
              if len(self.datas) > 1 and len(self.data1):
                  txt = list()
                  txt.append('Data1')
                  txt.append('%04d' % len(self.data1))
                  dtfmt = '%Y-%m-%dT%H:%M:%S.%f'
                  txt.append('{}'.format(self.data1.datetime[0]))
                  txt.append('%s' % self.data1.datetime.datetime(0).strftime(dtfmt))
                  txt.append('{}'.format(self.data1.open[0]))
                  txt.append('{}'.format(self.data1.high[0]))
                  txt.append('{}'.format(self.data1.low[0]))
                  txt.append('{}'.format(self.data1.close[0]))
                  txt.append('{}'.format(self.data1.volume[0]))
                  txt.append('{}'.format(self.data1.openinterest[0]))
                  txt.append('{}'.format(float('NaN')))
                  print(', '.join(txt))   
              
              
              
              
          def start(self):
              #if self.order:
              #    self.order.cancel()
      
              if self.data0.contractdetails is not None:
                  print('-- Contract Details:')
                  print(self.data0.contractdetails)
              print('Started')
              acc_cash = cerebro.broker.getcash()
              acc_val = cerebro.broker.getvalue()
              print('Account Cash = {}'.format(acc_cash))
              print('Account Value = {}'.format(acc_val))
              #orders = self.broker.get_orders_open()
              #if:
              #    self.cancel(self.order)
              #if orders:
              #    for order in orders:
              #        self.broker.cancel(order)        
      
      
              
              
      with open("config.json", "r") as file:
          config = json.load(file)
      
      storekwargs = dict(
          token=config["oanda"]["token"],
          account=config["oanda"]["account"],
          practice=config["oanda"]["practice"],
          #use_positions = True,
          #notif_transactions = True,
          stream_timeout=2,
          account_poll_freq = 1
      )
      
      store = bto.stores.OandaV20Store(**storekwargs)
      
      datakwargs = dict(
          timeframe=bt.TimeFrame.Minutes,
          compression=30,
          #tz='Europe/Berlin',
          tz = 'UTC',
          bidask = False,
          backfill=False,
          backfill_start=False,
      )
      data = store.getdata(dataname="EUR_USD", **datakwargs)
      #data.resample( 
      #    timeframe=bt.TimeFrame.Minutes, 
      #    compression=30)  # rightedge=True, boundoff=1), compression is the minutes or seconds
      cerebro = bt.Cerebro()
      cerebro.adddata(data)
      #broker = bto.brokers.OandaV20Broker()
      cerebro.setbroker(store.getbroker())
      cerebro.addstrategy(TestStrategy)
      cerebro.run()
      
      posted in General Code/Help
      T
      t3chap
    • RE: Having trouble with multi setup

      I feel like an idiot; I finally figured out that I wasn't passing data to the bt.indicators.ADX and ATR statements. Apparently the system uses the first data for any subsequent calls if you don't send it new data.

        self.adx[dat] = bt.indicators.ADX(dat, period = self.params.n, plot=True)
      self.atr[dat] = bt.indicators.ATR(dat, period = self.params.n, plot=True)
      

      Is the correct formulation of those two lines.

      posted in General Code/Help
      T
      t3chap
    • Having trouble with multi setup

      Re: how to test multi data

      I saw this in an old post and am trying to get it to work correctly.

      I'm trying to generate ADX and ATR values for my symbols. I create a list with the symbols in it.

      I don't have the whole thing built; I was trying to build step-by-step but I must be doing something wrong as the ADX and ATR seems to be calculated for the first symbol in the list . The data shows that it is different in the graph but the indicators don't for some reason.
      Can anyone point me in the right direction?

      import backtrader as bt
      import pandas as pd
      import barchart_data as bd
      
      class ADX_C(bt.Strategy):
          params = {"n": 25}
          def __init__(self):
              """initialize the strategy"""
              self.adx = dict()
              self.atr = dict()
              
              for dat in self.datas:      
                  self.adx[dat] = bt.indicators.ADX(period = self.params.n, plot=True)
                  self.atr[dat] = bt.indicators.ATR(period = self.params.n, plot=True)
      
      
      
      symbols=["ZROZ","XMPT"]
      min_per_bar=1440
      begin_date = '2019-01-01'
      end_date = '2020-06-11'
      
      cerebro = bt.Cerebro()
      
      for s in symbols:
          data = bd.BarchartData(s,min_per_bar).data_by_dates(begin_date,end_date)
          bt_data = bt.feeds.PandasData(dataname=data, name = s)
          cerebro.adddata(bt_data, name = s)
          
          
      cerebro.addstrategy(ADX_C)
      cerebro.run()
      cerebro.plot(iplot=True, volume=False, width=50, height=30, dpi=600)
      
      posted in General Code/Help
      T
      t3chap
    • How to build a sizer that can use some measure of volatility, like ATR, and the multiplier for the future to determine position sizing?

      The following is my attempt to make a custom position sizer based on ATR and the multiplier for the given future. I'm sure this is relatively easy but I seem to have hit a wall.

      I seem to have a position size of 0 for every trade.
      What am I getting wrong?

      Thanks.

      class comm_sizer(bt.Sizer):
          def __init__(self, atr):
              #self.atr_parameter= atr_parameter
              atr= self.atr
              risk_per_trade=5000
              atr_risk_per_trade=5
              
              sizing = math.floor((risk_per_trade/(mult*atr_risk_per_trade*atr)))
              
         # position = self.broker.getposition(data)
          
          def _getsizing(self,comminfo,cash,data,isbuy):
              
              return sizing
      
      posted in General Code/Help
      T
      t3chap
    • How to check for open orders by symbol, or how to cancel all orders for a given symbol/stock?

      I have a system where I enter a long position and simultaneously enter a protective stop. I have a separate exit that sometimes occurs. When this occurs, I'd like to be able to cancel the protective stop. I currently use more than one instrument, (currently looking at a basket of 5 stocks), so I'd like to either find a way to determine which orders are still open by symbol or cancel all open orders by symbol.
      After looking through the documentation I believe this should be possible but I can't seem to get it to work.
      Does anyone have any ideas?

      Thanks.

      posted in General Code/Help
      T
      t3chap