Navigation

    Backtrader Community

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

    ZooM

    @ZooM

    0
    Reputation
    10
    Profile views
    6
    Posts
    0
    Followers
    0
    Following
    Joined Last Online

    ZooM Unfollow Follow

    Latest posts made by ZooM

    • Custom “recursive” indicator

      class Butterword(bt.Indicator):

      lines = ('Filter',)
      params = (('period', None),)
      #plotinfo = {"subplot":True} 
      
      def __init__(self, data):
          self.DataClose = data.close
          self.i = 0
         
      def next(self):
          a = math.exp (-1.414 * 3.1459/self.Period)
          b = 2*a*math.cos(1.414*180/self.Period)
          self.lines.Filter[0] = b * self.lines.Filter[-1] - a*a*self.lines.Filter[-2] + ((1-b+a*a)/4)*((self.DataClose[0] + 2*self.DataClose[-1] + self.DataClose[-2])) 
      

      I can't understand how to do this indicator. I saw EMA indicator, but I can't. Can you help me?

      posted in Indicators/Strategies/Analyzers
      Z
      ZooM
    • RE: How strategy works?

      @vladisld
      if we use this, we solve the data sync problem and we don't have data duplication.

      if self.datas[0].datetime[0] == self.datas[1].datetime[0]

      posted in General Code/Help
      Z
      ZooM
    • RE: How strategy works?

      @vladisld
      thanks for the answer.

      How would you do filtering? How would you make your trading system more optimal?

      posted in General Code/Help
      Z
      ZooM
    • RE: How strategy works?

      @vladisld
      thanks for the answer.

      My program is printing Position, DataClose SBER, Have Position, Position GAZP. Why is data0 printed three times? Each strategy has a filter for input data. That is, if data0, data1, data 2 enters the Trend_Pull_Back_SBER strategy, only data with data0 should be printed, the same with the Trend_Hilbert_GAZP and Trend_Hilbert_GOLD strategies.
      I understand it should be like this, the Trend_Pull_Back_SBER strategy is called three times with data data0, data1, data 2, but the data should be printed once.

      You could show an example of the optimal implementation of the strategy you are talking about.

      posted in General Code/Help
      Z
      ZooM
    • How strategy works?

      I Have a code

      from datetime import datetime
      import backtrader as bt
      from BackTraderQuik.QKStore import QKStore
      from BackTraderQuik.QKData import QKData
      import talib

      class Trend_Pull_Back_SBER(bt.Strategy):

      params = (
          ('period', 230),
          ('PullBack', 4),
          ('ticker_id', 'SPBFUT.SRZ1')
      )
      
      def log(self, txt, dt=None):
          """Вывод строки с датой на консоль"""
          dt = bt.num2date(self.datas[0].datetime[0]) if dt is None else dt # Заданная дата или дата текущего бара
          print(f'{dt.strftime("%d.%m.%Y %H:%M")}, {txt}')  # Выводим дату и время с заданным текстом на консоль
      
      
      def __init__(self):
          """Инициализация торговой системы"""
          self.DataClose = self.datas[0].close
          self.isLive = False  # Сначала будут приходить исторические данные
          self.order = None  # Заявка
      
      def next(self):
          """Получение следующего исторического/нового бара"""
          if not self.isLive:
              return
      
          if self.order and self.order.status == bt.Order.Submitted:  # Если заявка не исполнена (отправлена брокеру)
              return  # то выходим, дальше не продолжаем
      
          if self.params.ticker_id==self.datas[0]._dataname:
              
              self.log(f'Position = {self.getposition(data = self.datas[0])}')
              self.log(f'DataClose SBER = {self.DataClose[0]:.5f}')
      
      
              if not self.getposition(data = self.datas[0]):
                  self.log(f'NO Position')
      
              else:
                  self.log(f'Have Position')
                  
      
      def notify_data(self, data, status, *args, **kwargs):
          """Изменение статуса приходящих баров"""
          dataStatus = data._getstatusname(status)  # Получаем статус (только при LiveBars=True)
          print(dataStatus + ' 1')  # Не можем вывести в лог, т.к. первый статус DELAYED получаем до первого бара (и его даты)
          self.isLive = dataStatus == 'LIVE'
      
      def notify_order(self, order):
          """Изменение статуса заявки"""
          if order.status in [order.Submitted, order.Accepted]:  # Если заявка не исполнена (отправлена брокеру или принята брокером)
              self.log(f'Order Status: {order.getstatusname()}. TransId={order.ref}')
              return  # то выходим, дальше не продолжаем
      
          if order.status in [order.Canceled]:  # Если заявка отменена
              self.log(f'Order Status: {order.getstatusname()}. TransId={order.ref}')
              return  # то выходим, дальше не продолжаем
      
          if order.status in [order.Completed]:  # Если заявка исполнена
              if order.isbuy():  # Заявка на покупку
                  self.log(f'Bought @{order.executed.price:.2f}, Cost={order.executed.value:.2f}, Comm={order.executed.comm:.2f}')
              elif order.issell():  # Заявка на продажу
                  self.log(f'Sold @{order.executed.price:.2f}, Cost={order.executed.value:.2f}, Comm={order.executed.comm:.2f}')
          elif order.status in [order.Margin, order.Rejected]:  # Нет средств, или заявка отклонена брокером
              self.log(f'Order Status: {order.getstatusname()}. TransId={order.ref}')
          self.order = None  # Этой заявки больше нет
      
      def notify_trade(self, trade):
          """Изменение статуса позиции"""
          if not trade.isclosed:  # Если позиция не закрыта
              return  # то статус позиции не изменился, выходим, дальше не продолжаем
          self.log(f'Trade Profit, Gross={trade.pnl:.2f}, NET={trade.pnlcomm:.2f}')
      

      class Trend_Hilbert_GOLD(bt.Strategy):

      params = (  # Параметры торговой системы
          ('ticker_id', 'SPBFUT.GDZ1'),
      )
      
      def log(self, txt, dt=None):
          """Вывод строки с датой на консоль"""
          dt = bt.num2date(self.datas[2].datetime[0]) if dt is None else dt # Заданная дата или дата текущего бара
          print(f'{dt.strftime("%d.%m.%Y %H:%M")}, {txt}')  # Выводим дату и время с заданным текстом на консоль
      
      def __init__(self):
          """Инициализация торговой системы"""
          self.DataClose = self.datas[2].close
          self.isLive = False  # Сначала будут приходить исторические данные
          self.order = None  # Заявка
      
      def next(self):
          """Получение следующего исторического/нового бара"""
          if not self.isLive:
              return
      
          if self.order and self.order.status == bt.Order.Submitted:  # Если заявка не исполнена (отправлена брокеру)
              return  # то выходим, дальше не продолжаем
      
          if self.params.ticker_id==self.datas[2]._dataname:
      
              if not self.getposition(data = self.datas[2]):
          	pass
              else:
                  pass 
                
      
      def notify_data(self, data, status, *args, **kwargs):
          """Изменение статуса приходящих баров"""
          dataStatus = data._getstatusname(status)  # Получаем статус (только при LiveBars=True)
          print(dataStatus + ' 2')  # Не можем вывести в лог, т.к. первый статус DELAYED получаем до первого бара (и его даты)
          self.isLive = dataStatus == 'LIVE'
      
      def notify_order(self, order):
          """Изменение статуса заявки"""
          if order.status in [order.Submitted, order.Accepted]:  # Если заявка не исполнена (отправлена брокеру или принята брокером)
              self.log(f'Order Status: {order.getstatusname()}. TransId={order.ref}')
              return  # то выходим, дальше не продолжаем
      
          if order.status in [order.Canceled]:  # Если заявка отменена
              self.log(f'Order Status: {order.getstatusname()}. TransId={order.ref}')
              return  # то выходим, дальше не продолжаем
      
          if order.status in [order.Completed]:  # Если заявка исполнена
              if order.isbuy():  # Заявка на покупку
                  self.log(f'Bought @{order.executed.price:.2f}, Cost={order.executed.value:.2f}, Comm={order.executed.comm:.2f}')
              elif order.issell():  # Заявка на продажу
                  self.log(f'Sold @{order.executed.price:.2f}, Cost={order.executed.value:.2f}, Comm={order.executed.comm:.2f}')
          elif order.status in [order.Margin, order.Rejected]:  # Нет средств, или заявка отклонена брокером
              self.log(f'Order Status: {order.getstatusname()}. TransId={order.ref}')
          self.order = None  # Этой заявки больше нет
      
      def notify_trade(self, trade):
          """Изменение статуса позиции"""
          if not trade.isclosed:  # Если позиция не закрыта
              return  # то статус позиции не изменился, выходим, дальше не продолжаем
          self.log(f'Trade Profit, Gross={trade.pnl:.2f}, NET={trade.pnlcomm:.2f}')
      

      class Trend_Hilbert_GAZP(bt.Strategy):

      params = (  # Параметры торговой системы
          ('ticker_id', 'SPBFUT.GZZ1'),
      )
      
      def log(self, txt, dt=None):
          """Вывод строки с датой на консоль"""
          dt = bt.num2date(self.datas[3].datetime[0]) if dt is None else dt # Заданная дата или дата текущего бара
          print(f'{dt.strftime("%d.%m.%Y %H:%M")}, {txt}')  # Выводим дату и время с заданным текстом на консоль
      
      def __init__(self):
          """Инициализация торговой системы"""
          self.DataClose = self.datas[3].close
          self.isLive = False  # Сначала будут приходить исторические данные
          self.order = None  # Заявка
      
      
      def next(self):
          """Получение следующего исторического/нового бара"""
          if not self.isLive:
              return
      
          if self.order and self.order.status == bt.Order.Submitted:  # Если заявка не исполнена (отправлена брокеру)
              return  # то выходим, дальше не продолжаем
          
          if self.params.ticker_id==self.datas[3]._dataname:
      
          
              if not self.getposition(data = self.datas[3]):
                  self.log(f'NO Position GAZP')             
              else:
                  self.log(f'Position GAZP')
                
                      
      
      def notify_data(self, data, status, *args, **kwargs):
          """Изменение статуса приходящих баров"""
          dataStatus = data._getstatusname(status)  # Получаем статус (только при LiveBars=True)
          print(dataStatus + ' 3')  # Не можем вывести в лог, т.к. первый статус DELAYED получаем до первого бара (и его даты)
          self.isLive = dataStatus == 'LIVE'
      
      def notify_order(self, order):
          """Изменение статуса заявки"""
          if order.status in [order.Submitted, order.Accepted]:  # Если заявка не исполнена (отправлена брокеру или принята брокером)
              self.log(f'Order Status: {order.getstatusname()}. TransId={order.ref}')
              return  # то выходим, дальше не продолжаем
      
          if order.status in [order.Canceled]:  # Если заявка отменена
              self.log(f'Order Status: {order.getstatusname()}. TransId={order.ref}')
              return  # то выходим, дальше не продолжаем
      
          if order.status in [order.Completed]:  # Если заявка исполнена
              if order.isbuy():  # Заявка на покупку
                  self.log(f'Bought @{order.executed.price:.2f}, Cost={order.executed.value:.2f}, Comm={order.executed.comm:.2f}')
              elif order.issell():  # Заявка на продажу
                  self.log(f'Sold @{order.executed.price:.2f}, Cost={order.executed.value:.2f}, Comm={order.executed.comm:.2f}')
          elif order.status in [order.Margin, order.Rejected]:  # Нет средств, или заявка отклонена брокером
              self.log(f'Order Status: {order.getstatusname()}. TransId={order.ref}')
          self.order = None  # Этой заявки больше нет
      
      def notify_trade(self, trade):
          """Изменение статуса позиции"""
          if not trade.isclosed:  # Если позиция не закрыта
              return  # то статус позиции не изменился, выходим, дальше не продолжаем
          self.log(f'Trade Profit, Gross={trade.pnl:.2f}, NET={trade.pnlcomm:.2f}')
      

      if name == 'main': # Точка входа при запуске этого скрипта
      cerebro = bt.Cerebro() # Инициируем "движок" BackTrader

      symbol0 = 'SPBFUT.SRZ1' # 0 1-resampledata
      symbol2 = 'SPBFUT.GDZ1'
      symbol3 = 'SPBFUT.GZZ1'
      
      cerebro.addstrategy(Trend_Pull_Back_SBER, ticker_id ='SPBFUT.SRZ1')  # Добавляем торговую систему
      cerebro.addstrategy(Trend_Hilbert_GOLD, ticker_id ='SPBFUT.GDZ1')  # Добавляем торговую систему
      cerebro.addstrategy(Trend_Hilbert_GAZP, ticker_id ='SPBFUT.GZZ1')  # Добавляем торговую систему
      
      store = QKStore()  # Хранилище QUIK
      broker = store.getbroker(ClientCode = '', FirmId = ' ', TradeAccountId= ' ' )  # Брокер со счетом по умолчанию (срочный рынок РФ)
      
      cerebro.setbroker(broker)  # Устанавливаем брокера
      data0 = QKData(dataname=symbol0, timeframe=bt.TimeFrame.Minutes, compression=60, fromdate=datetime(2021, 5, 5, 19, 0), LiveBars=True)  # Исторические и новые минутные бары за все время
      cerebro.adddata(data0)  # Добавляем данные
      cerebro.resampledata(data0, timeframe = bt.TimeFrame.Days , compression = 1)
      data2 = QKData(dataname=symbol2, timeframe=bt.TimeFrame.Minutes, compression=60, fromdate=datetime(2021, 7, 5, 19, 0), LiveBars=True)  # Исторические и новые минутные бары за все время
      data3 = QKData(dataname=symbol3, timeframe=bt.TimeFrame.Minutes, compression=60, fromdate=datetime(2021, 7, 5, 19, 0), LiveBars=True)  # Исторические и новые минутные бары за все время
      cerebro.adddata(data2)  # Добавляем данные
      cerebro.adddata(data3)  # Добавляем данные
      
      cerebro.run()  # Запуск торговой системы
      

      And the result

      DELAYED 1
      DELAYED 2
      DELAYED 3
      CONNECTED 1
      CONNECTED 2
      CONNECTED 3
      DELAYED 1
      DELAYED 2
      DELAYED 3
      CONNECTED 1
      CONNECTED 2
      CONNECTED 3
      DELAYED 1
      DELAYED 2
      DELAYED 3
      CONNECTED 1
      CONNECTED 2
      CONNECTED 3
      DISCONNECTED 1
      DISCONNECTED 2
      DISCONNECTED 3
      DISCONNECTED 1
      DISCONNECTED 2
      DISCONNECTED 3
      DISCONNECTED 1
      DISCONNECTED 2
      DISCONNECTED 3
      LIVE 1
      LIVE 2
      LIVE 3
      24.09.2021 16:00, Position = --- Position Begin

      • Size: 200
      • Price: 330.38
      • Price orig: 330.38
      • Closed: 0
      • Opened: 0
      • Adjbase: None
        --- Position End
        24.09.2021 16:00, DataClose SBER = 330.38000
        24.09.2021 16:00, Have Position
        24.09.2021 17:00, Position GAZP
        LIVE 1
        LIVE 2
        LIVE 3
        LIVE 1
        LIVE 2
        LIVE 3
        24.09.2021 17:00, Position = --- Position Begin
      • Size: 200
      • Price: 330.38
      • Price orig: 330.38
      • Closed: 0
      • Opened: 0
      • Adjbase: None
        --- Position End
        24.09.2021 17:00, DataClose SBER = 331.09000
        24.09.2021 17:00, Have Position
        24.09.2021 17:00, Position GAZP
        24.09.2021 17:00, Position = --- Position Begin
      • Size: 200
      • Price: 330.38
      • Price orig: 330.38
      • Closed: 0
      • Opened: 0
      • Adjbase: None
        --- Position End
        24.09.2021 17:00, DataClose SBER = 331.09000
        24.09.2021 17:00, Have Position
        24.09.2021 17:00, Position GAZP
        24.09.2021 18:00, Position = --- Position Begin
      • Size: 200
      • Price: 330.38
      • Price orig: 330.38
      • Closed: 0
      • Opened: 0
      • Adjbase: None
        --- Position End
        24.09.2021 18:00, DataClose SBER = 330.35000
        24.09.2021 18:00, Have Position
        24.09.2021 18:00, Position GAZP

      I removed some of the executable code in the next () construct. This is for simple.
      My question is:
      Why is the strategy executed 3 times? (I have a DELAYED take 1 2 3 3 times)
      How to correctly implement a strategy with trading multiple strategies?

      posted in General Code/Help
      Z
      ZooM
    • IB for live trading two tickers

      How can I use IB for live trading two tickers?
      (https://github.com/ultra1971/backtrader_ib_insync)

      for example:
      data0 = ibdata(dataname='EUR.USD-CASH-IDEALPRO', **datakwargs)
      data1 = ibdata(dataname='AAPL-STK-SMART-USD', **datakwargs)

      posted in General Discussion
      Z
      ZooM