Navigation

    Backtrader Community

    • Register
    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    For code/output blocks: Use ``` (aka backtick or grave accent) in a single line before and after the block. See: http://commonmark.org/help/

    Simple Strategy - New to this

    General Code/Help
    1
    1
    167
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • K
      khaos last edited by

      Hey guys!

      I'm trying out my first code on Backtrader, been trading with algo for some time but never backtested! Wanted to find the best strategy to use Binance Futures Leverage and Coumpounding long-term to exponentially grow my account. I know it seems difficult, but I've had some succesfull strategies, just want to know how to test several of them!

      In order to do that, my objective for now is to compute a strategy and test it in several coins, it has dependencies on BTC fluctuation and will generate buy's of other coins. But first things come first, for now I want to do the following:

      • Buy when SMA fast (20) > SMA slow (50) and RSI < 30
      • Sell when profit is 0.6% OR loss is 0.2% (adding the comission of 0.06%)

      In my code the truth is that I'm not even being able to get the BUY going, I get the following:

      # 2021-07-07, BUY CREATE 0.084140
      # EXECUTED PRICE IS: 0.000000
      

      I guess the buy Market Order is not even buying, it just stays there

      I'll leave the code so that you guys can comment on it, If anyone is open to developing an idea with me let me know, I would love to share my insights on the crypto world.

      from datetime import datetime
      import os
      import matplotlib
      import threading
      
      import backtrader as bt
      import backtrader.feeds as btfeeds
      
      from binancedata import *
      
      # Overall account balance
      account_balance = 100
      
      # size of each trade in native currency
      # ie if backtesting on ETH, each trade will be 1ETH in size
      trade_size = 50
      
      # in %
      take_profit = 0.6
      stop_loss = 0.2
      # The difference betweent the current candle price compared to the previous one
      # If higher than 1% we will buy
      buy_trigger = 1
      
      # Get historical data and store filename
      # No need to run this if you already have historical data
      # Simply comment out and re-assign your filename to 'ETHUSDT_1 Jan 2021.csv' for example
      
      threads = []
      coins = get_coins()
      for coin in coins:
      
          t = threading.Thread(target=get_historical_data, args=(coin, '7 Jul 2021', Client.KLINE_INTERVAL_1MINUTE) ) #'get_historical_data('ETHUSDT', '1 Jan 2021', Client.KLINE_INTERVAL_1MINUTE)
          t.start()
          threads.append(t)
      
      
      [thread.join() for thread in threads]
      
      def get_all_filenames():
          for coin in coins:
              return [get_historical_data(coin, '7 Jul 2021', Client.KLINE_INTERVAL_1MINUTE) for coin in coins]
      
      
      # Create a Stratey
      class TestStrategy(bt.Strategy):
          # Moving average parameters
          params = (
              ('verbose', False),
              ('maperiod', 14),
              ('quantity', None),
              ('upper', 70),         # upper threshold
              ('lower', 30),         # lower threshold
              ('pfast', 20),
              ('pslow', 50)     # stop loss %
          )
      
      
          def log(self, txt, dt=None):
              ''' Logging function fot this strategy'''
              dt = dt or self.datas[0].datetime.date(0)
              print('%s, %s' % (dt.isoformat(), txt))
      
          def __init__(self):
              # Keep a reference to the "close" line in the data[0] dataseries
              self.dataclose = self.datas[0].close
      
              # To keep track of pending orders
              self.order = None
      
              self.slow_sma = bt.indicators.MovingAverageSimple(self.datas[0],
                                                                period=self.params.pslow)
              self.fast_sma = bt.indicators.MovingAverageSimple(self.datas[0],
                                                                period=self.params.pfast)
              #
              # bt.indicators.WeightedMovingAverage(self.datas[0], period=25,
              #                                     subplot=True)
              # bt.indicators.StochasticSlow(self.datas[0])
      
              # Add a MovingAverageSimple indicator
              self.rsi = bt.indicators.RSI_SMA(self.datas[0], period=self.params.maperiod)
              bt.indicators.MACDHisto(self.datas[0])
              rsi = bt.indicators.RSI(self.datas[0])
              # bt.indicators.SmoothedMovingAverage(rsi, period=10)
              # bt.indicators.ATR(self.datas[0], plot=False)
      
          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 enough cash
              if order.status in [order.Completed]:
                  if order.isbuy():
                      self.log('BUY EXECUTED, %.6f' % order.executed.price)
                  elif order.issell():
                      self.log('SELL EXECUTED, %.6f' % 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 next(self):
              # Simply log the closing price of the series from the reference
              self.log('Close, %.6f' % self.dataclose[0])
      
              # Check if an order is pending ... if yes, we cannot send a 2nd one
              if self.order:
                  return
      
              # Check if we are in the market
              if not self.position:
      
                  # Not yet ... we MIGHT BUY if ...
                  if self.fast_sma[0] > self.slow_sma[0] and self.rsi < self.params.lower:
                      self.log(f'BUY CREATE {self.dataclose[0]:6f}')
                      # Keep track of the created order to avoid a 2nd order
                      self.buy(size=trade_size, exectype=bt.Order.Market)
                      self.order = self.buy()
      
                      print(f'EXECUTED PRICE IS: %.6f' % self.order.executed.price)
      
      
      
      
              if self.position:
                  if self.dataclose[0] > self.position.price + (self.position.price*take_profit/100) or  self.dataclose[0] < self.position.price - (self.position.price*stop_loss/100):
      
                      #self.log('SELL CREATE, %.2f' % self.dataclose[0])
                      #self.sell(size=trade_size, exectype=bt.Order.Market)
                      #self.order = self.sell()
                      self.close()
                      self.order = self.close()
      
      def start_backtesting():
      
          historical_data = get_all_filenames()
          for coin in historical_data:
              # Create a cerebro entity
              cerebro = bt.Cerebro()
      
              # Add a strategy
              cerebro.addstrategy(TestStrategy)
      
              # load data from our CSV file
              data = btfeeds.GenericCSVData(
      
              # Create a Data Feed
              dataname=coin,
              fromdate=datetime(2021, 7, 7),
              todate=datetime(2021, 7, 8),
              nullvalue=0.0,
              dtformat=lambda x: datetime.utcfromtimestamp(float(x) / 1000.0),
              datetime=0,
              high=1,
              low=2,
              open=3,
              close=4,
              volume = -1,
              openinterest=-1
              )
      
              # Add the Data Feed to Cerebro
              cerebro.adddata(data)
      
              # Set our desired cash start
              cerebro.broker.setcash(account_balance)
      
              # Print out the starting conditions
              print('Starting Portfolio Value: %.2f' % cerebro.broker.getvalue())
      
              # Run over everything
              cerebro.run()
              cerebro.plot()
      
              # Print out the final result
              print('Final Portfolio Value: %.2f' % cerebro.broker.getvalue())
      
      
      start_backtesting()
      

      Thank you!

      1 Reply Last reply Reply Quote 0
      • 1 / 1
      • First post
        Last post
      Copyright © 2016, 2017, 2018, 2019, 2020, 2021 NodeBB Forums | Contributors