My goal is to backtest data where you provide buy/sell dates and closing prices to backtest module in order to backtest data from one source csv (instead of having 3 separate files such as price data, buy signals and sell signals)
I am not sure why not all of the trades execute here. Currently, my trades are being capped at 5? unsure why I cant get more to execute.
Tried setting hedge to true, exclusive orders to false in order to allow for overlapping trades. I set up checking for dates to make sure they werent on holiday. I'm stuck here with trades being capped at 5.
import pandas as pdfrom backtesting import Backtest as OriginalBacktest, Strategyfrom io import StringIOimport numpy as npfrom pandas.tseries.holiday import USFederalHolidayCalendar# Updated CSV data as a string for buy/sell dates and closing pricescsv_data = """Buy Dates,Sell Dates,Buy Close,Sell Close2010-01-15,2010-03-20,120.45,130.232011-02-25,2011-05-10,125.67,135.892012-08-21,2013-07-22,130.54,140.672014-05-23,2014-08-28,135.78,145.342015-09-10,2016-01-12,140.23,150.562017-02-15,2017-06-18,145.45,155.782013-04-18,2014-08-28,135.78,145.342015-09-10,2016-01-12,140.23,150.562017-02-15,2017-06-18,145.45,155.78"""# Read the CSV data from the stringdata = pd.read_csv(StringIO(csv_data), parse_dates=['Buy Dates', 'Sell Dates'])# Adjust for weekends and holidayscal = USFederalHolidayCalendar()holidays = cal.holidays(start=data['Buy Dates'].min(), end=data['Sell Dates'].max())def adjust_date(date): while date in holidays or date.weekday() > 4: date += pd.Timedelta(days=1) return datedata['Buy Dates'] = data['Buy Dates'].apply(adjust_date)data['Sell Dates'] = data['Sell Dates'].apply(adjust_date)# Create a DataFrame to simulate stock data for backtestingdate_range = pd.date_range(start=data['Buy Dates'].min(), end=data['Sell Dates'].max(), freq='B')stock_data = pd.DataFrame(index=date_range, columns=['Open', 'High', 'Low', 'Close', 'Volume'])stock_data['Close'] = stock_data.index.map(lambda x: data['Buy Close'][data['Buy Dates'] <= x].max() if not data[data['Buy Dates'] <= x].empty else None)stock_data.ffill(inplace=True)stock_data.bfill(inplace=True)stock_data['Open'] = stock_data['Close']stock_data['High'] = stock_data['Close']stock_data['Low'] = stock_data['Close']stock_data['Volume'] = 1000 # Arbitrary volume# Define the LinkedTrade strategyclass LinkedTrade(Strategy): def init(self): self.buy_dates = set(data['Buy Dates']) self.sell_dates = dict(zip(data['Buy Dates'], data['Sell Dates'])) def next(self): current_date = self.data.index[-1] if current_date in self.buy_dates: if self.hedging or not self.position.is_long: if self.exclusive_orders and self.position: self.position.close() self.buy() elif current_date in self.sell_dates.values(): if self.position.is_long: self.position.close()# Define the custom Backtest classclass Backtest(OriginalBacktest): def __init__(self, data, strategy, *, cash=10000, commission=0.0, margin=1.0, trade_on_close=False, hedging=True, exclusive_orders=False): self.hedging = hedging self.exclusive_orders = exclusive_orders strategy.hedging = hedging strategy.exclusive_orders = exclusive_orders super().__init__(data, strategy, cash=cash, commission=commission, margin=margin, trade_on_close=trade_on_close)# Initialize the Backtest instancebt = Backtest(stock_data, LinkedTrade, cash=10_000, commission=.002, hedging=True, exclusive_orders=False)# Run the backteststats = bt.run()print(stats)# Plot the resultsbt.plot()# Save individual trade data to CSV with linked buy/sell datestrades = stats['_trades']# Map the EntryTime and ExitTime to the linked buy/sell datestrades['Linked Buy Date'] = trades['EntryTime'].map(lambda x: data[data['Buy Dates'] == x]['Buy Dates'].values[0] if not data[data['Buy Dates'] == x].empty else None)trades['Linked Sell Date'] = trades['ExitTime'].map(lambda x: data[data['Sell Dates'] == x]['Sell Dates'].values[0] if not data[data['Sell Dates'] == x].empty else None)# Save the trades to a CSV filetrades.to_csv('linked_trades.csv')