For code/output blocks: Use ``` (aka backtick or grave accent) in a single line before and after the block. See: http://commonmark.org/help/
Extending Pandas Columns
-
I have gone through every example I can find here and I can't seem to get past the below error. I am adding the lines and parameters, and I am initiating the column variable, what am I missing? I am just trying to get the extra columns into the data to make these vars available in the Strategy.
Traceback (most recent call last): File "backtest1.py", line 171, in <module> main() File "backtest1.py", line 93, in main thestrats = cerebro.run() File "/usr/lib/python3.8/site-packages/backtrader/cerebro.py", line 1127, in run runstrat = self.runstrategies(iterstrat) File "/usr/lib/python3.8/site-packages/backtrader/cerebro.py", line 1217, in runstrategies strat = stratcls(*sargs, **skwargs) File "/usr/lib/python3.8/site-packages/backtrader/metabase.py", line 88, in __call__ _obj, args, kwargs = cls.doinit(_obj, *args, **kwargs) File "/usr/lib/python3.8/site-packages/backtrader/metabase.py", line 78, in doinit _obj.__init__(*args, **kwargs) File "/home/krypterro/btcbot/Strategy.py", line 20, in __init__ self.order_act = self.datas[0].order_act File "/usr/lib/python3.8/site-packages/backtrader/lineseries.py", line 461, in __getattr__ return getattr(self.lines, name) AttributeError: 'Lines_LineSeries_DataSeries_OHLC_OHLCDateTime_Abst' object has no attribute 'order_act'
from __future__ import (absolute_import, division, print_function, unicode_literals) import datetime # For datetime objects import os.path # To manage paths import sys # To find out the script name (in argv[0]) import pandas as pd import btalib from tqdm import tqdm from colorama import init from colorama import Fore, Back, Style 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 Strategy import TestStrategy from Toolbox import Hammers init() db1 = DB1() os.system('clear') cash = 10000 def main(): cnt = 0 btc_list = Binance.get_btc_hours(db1) row_count = len(btc_list) new_list = [] print(Fore.GREEN) for i in tqdm (range (row_count), desc="Processing"): #for i in range(row_count): if i > 2: row_0_data = dict(btc_list[i]) back_1_data = dict(btc_list[i-1]) back_2_data = dict(btc_list[i-2]) # build indicators row_0_data['decline'] = back_1_data['high'] - row_0_data['low'] row_0_data['rally'] = row_0_data['high'] - back_1_data['low'] row_0_data['buy_high'] = Hammers.get_buy_high(row_0_data['high'], back_1_data['high']) row_0_data['buy_under'] = Hammers.get_buy_under(back_1_data['low'], row_0_data['low']) row_0_data['btc_mi'] = row_0_data['close'] - back_2_data['close'] row_0_data['btc_mt'] = Hammers.get_mt(row_0_data['btc_mi'], back_1_data['btc_mi'], back_2_data['btc_mi']) row_0_data['level'] = 0 row_0_data['level'] = Hammers.get_level(row_0_data, back_1_data) new_list.append(row_0_data) # setup order row_0_data['pip_value'] = Hammers.get_pip_value(row_0_data) order = Hammers.get_order(row_0_data, back_1_data) row_0_data['order_act'] = order['act'] try: row_0_data['order_target'] = round(order['target'],2) except: pass data_df = pd.DataFrame(new_list) data_df = data_df.set_index('stamp') data = bt.feeds.PandasData(dataname=data_df) #print(data_df.tail(10)) # Create a cerebro obj and populate cerebro = bt.Cerebro() #cerebro.addstrategy(btstrats.SMA_CrossOver) cerebro.addstrategy(TestStrategy) cerebro.adddata(data) cerebro.broker.setcash(cash) # Set the commission cerebro.broker.setcommission(commission=0.002) # 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 out the starting conditions print('Starting Portfolio Value: ', as_currency(cerebro.broker.getvalue())) start_cap = cerebro.broker.getvalue() print(Fore.CYAN) # 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 = int(drawdown_data['drawdown']) drawdown_percentage = str(drawdown_percentage) + '%' 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()) # Print out the final result print('Max Drawdown Length:', drawdown_data['len'], 'hours') print('Max Drawdown Percentage:', drawdown_data['drawdown']) print('Max Drawdown Money:', drawdown_money) print(Fore.GREEN) print('Sharpe Ratio:', sharpe_ratio) print('Final Portfolio Value: ', final_total) print('Net Profit: ', net_profit, '%') print(Style.RESET_ALL) print('BackTesting Complete') 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', 'symbol', 'open', 'high', 'low', 'close', 'range_usd', 'sma24', 'ema', 'volume_btc', 'volume_usd', 'decline', 'rally', 'buy_high', 'buy_under', 'btc_mi', 'btc_mt', 'level', 'pip_value', 'order_act', 'order_target') params = ( ('datetime', None), ('btc_id', 0), ('btc_hour', 1), ('symbol', 2), ('open', 3), ('high', 4), ('low', 5), ('close', 6), ('range_usd', 7), ('sma24', 8), ('ema', 9), ('volume_btc', 10), ('volume_usd', 11), ('decline', 12), ('rally', 13), ('buy_high', 14), ('buy_under', 15), ('btc_mi', 16), ('btc_mt', 17), ('level', 18), ('pip_value', 19), ('order_act', 20), ('order_target', 21) ) def print_full(x): pd.set_option('display.max_rows', len(x)) pd.set_option('display.max_columns', None) pd.set_option('display.width', 2000) pd.set_option('display.float_format', '{:20,.2f}'.format) pd.set_option('display.max_colwidth', None) print(x) pd.reset_option('display.max_rows') pd.reset_option('display.max_columns') pd.reset_option('display.width') pd.reset_option('display.float_format') pd.reset_option('display.max_colwidth') main()
import backtrader as bt from Toolbox import Hammers class TestStrategy(bt.Strategy): params = ( ('maperiod', 240), ('period', 10), ('onlydaily', False) ) 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): # custom vars self.order_act = self.datas[0].order_act # Keep a reference to the "close" line in the data[0] dataseries self.dataclose = self.datas[0].close # To keep track of pending orders and buy price/commission self.order = None self.buyprice = None self.buycomm = None # Add a MovingAverageSimple indicator self.sma = bt.indicators.SimpleMovingAverage( self.datas[0], period=self.params.maperiod) 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, Price: %.2f, Cost: %.2f, Comm %.2f' % (order.executed.price, order.executed.value, order.executed.comm)) self.buyprice = order.executed.price self.buycomm = order.executed.comm else: # Sell self.log('SELL EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f' % (order.executed.price, order.executed.value, order.executed.comm)) self.bar_executed = len(self) elif order.status in [order.Canceled, order.Margin, order.Rejected]: self.log('Order Canceled/Margin/Rejected') self.order = None def notify_trade(self, trade): if not trade.isclosed: return self.log('OPERATION PROFIT, GROSS %.2f, NET %.2f' % (trade.pnl, trade.pnlcomm)) def next(self): # Simply log the closing price of the series from the reference self.log('Close, %.2f' % 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.order_act == 'buy': # BUY, BUY, BUY!!! (with all possible default parameters) self.log('BUY CREATE, %.2f' % self.dataclose[0]) # Keep track of the created order to avoid a 2nd order self.order = self.buy() else: if self.order_act == 'sell': # SELL, SELL, SELL!!! (with all possible default parameters) self.log('SELL CREATE, %.2f' % self.dataclose[0]) # Keep track of the created order to avoid a 2nd order self.order = self.sell()
-
@krypterro
The solution to the above problem is
data = PandasData_Extend(dataname=data_df)
I was not extending the class properly.