@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()