Backtrader Community

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

    Osofuego

    @Osofuego

    7
    Reputation
    691
    Profile views
    19
    Posts
    0
    Followers
    0
    Following
    Joined Last Online

    Osofuego Unfollow Follow

    Best posts made by Osofuego

    • RE: Tearsheets - QSTrader

      Thx @backtrader for the guidance.

      I have adapted the package monthly_returns to backtrader using backtraders TimeReturn to create a heatmap of monthly returns. Maybe this will help somebody.

      Do you know if pyfolio is going to be re-integrated in backtrader anytime soon? Thx for all your work!

      I have only included the relevant parts (imports, adding analyzer, and then the code i adapted).

      import matplotlib.pyplot as plt
      import seaborn as sns
      import collections
      import pandas as pd
      
      ......
      #add analyzer
      cerebro.addanalyzer(bt.analyzers.TimeReturn, _name='myreturntme',timeframe=bt.TimeFrame.Months)
      .....
      
      #Get analyzer analysis
      tmereturn = strat.analyzers.myreturntme.get_analysis()
      
      
      ....
      # empty list for datetime index
          lst_indx = []
          # empty list for monthly retuns
          lst_mnth_ret = []
      
          #iterate through returns
          for key, value in tmereturn.items():
              lst_indx.append(key)
              lst_mnth_ret.append(value)
      
      
          #Create dataframe for returns
          df_ret_mnth = pd.DataFrame(lst_mnth_ret, index=lst_indx)
          #Change label of column
          df_ret_mnth.columns = ['Returns']
          #multiply returns by 100 
          df_ret_mnth['Returns'] = df_ret_mnth['Returns'] *100
          #Add year month info
          df_ret_mnth['Year'] = df_ret_mnth.index.strftime('%Y')
          df_ret_mnth['Month'] = df_ret_mnth.index.strftime('%b')
          # make pivot table
          df_ret_mnth = df_ret_mnth.pivot('Year', 'Month', 'Returns').fillna(0)
          df_ret_mnth = df_ret_mnth[['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
                             'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']]
      
          #Get Plot size
          size = list(plt.gcf().get_size_inches())
          figsize = (size[0], size[0] // 2)
          plt.close()
          #Create subplot
          fig, ax = plt.subplots(figsize=figsize)
          #create heatmap
          ax = sns.heatmap(df_ret_mnth, ax=ax, annot=True,
                           annot_kws={"size": 10}, fmt="0.2f", linewidths=0.5,
                           square=False, cbar=True, cmap='RdYlGn')
          ax.set_title('Monthly Returns (%)', fontsize=12, color='black', fontweight="bold")
      
          fig.subplots_adjust(hspace=0)
          plt.yticks(rotation=0)
          plt.show()
          plt.close()
      

      Here is the result 0_1506527091752_Backtrader Heatmap.png

      posted in General Code/Help
      O
      Osofuego
    • Getting executed time - Float to Datetime

      Hi. I am trying to debug my execution times and am getting a weird float output when I use notify_order. I am trying to convert the float of 'order.executed.dt' to datetime to print a string.

      My question is how to convert this float to readable string, as i am getting weird errors. When I print the float as is I get '735480.4798611111' which equates to Sept 1970. The data I am using is 8/1/2014 10:31:00 AM.

      What am I doing wrong here?

      Here is the code

      
      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 enougth cash
              if order.status in [order.Completed]:
                  if order.isbuy():
                      self.log(
                          'BUY EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f, Datetime: %s' %
                          (order.executed.price,
                           order.executed.value,
                           order.executed.comm,
                          datetime.datetime.strftime(datetime.datetime.fromtimestamp(order.executed.dt),'%Y-%m-%d %H:%M:%S')))
      
      posted in General Discussion
      O
      Osofuego
    • Tearsheets - QSTrader

      Re: Getting to portfolio performance data.

      Since pyfolio is iffy with its tear sheets and QSTrader's tearsheet seems to be pretty nice, is there any update on this?

      I find tearsheets, esp monthly PnL's to be helpful. I am not that experienced but would gladly help either test or code some of this port unleass this is already done?

      posted in General Code/Help
      O
      Osofuego
    • RE: Getting executed time - Float to Datetime

      Solved. Thank you so much for the really quick reply!

      Here is the code for reference for anyone else.

      self.log('SELL EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f, Datetime: %s' %
                              (order.executed.price,
                               order.executed.value,
                               order.executed.comm,
                               bt.num2date(order.executed.dt)))
      
      
      posted in General Discussion
      O
      Osofuego

    Latest posts made by Osofuego

    • RE: Cancelling orders get UnboundLocal Error

      Ah. I was on the right track-ish. Got it solved, thanks for your guidance!

      For good order here is the code I used.

       def __init__(self):
              self.orderlst = []
      
      
      def notify_order(self, order):
      
      
              if order.status in [order.Submitted, order.Accepted]:
                  # Buy/Sell order submitted/accepted to/by broker - Nothing to do
                  #self.orderlst.extend(self.order.ref)
                  #print(order.ref)
                  pass
              if order.status in [order.Accepted]:
                  self.orderlst.append(order)
       def next(self):
            
             #exit position
             if tme == datetime.time(14, 59, 0):
                  if abs(self.position.size) > 0:
                      #if in position and none of the brackets have executed then cancel all 3 orders and close position
                      #after cancelling orders, make list empty
                      #this also makes sure no orders are outstanding
                      for ordnum in self.orderlst:
                          self.cancel(ordnum)
                      self.orderlst = []
                      print (self.orderlst)
                      print('Canceles done')
                      self.close(data)
      posted in General Code/Help
      O
      Osofuego
    • RE: Cancelling orders get UnboundLocal Error

      Thanks for the reply. I should of realized that.

      What would be the appropriate way to cancel all outstanding orders. I can only get the order numbers in Notify_Trade. Should I make a list and pass this list to the strategy section? Is there no cancel all?

      Thanks again!

      posted in General Code/Help
      O
      Osofuego
    • Cancelling orders get UnboundLocal Error

      I am putting bracket orders on a futures and if the stops or take profits aren't hit I want to close at the end of the day.

                  buytp = self.datas[0].close[0] + .5
                  sellstp = self.datas[0].close[0] + .5
                  selltp = self.datas[0].close[0] - .5
      
                  if self.datas[0].FX_Idx_Slope[0] >= 0:
                      #if element in rank (first in list = AD 2nd = BP etc) = 5 4 3 then sell currency otherwise do nothing
                      if ranks[0] == 4 or ranks[0] == 3 or ranks[0] == 2:
                          brackets = self.sell_bracket(limitprice=selltp, stopprice=sellstp)
      
                  if self.datas[0].FX_Idx_Slope[0] < 0:
                      # if element in rank (first in list = AD 2nd = BP etc) = 5 4 3 then sell currency otherwise do nothing
                      if ranks[0] == 4 or ranks[0] == 3 or ranks[0] == 2:
                          brackets = self.sell_bracket(limitprice=selltp, stopprice=sellstp)
      
              # close all at 4pm
              if self.datas[0].datetime.time(0) == datetime.time(15, 59, 0):
                  if abs(self.position.size) > 0:
                      self.close(data)
                      self.broker.cancel(brackets)
      

      I am getting the following error

        File "C:/Users/Dropbox/v1.py", line 309, in <module>
          results = cerebro.run()
        File "C:\Python27\lib\site-packages\backtrader\cerebro.py", line 1127, in run
          runstrat = self.runstrategies(iterstrat)
        File "C:\Python27\lib\site-packages\backtrader\cerebro.py", line 1290, in runstrategies
          self._runonce(runstrats)
        File "C:\Python27\lib\site-packages\backtrader\cerebro.py", line 1691, in _runonce
          strat._oncepost(dt0)
        File "C:\Python27\lib\site-packages\backtrader\strategy.py", line 287, in _oncepost
          self.next()
        File "C:/Users/Dropbox/All Devices/v1.py", line 208, in next
          self.broker.cancel(brackets)
      UnboundLocalError: local variable 'brackets' referenced before assignment
      

      I am missing something. I just don't know what. I am getting the first days orders off but the second day I am getting an error. Thanks for the help!

      2018-02-02, SELL EXECUTED, Price: 79.88, Cost: 2000.00, Comm 1.00, Datetime: 2018-02-02 08:01:00
      2018-02-02, BUY EXECUTED, Price: 79.37, Cost: 2000.00, Comm 1.00, Datetime: 2018-02-02 08:35:00
      2018-02-02, Order Canceled
      2018-02-02, OPERATION PROFIT, GROSS 510.00, NET 508.00
      2018-02-05, SELL EXECUTED, Price: 79.30, Cost: 2000.00, Comm 1.00, Datetime: 2018-02-05 08:01:00
      
      posted in General Code/Help
      O
      Osofuego
    • RE: Need guidance how to implement intraday pair trading strategy

      There are a few options.

      1. You can use backtrader to actually resample the data (example here: https://www.backtrader.com/docu/data-multitimeframe/data-multitimeframe.html)

      2. You can use a counter and resample every x amount of datapoints (ie. use the window of 5 min bars to get the ratio/std) https://backtest-rookies.com/2017/12/06/backtrader-data-replay/

      3. Can "cheat" by using formatting and backfilling daily information into a minute custom dataframe and then sampling this minute data. (pandas is best for this IMO)

      Not sure what a "ratio/std" means but if you provided a bit more information I am sure you would get a little more information.

      posted in General Discussion
      O
      Osofuego
    • Multiple Futures - Different Multipliers

      I am trying to backtest Silver vs Gold and have no issues getting the feeds to work but am having an issue with the multipliers.

      I use
      cerebro.broker.setcommission(commission=2.0, margin=2000.0, mult=100.0)

      But thats at the broker level.

      Gold's multiplier per contract is 100x contract and Silver's is 5000x contract, can I extend the setcomission to each specific datafeed?

      posted in General Code/Help
      O
      Osofuego
    • RE: Copyright Abuse?

      Also curious what is going on. I really like the platform and am really hoping this is not as serious as it seems.

      posted in General Discussion
      O
      Osofuego
    • RE: Extending Datafeeds GenericCSV Attribute Error

      I noticed the last line of my csv file had a formatted date that was an integer. I would check each line of your data first.

      posted in Indicators/Strategies/Analyzers
      O
      Osofuego
    • I am an idiot

      Re: Extending Datafeeds GenericCSV Attribute Error

      Thanks Admin! I am an idiot!

      posted in Indicators/Strategies/Analyzers
      O
      Osofuego
    • Extending Datafeeds GenericCSV Attribute Error

      I have looked at extending the GenericCSV and am trying to add an additional column (pe) like in the example and am getting the error

      AttributeError: 'Lines_LineSeries_DataSeries_OHLC_OHLCDateTime_Abst' object has no attribute 'pe'

      Hopefully i am doing something stupid but cannot seem to figure out why the GenericCSVpe isn't adding the pe parameter to the class?

      Here is my complete test code.

      from __future__ import (absolute_import, division, print_function,
                              unicode_literals)
      import backtrader as bt
      import pandas as pd
      from backtrader.feeds import GenericCSVData
      import backtrader.feeds as btfeeds
      import datetime as datetime
      import backtrader.indicators as btind
      import numpy as np
      
      from backtrader.feeds import GenericCSVData
      
      class GenericCSV_PE(GenericCSVData):
      
          # Add a 'pe' line to the inherited ones from the base class
          lines = ('pe',)
      
          # openinterest in GenericCSVData has index 7 ... add 1
          # add the parameter to the parameters inherited from the base class
          params = (('pe', 8),)
      
      class MyStrategy(bt.Strategy):
      
      
          def log(self, txt, dt=None):
              ''' Logging function for this strategy'''
              dt = self.datas[0].datetime.date(0)
              dt_time = self.datas[0].datetime.time(0)
              dt_weekday = datetime.datetime.weekday(dt)
              print('%s, %s' % (dt.isoformat(), txt))
      
      
          def __init__(self):
              # Keep a reference to the "close" line in the data[0] dataseries
              # init stop loss and take profit order variables
              self.sl_order, self.tp_order = None, None
              self.datavolume = self.datas[0].volume
              self.pe = self.datas[0].pe
      
      
          def next(self):
              if self.datavolume[0] / np.mean(self.datavolume.get(size=10, ago=-1)) >= 1.25:
                  self.buy()
                  print(self.pe[0])
      
      
      
      if __name__ == '__main__':
          # Create a cerebro entity
          cerebro = bt.Cerebro()
      
      
          data = btfeeds.GenericCSVData(
              dataname='C:\\Users\\oso\\Dropbox\\All Devices\\Datav1.csv',
      
              nullvalue=0.0,
      
              dtformat=('%m/%d/%Y'),
      
              datetime=0,
              time=-1,
              high=2,
              low=3,
              open=1,
              close=4,
              volume=5,
              openinterest=6
          )
      
          # Add the Data Feed to Cerebro
          cerebro.adddata(data)
      
          # Set our desired cash start
          cerebro.broker.setcash(100000.0)
      
          # Add a strategy
          cerebro.addstrategy(MyStrategy)
      
          # 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())
      
          cerebro.plot(style='bar')
      

      0_1507400960917_pe backtrader.PNG

      posted in Indicators/Strategies/Analyzers
      O
      Osofuego
    • MemoryError

      I am getting this weird error when running a backtest of minute data. There are 129k rows and it works fine for the most part until i start adding code for trailing stops and take profits and it runs out of memory.

      I have a pretty powerful

      Traceback (most recent call last):
        File "C:/Users/oso/Dropbox/All Devices/Backtest v1.1.py", line 328, in <module>
          cerebro.plot(style='bar')
        File "C:\Users\oso\AppData\Roaming\Python\Python27\site-packages\backtrader\cerebro.py", line 999, in plot
          start=start, end=end, use=use)
        File "C:\Users\oso\AppData\Roaming\Python\Python27\site-packages\backtrader\plot\plot.py", line 222, in plot
          self.plotdata(data, self.dplotsover[data])
        File "C:\Users\oso\AppData\Roaming\Python\Python27\site-packages\backtrader\plot\plot.py", line 725, in plotdata
          self.plotind(data, ind, subinds=self.dplotsover[ind], masterax=ax)
        File "C:\Users\oso\AppData\Roaming\Python\Python27\site-packages\backtrader\plot\plot.py", line 420, in plotind
          lplot = line.plotrange(self.pinf.xstart, self.pinf.xend)
        File "C:\Users\oso\AppData\Roaming\Python\Python27\site-packages\backtrader\linebuffer.py", line 332, in plotrange
          return self.array[start:end]
      MemoryError
      

      Here is the TP/SL code:

      if (str(dt) in lst_ext) and tme == datetime.time(12,00,0,0):
                          self.close()
                          self.broker.cancel(self.sl_order)
                          self.broker.cancel(self.tp_order)
      
      
                  else:
      
                      # set stop loss and take profit prices
                      # in case of trailing stops stop loss prices can be assigned based on current indicator value
                      #Price Stop
                      price_tp_long = self.position.price * 1.02
                      price_tp_short = self.position.price * 0.98
                      price_sl_long = .99
                      price_sl_short = 1.01
      
                      # cancel existing stop loss and take profit orders
                      if self.tp_order:
                          self.broker.cancel(self.tp_order)
      
                      #check & update stop loss order
                      sl_price = 0
                      # if price goes up and you are long move stop
                      if self.position.size > 0 and (self.dataclose[0] - self.dataclose[-1]) > 0: sl_price = price_sl_long * self.position.price
                      if self.position.size < 0 and (self.dataclose[0] - self.dataclose[-1]) < 0: sl_price = price_sl_short * self.position.price
      
                      if sl_price != 0:
                          self.broker.cancel(self.sl_order)
                          self.sl_order = self.order_target_value(target=0.0, exectype=bt.Order.Stop, price=sl_price)
      
      
                      # check & update take profit order
                      tp_price = 0.0
                      if self.position.size > 0 and price_tp_long != 0: tp_price = price_tp_long
                      if self.position.size < 0 and price_tp_short != 0: tp_price = price_tp_short
      
                      if tp_price != 0.0:
                          self.tp_order = self.order_target_value(target=0.0, exectype=bt.Order.Limit, price=tp_price)
      
      

      and my main

      if __name__ == '__main__':
          #Start the brain
          cerebro = bt.Cerebro()
          # Load Strat
          cerebro.addstrategy(Strat)
      
          #Start cash level
          cerebro.broker.setcash(10000.0)
      
          #Set multiplier and commish level
          cerebro.broker.setcommission(commission=0.79, margin=3000.0, mult=1000.0)
      
      
      
      
          #Get dataframe
          df = pd.DataFrame()
      
          #df = pd.DataFrame.from_csv('C:\\Users\\oso\\Dropbox\\Strats\\df.csv')
      
          data = bt.feeds.PandasData(dataname=df,timeframe=bt.TimeFrame.Minutes, compression=1)
      
          #Add Analyzers
      
          cerebro.addanalyzer(bt.analyzers.TradeAnalyzer, _name='tradeanalyizer')  # Analyzes individual trades
          cerebro.addanalyzer(bt.analyzers.SharpeRatio_A, _name='mysharpeA')  # Gets the annualized Sharpe ratio
          cerebro.addanalyzer(bt.analyzers.AnnualReturn, _name='myannualreturn')        # Annualized returns (does not work?)
          cerebro.addanalyzer(bt.analyzers.Returns, _name='myreturn')  # Returns
          cerebro.addanalyzer(bt.analyzers.DrawDown, _name='mydrawdown')  # Drawdown statistics
          cerebro.addanalyzer(bt.analyzers.VWR, _name='myvwr')  # Value at risk
          cerebro.addanalyzer(bt.analyzers.SharpeRatio, _name='mysharpe')  # Sharpe
          cerebro.addanalyzer(bt.analyzers.TimeDrawDown, _name='mydrawdowntime')
          cerebro.addanalyzer(bt.analyzers.SQN, _name='mysqn')
          cerebro.addanalyzer(bt.analyzers.Transactions, _name='trans')
          cerebro.addanalyzer(bt.analyzers.TimeReturn, _name='myreturntme',timeframe=bt.TimeFrame.Months)
      
          #Load data to brain
          cerebro.adddata(data)
      
          print('Starting Portfolio Value: %.2f' % cerebro.broker.getvalue())
      
          cerebro.addanalyzer(bt.analyzers.SharpeRatio, _name='mysharpe')
      
          results = cerebro.run()
      
      
      
          print('Final Portfolio Value: %.2f' % cerebro.broker.getvalue())
      
      
      
      
          cerebro.plot(style='bar')
      

      Any ideas how to solve?

      posted in Indicators/Strategies/Analyzers
      O
      Osofuego