For code/output blocks: Use ``` (aka backtick or grave accent) in a single line before and after the block. See: http://commonmark.org/help/

Importing Pandas Data in Minute Intervals



  • I am unable to get my strategy to recognize my minute data, although hourly works fine. It seems I need to switch the cerebro default from daily to minutes, but the code out found here to do that...

    cerebro.adddata(data, timeframe=bt.Timeframe.Minutes, compression=1)
    

    throws this error:

    Traceback (most recent call last):
     File "autotest2.py", line 196, in <module>
       main()
     File "autotest2.py", line 54, in main
       x = threading.Thread(target=runner(db1, df, interval), args=(index,))
     File "autotest2.py", line 103, in runner
       cerebro.adddata(data, timeframe=bt.Timeframe.Minutes, compression=1)
    AttributeError: module 'backtrader' has no attribute 'Timeframe'
    

    Has something changed in the current version? How do I utilize Pandas data in minutes properly so that cerebro recognizes and processes them correctly?



  • @krypterro
    The following code works, but still does not process buy/sell functions in the strategy. I am using the generic sma example strategy from Backtrader docs. Works on hourly data perfectly, but not per minute data, but now with no errors. I am pulling data from MySQL, into a Pandas DataFrame with the code below, and using bta-lib in Pandas before passing the DataFrame into cerebro. How do I get cerebro to work with minute data if not this way?

    from __future__ import (absolute_import, division, print_function,
                            unicode_literals)
    import random
    import datetime  # For datetime objects
    import os.path  # To manage paths
    import sys  # To find out the script name (in argv[0])
    import threading
    
    import pandas as pd
    import btalib
    from colorama import init
    from colorama import Fore, Back, Style
    from loguru import logger
    
    import backtrader as bt
    import backtrader.analyzers as btanalyzers
    import backtrader.feeds as btfeeds
    import backtrader.strategies as btstrats
    
    from DBA import Binance
    from DB import DB1
    from Strategy2 import MinStrategy
    from Toolbox import Hammers
    
    def main():
        go_time = datetime.datetime.now()
        init()
        db1 = DB1()
        os.system('clear')
        
        runs = 1
        interval = 'minutes'
        start_time = datetime.datetime.strptime('1 Aug 2020', '%d %b %Y')
        
        # period select
        print('retrieving data...')
        btc_list = Binance.get_btc_minutes_cut(db1, start_time)
        print('loading dataframe...')
        data_df = pd.DataFrame(btc_list)
        df = data_df.set_index('stamp')
        print('begining analysis...')
        print('--------------------')
        print(Fore.CYAN)
        # ---------------------
        
        threads = list()
        for index in range(runs):
            x = threading.Thread(target=runner(db1, df, interval), args=(index,))
            threads.append(x)
            x.start()
    
        for index, thread in enumerate(threads):
            thread.join()
        
        # ---------------------
        print(Style.RESET_ALL)
        print('BackTesting Complete')
        stop_time = datetime.datetime.now() - go_time
        run_time = stop_time.total_seconds()
        print('Toal Run Time:', run_time)
        avg_run = run_time / runs
        print('Average Run Time:', avg_run)
        
    def runner(db1, df, interval):
        start_time = df.index[0]
        end_time = df.index[-1]
        span_list = [1,2,4,6,15,60,120,240]
        in_data = {}
        in_data['strategy'] = 'btcemaroll'
        in_data['cash_in'] = 10000
        in_data['commission'] = .002
        in_data['span'] = random.choice(span_list)
        in_data['pip_value'] = 0.01
        in_data['range_under'] = random.randint(1, 2000)
        in_data['range_over'] = random.randint(2000, 3000)
        in_data['diff_under'] = random.randint(1, 100)
        in_data['diff_over'] = random.randint(100, 300)
        in_data['min_profit'] = .01 #random.randint(1, 50)
        
        # add bta-lib indicators
        #df['sma'] = btalib.sma(df.high, period=in_data['span']).df
        df['ema'] = btalib.ema(df.close, period=in_data['span']).df
    
        # Create a cerebro obj and populate
        cerebro = bt.Cerebro()
        #cerebro.addstrategy(MinStrategy, in_data)
        cerebro.addstrategy(MinStrategy, in_data)
    
        # ---------------
        # pandas data setup
        data = PandasData_Extend(dataname=df, timeframe=bt.TimeFrame.Minutes, compression = 1)
        cerebro.adddata(data)
        # ---------------
        
        cerebro.broker.setcash(in_data['cash_in'])
        cerebro.broker.setcommission(commission=in_data['commission'])
    
        # Analyzer
        cerebro.addanalyzer(btanalyzers.SharpeRatio, _name='out_sharpe')
        cerebro.addanalyzer(btanalyzers.DrawDown, _name='out_drawdown')
        #cerebro.addanalyzer(btanalyzers.AnnualReturn, _name='out_annual')
    
        # Add a FixedSize sizer according to the stake
        #cerebro.addsizer(bt.sizers.FixedSize, stake=10)
        
        print('Starting Portfolio Value: ', as_currency(cerebro.broker.getvalue()))
        print('Start Time:', start_time)
        print('End Time:', end_time)
        start_cap = cerebro.broker.getvalue()
        
        # Run over everything
        thestrats = cerebro.run()
        thestrat = thestrats[0]
    
        sharpe_data = dict(thestrat.analyzers.out_sharpe.get_analysis())
        sharpe_ratio = sharpe_data['sharperatio']
        drawdown_data = dict(thestrat.analyzers.out_drawdown.get_analysis())
        drawdown_data = drawdown_data['max']
        #annual_data = dict(thestrat.analyzers.out_annual.get_analysis())
    
        # format text
        drawdown_percentage = round(drawdown_data['drawdown'],2)
        drawdown_money = as_currency(drawdown_data['moneydown'])
        net_profit = (cerebro.broker.getvalue() - start_cap
                      ) / cerebro.broker.getvalue() * 100
        net_profit = round(net_profit, 2)
        final_total = as_currency(cerebro.broker.getvalue())
        
        # build dictionary for results db
        out_data = {}
        out_data['cash_in'] = final_total
        out_data['max_drawdown_hours'] = drawdown_data['len']
        out_data['max_drawdown_per'] = drawdown_percentage
        out_data['max_drawdown_money'] = round(drawdown_data['moneydown'],2)
        out_data['sharpe'] = sharpe_ratio
        out_data['cash_out'] = round(cerebro.broker.getvalue(),2)
        out_data['net_profit'] = net_profit
        
        # Print out the final result
        #Binance.add_backtest(db1, interval, start_time, end_time, in_data, out_data)
        print('Minimum Profit:', in_data['min_profit'], '%')
        print('Span:', in_data['span'], interval)
        print('Max Drawdown Length:', drawdown_data['len'], 'hours')
        print('Max Drawdown Percentage:', drawdown_percentage, '%')
        print('Max Drawdown Money:', drawdown_money)
        print('Sharpe Ratio:', sharpe_ratio)
        print('Final Portfolio Value: ', final_total)
        print('Net Profit: ', net_profit, '%')
        print('------------------------')
        
    def as_currency(amount):
        if amount >= 0:
            return '${:,.2f}'.format(amount)
        else:
            return '-${:,.2f}'.format(-amount)
    
    
    class PandasData_Extend(btfeeds.PandasData):
        lines = (('btc_id','btc_hour','volume','close_time','quote_av','trades','tb_base_av','tb_quote_av','ema'))
        params = (
            ('btc_id', -1),
            ('btc_hour', -1),
            ('volume', -1),
            ('close_time', -1),
            ('quote_av', -1),
            ('trades', -1),
            ('tb_base_av', -1),
            ('tb_quote_av', -1),
            ('ema', -1)
            )
    
    main()
    


});