Navigation

    Backtrader Community

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

    hfrog713

    @hfrog713

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

    hfrog713 Unfollow Follow

    Latest posts made by hfrog713

    • RE: Correct way to use nested If statements on a SignalStrategy

      @hfrog713 said in Correct way to use nested If statements on a SignalStrategy:

      delta_under_flag = bt.If(delta_below_zero, 1, 0)
      hl2_under_flag = bt.If(delta_and_hl2_down, 1, 0)
      

      Seems to be working fine, i accidentally had 1 on both the buy and the sell signal.
      Now everything seems to be working well.
      Please let me know if there are any comments.

      posted in Indicators/Strategies/Analyzers
      hfrog713
      hfrog713
    • Correct way to use nested If statements on a SignalStrategy

      Hello Guys,

      Fairly new, trying to figure out the correct way to do nested if statements.
      I do the following but it seems like the function itself is showing up as opposed to the evaluated If return.
      Can someone please help?

      Thanks,
      Hernando

      class SMACloseSignalStrategy(bt.SignalStrategy):
      params = (('fastMA',22),('slowMA', 23),('macd1',7),('macd2',8),('macdsig',3),('period',30),)

      def log(self, txt, dt=None):
          '''Logging function for the strategy'''
          dt = dt or self.datas[0].datetime.date(0)
          print('%s, %s' % (dt.isoformat(), txt))
          
      
      def __init__(self):
          self.high = self.datas[0].high
          self.low = self.datas[0].low
          self.close = self.datas[0].close
          
          self.ema_slow = self.datas[0].ema_slow
          self.ema_fast = self.datas[0].ema_fast
          self.macd_delta = self.datas[0].macd_delta
          self.high_low2 = self.datas[0].high_low2
          
          close_over_emaS = self.close > self.ema_slow
          delta_over_zero = self.macd_delta > 0
          hl2_over_emaF = self.high_low2 > self.ema_fast
          
          close_below_emaS = self.close < self.ema_slow
          delta_below_zero = self.macd_delta < 0
          hl2_below_emaF = self.high_low2 < self.ema_slow
          
          
          delta_and_hl2_up = bt.And(delta_over_zero, hl2_over_emaF)
          delta_and_hl2_down = bt.And(delta_below_zero, hl2_below_emaF)
          
          delta_over_flag = bt.If(delta_over_zero, 1, 0)
          hl2_over_flag = bt.If(delta_and_hl2_up, 1, 0)
          
          delta_under_flag = bt.If(delta_below_zero, 1, 0)
          hl2_under_flag = bt.If(delta_and_hl2_down, 1, 0)
          
          #long_signal = bt.If(close_over_emaS, bt.If(delta_over_zero, 1, 0), bt.If(delta_and_hl2_up, 1, 0))
          #short_signal = bt.If(close_below_emaS, bt.If(delta_below_zero, 1, 0), bt.If(delta_and_hl2_down, 1, 0))
          
          long_signal = bt.If(close_over_emaS, delta_over_flag, hl2_over_flag)
          short_signal = bt.If(close_below_emaS, delta_under_flag, hl2_under_flag)
          
          #Another working example with 2 mil profit lol ....
          #long_signal = bt.If(close_over_emaS, 1, 0)
          #short_signal = bt.If(close_below_emaS, -1, 0)
          breakpoint()
          #Selling on SMA strategy......seems pretty profitable
          sma1, sma2 = bt.ind.SMA(period=self.p.fastMA), bt.ind.SMA(period=self.p.slowMA)        
          #self.signal_add(bt.SIGNAL_LONG, bt.ind.CrossOver(sma1,sma2))
          #self.signal_add(bt.SIGNAL_SHORT, bt.ind.CrossOver(sma2,sma1))
          self.signal_add(bt.SIGNAL_LONG, long_signal)
          self.signal_add(bt.SIGNAL_SHORT, short_signal)
      
      posted in Indicators/Strategies/Analyzers
      hfrog713
      hfrog713
    • RE: Converting a Tradingview Strategy to a Backtrader Strategy - EMA Crossover

      I guess the crux of the question is.......

      I have some logic in tradingview....

      //@version=3
      strategy(title = "test", overlay=true, initial_capital = 10000, pyramiding = 0, commission_type = strategy.commission.percent, commission_value = 0.0, calc_on_order_fills = false, calc_on_every_tick = false, default_qty_type = strategy.percent_of_equity, default_qty_value = 100, currency = currency.USD)

      fastMA = ema(close, 22)
      slowMA = ema(close, 23)
      
      buyCondition = crossover(fastMA, slowMA)
      closeCondition = crossunder(fastMA, slowMA)
      
      if buyCondition
          strategy.entry("MA Cross - Long", strategy.long)
      
      strategy.close("MA Cross - Long", closeCondition)
      

      How do i convert that to logic in backtrader.......

      I thought the following, but i end up with different results.

      class LongCloseLarpStrat(bt.Strategy):
      
          params = (('fastMA',22),('slowMA', 23))
      
          
      
          def log(self, txt, dt=None):
      
              ''' Logging function for this strategy'''
      
              dt = dt or self.datas[0].datetime.datetime(0)
      
              print('%s, %s' % (dt.isoformat(), txt))
      
              
      
              
      
          def __init__(self):
      
              self.livetrades = {}
      
              self.counter = 0
      
              
      
              self.fastMA = bt.indicators.ExponentialMovingAverage(period=self.p.fastMA)
      
              self.slowMA = bt.indicators.ExponentialMovingAverage(period=self.p.slowMA)
      
              self.crossover = bt.indicators.CrossOver(self.fastMA, self.slowMA) 
      
                
      
          def notify_order(self, order):
      
              if order.status in [order.Submitted, order.Accepted, order.Partial]:# Buy/Sell order submitted/accepted to/by broker/partially filled - Nothing to do
      
                  return
      
      
      
              # Check if an order has been completed
      
              if order.status in [order.Completed]:
      
                  if order.isbuy():
      
                      self.log('BUY EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f, tradeID: %d' %(order.executed.price, order.executed.value, order.executed.comm, order.tradeid))
      
                  elif order.issell():
      
                      self.log('SELL EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f, tradeID: %d' %(order.executed.price, order.executed.value, order.executed.comm, order.tradeid))
      
      
      
              elif order.status in [order.Canceled, order.Margin, order.Rejected]:
      
                  self.log('Order Canceled/Margin/Rejected')
      
      
      
          def notify_trade(self, trade):
      
              if trade.justopened:
      
                  self.log('New trade just opened with id %d'%(trade.tradeid))
      
                  self.livetrades[trade.tradeid] = trade
      
              elif trade.isclosed:
      
                  self.log('A trade just closed with id %d'%(trade.tradeid))
      
                  self.livetrades.pop(trade.tradeid)
      
              else:
      
                  self.log('Trade id %d updated'%(trade.tradeid))
      
                  
      
          def next(self):
      
              if self.position.size:
      
                  if self.crossover == -1:
      
                      self.sell()
      
              elif not self.position.size:
      
                  if self.crossover == 1:
      
                      self.buy()
      

      Can someone help me out here?

      Thanks in advance,
      Hernando

      posted in Indicators/Strategies/Analyzers
      hfrog713
      hfrog713
    • RE: Converting a Tradingview Strategy to a Backtrader Strategy - EMA Crossover

      @run-out tradingview_trades.png

      posted in Indicators/Strategies/Analyzers
      hfrog713
      hfrog713
    • RE: Converting a Tradingview Strategy to a Backtrader Strategy - EMA Crossover

      @run-out Hi Sorry, i am not getting an error......the problem is the number of trades, trade prices, and times of trades don't match at all with what i am seeing in the tradingview strategy. I have confirmed that the data looks the same in the dataframe as the data i am using in tradingview.

      I can upload samples of the data if required.
      The results i get from backtrader is the following.

      Trade Analysis Results:
      Total Open Total Closed Total Won Total Lost
      0 62 8 54
      Strike Rate Win Streak Losing Streak PnL Net
      12.9 2 11 -96628.15
      Final Portfolio Value: $3371.849999999994

      The results i get from TradingView are attached as a picture.

      Please let me know if you need anything else.
      I believe I am just trying to get a simple EMA crossover to buy and sell on positive and negative crossover. You can see what i am trying to do directly in the PineScript.

      Thanks in advance for your help.

      posted in Indicators/Strategies/Analyzers
      hfrog713
      hfrog713
    • Converting a Tradingview Strategy to a Backtrader Strategy - EMA Crossover

      Hi Guys,

      I need help with converting a tradingview strategy over into backtrader. I have been working on this for a couple of months and can't seem to get the numbers to matchup. We are getting the data from the Bybit API and loading into a pandas dataframe. We then use backtrader to load the dataframe into Cerebro.

      Please see below for the BackTrader Strategy and Pandas Data.

      class LongCloseLarpStrat(bt.Strategy):
          params = (('fastMA',22),('slowMA', 23))
          
          def log(self, txt, dt=None):
              ''' Logging function for this strategy'''
              dt = dt or self.datas[0].datetime.datetime(0)
              print('%s, %s' % (dt.isoformat(), txt))
              
              
          def __init__(self):
              self.livetrades = {}
              self.counter = 0
              
              self.fastMA = bt.indicators.ExponentialMovingAverage(period=self.p.fastMA)
              self.slowMA = bt.indicators.ExponentialMovingAverage(period=self.p.slowMA)
              self.crossover = bt.indicators.CrossOver(self.fastMA, self.slowMA) 
                
          def notify_order(self, order):
              if order.status in [order.Submitted, order.Accepted, order.Partial]:# Buy/Sell order submitted/accepted to/by broker/partially filled - Nothing to do
                  return
      
              # Check if an order has been completed
              if order.status in [order.Completed]:
                  if order.isbuy():
                      self.log('BUY EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f, tradeID: %d' %(order.executed.price, order.executed.value, order.executed.comm, order.tradeid))
                  elif order.issell():
                      self.log('SELL EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f, tradeID: %d' %(order.executed.price, order.executed.value, order.executed.comm, order.tradeid))
      
              elif order.status in [order.Canceled, order.Margin, order.Rejected]:
                  self.log('Order Canceled/Margin/Rejected')
      
          def notify_trade(self, trade):
              if trade.justopened:
                  self.log('New trade just opened with id %d'%(trade.tradeid))
                  self.livetrades[trade.tradeid] = trade
              elif trade.isclosed:
                  self.log('A trade just closed with id %d'%(trade.tradeid))
                  self.livetrades.pop(trade.tradeid)
              else:
                  self.log('Trade id %d updated'%(trade.tradeid))
                  
          def next(self):
              if self.position.size:
                  if self.crossover < 0:
                      self.sell()
              elif self.crossover > 0:
                  self.buy()
      

      Pandas Data

      class PandasData(bt.feeds.PandasData):
          lines = ('turnover','high_low2', 'ema_slow', 'ema_fast', 'macd_delta')
          params = (
              ('datetime', None),
              ('open','Open'),
              ('high','High'),
              ('low','Low'),
              ('close','Close'),
              ('volume','Volume'),
              ('openinterest', None),
              ('turnover','Turnover'),        
              ('high_low2','high_low2'), 
              ('ema_slow', 'ema_slow'),
              ('ema_fast', 'ema_fast'),
              ('macd_delta', 'macd_delta')
          )
      

      Please see below for the Pinescript Code.

      //@version=3
      strategy(title = "test", overlay=true, initial_capital = 10000, pyramiding = 0, commission_type = strategy.commission.percent, commission_value = 0.0, calc_on_order_fills = false, calc_on_every_tick = false, default_qty_type = strategy.percent_of_equity, default_qty_value = 100, currency = currency.USD)
      
      fastMA = ema(close, 22)
      slowMA = ema(close, 23)
      
      plot(fastMA, color = red, linewidth = 1, title = "Fast MA")
      plot(slowMA, color = blue, linewidth = 1, title = "Slow MA")
      
      buyCondition = crossover(fastMA, slowMA)
      closeCondition = crossunder(fastMA, slowMA)
      
      strategy.entry("MA Cross - Long", strategy.long)
      strategy.close("MA Cross - Long", closeCondition)
      

      I apologize if I did not ask this question in the correct manner.
      Please let me know if there is any additional questions or anything I can add.

      Here is a link to the tradingview ticker.

      https://www.tradingview.com/symbols/BTCUSD/?exchange=BYBIT

      We are working on the 3 hour timeframe.
      Also, here is the code for getting the data from bybit.

      def get_historical_klines_pd(client, symbol, interval, start_str, end_str=None):
          """Get Historical Klines from Bybit 
          See dateparse docs for valid start and end string formats 
          http://dateparser.readthedocs.io/en/latest/
          If using offset strings for dates add "UTC" to date string 
          e.g. "now UTC", "11 hours ago UTC"
          :param symbol: Name of symbol pair -- BTCUSD, ETCUSD, EOSUSD, XRPUSD 
          :type symbol: str
          :param interval: Bybit Kline interval -- 1 3 5 15 30 60 120 240 360 720 "D" "M" "W" "Y"
          :type interval: str
          :param start_str: Start date string in UTC format
          :type start_str: str
          :param end_str: optional - end date string in UTC format
          :type end_str: str
          :return: list of OHLCV values
          """
      
          # set parameters for kline() 
          interval = int(interval)
          timeframe = str(interval)
          limit    = 200
          start_ts = int(date_to_milliseconds(start_str)/1000)
          end_ts = None
          if end_str:
              end_ts = int(date_to_milliseconds(end_str)/1000)
          else: 
              end_ts = int(date_to_milliseconds('now')/1000)
      
      
          # init our list
          output_data = []
      
          # loop counter 
          idx = 0
          # it can be difficult to know when a symbol was listed on Binance so allow start time to be before list date
          symbol_existed = False
          while True:
              # fetch the klines from start_ts up to max 200 entries 
              temp_tuple = client.Kline.Kline_get(symbol=symbol, interval=timeframe, **{'from':start_ts}, limit=limit).result()        
              temp_dict = temp_tuple[0]
              # handle the case where our start date is before the symbol pair listed on Binance
              if not symbol_existed and len(temp_dict):
                  symbol_existed = True
      
              if symbol_existed:
                  # extract data and convert to list 
                  temp_data = [list(i.values()) for i in temp_dict['result']]
                  # append this loops data to our output data
                  output_data += temp_data
      
                  # update our start timestamp using the last value in the array and add the interval timeframe
                  # NOTE: current implementation does not support inteval of D/W/M/Y
                  start_ts = temp_data[len(temp_data) - 1][2] + interval*60
      
              else:
                  # it wasn't listed yet, increment our start date
                  start_ts += timeframe
      
              idx += 1
              # check if we received less than the required limit and exit the loop
              if len(temp_data) < limit:
                  # exit the while loop
                  break
      
              # sleep after every 3rd call to be kind to the API
              if idx % 3 == 0:
                  time.sleep(0.2)
      
          # convert to data frame 
          df = pd.DataFrame(output_data, columns=['Symbol', 'Interval', 'TimeStamp', 'Open', 'High', 'Low', 'Close', 'Volume', 'Turnover'])
          df['Date'] = [datetime.fromtimestamp(i).strftime('%Y-%m-%d %H:%M:%S.%d')[:-3] for i in df['TimeStamp']]
      
          return df
      

      Thanks,
      Hernando

      posted in Indicators/Strategies/Analyzers
      hfrog713
      hfrog713