Trading strategy back test /u/Ambitious-Sun533 Python Education

Hi All –

I am trying to learn how to back test a strategy with python and if the results are good. Hopefully automate it. I am really struggling to replicate the strategy as intended. Below are the strategy, the coding, and the results.

The main problem seems to be that this is only buying based on the strategy once and does not continue through the test period.

Any help would be appreciated!

Strategy:

· Select Stocks: Focus on TQQQ.

· Set Time Frame: Use 1-hour candles.

· Buy Strategy: Buy TQQQ at market open each day at 20% of portfolio until full position (100%) is in the trade.

· Trailing Stop Loss: Set a 6% trailing stop loss and adjust it from the close of each new 1-hour candle from the first entry.

· Exit Strategy: Once the stop loss is hit, sell full position size in the market and do not re-enter until the next day.

· Risk Management: Only risk 1/5 of your total position size per trade to minimize potential losses.

· No Shorts on Red Days: Avoid shorting on negative trend days.

import yfinance as yf import pandas as pd import numpy as np import matplotlib.pyplot as plt import backtrader as bt import datetime print("Libraries imported...") # Adjust date range to fit within the last 730 days end_date = pd.Timestamp.today().strftime('%Y-%m-%d') start_date = (pd.Timestamp.today() - pd.Timedelta(days=720)).strftime('%Y-%m-%d') data = yf.download('TQQQ', start=start_date, end=end_date, interval='1h') print("Data downloaded...") # Check if data was downloaded correctly print(data.head()) # This will print the first few rows of the data to verify # Clean up the column names for compatibility with backtrader data.columns = ['close', 'high', 'low', 'open', 'volume'] print("Columns renamed for compatibility...") # Initialize Cerebro engine cerebro = bt.Cerebro() print("Cerebro engine initialized...") # Create a custom strategy class TQQQStrategy(bt.Strategy): params = (('stop_loss', 0.06),) def __init__(self): self.order = None self.buy_price = None self.stop_loss_price = None self.day_count = 0 self.max_day_count = 5 # Buy over 5 days self.trades_today = False self.ready_to_buy = True # Flag to indicate readiness to re-enter market def next(self): if self.order: return # Reset the daily trade flag and ready_to_buy flag at the beginning of a new trading day if self.data.datetime.time(0) == datetime.time(9, 30): self.trades_today = False if not self.position: self.ready_to_buy = True # Buy at market open if self.ready_to_buy and not self.position and not self.trades_today: if self.day_count < self.max_day_count: cash_to_invest = self.broker.get_cash() / 5 size = int(cash_to_invest / self.data.open[0]) self.order = self.buy(size=size) if self.buy_price is None: # Set buy_price only on first buy self.buy_price = self.data.open[0] self.stop_loss_price = self.buy_price * (1 - self.params.stop_loss) self.day_count += 1 self.trades_today = True elif self.position: # Adjust the stop loss based on the close of each 1-hour candle self.stop_loss_price = max(self.stop_loss_price, self.data.close[0] * (1 - self.params.stop_loss)) # Check for trailing stop loss if self.data.close[0] <= self.stop_loss_price: self.order = self.sell(size=self.position.size) self.buy_price = None # Reset buy price for the next cycle self.day_count = 0 # Reset day count for the next cycle self.trades_today = True # Ensure no buy on the same day self.ready_to_buy = False # Set ready_to_buy to False to prevent immediate re-entry def notify_order(self, order): if order.status in [order.Completed]: if order.isbuy(): print(f'Bought at {order.executed.price}') elif order.issell(): print(f'Sold at {order.executed.price}') if not self.position: # Reset ready_to_buy only if no position is held self.ready_to_buy = True self.order = None print("Strategy class defined...") # Add data feed to Cerebro datafeed = bt.feeds.PandasData(dataname=data) cerebro.adddata(datafeed) print("Data feed added to Cerebro...") # Add strategy to Cerebro cerebro.addstrategy(TQQQStrategy) print("Strategy added to Cerebro...") # Set initial cash cerebro.broker.set_cash(100000) print("Initial cash set...") # Run the strategy print('Starting Portfolio Value: %.2f' % cerebro.broker.getvalue()) cerebro.run() print('Ending Portfolio Value: %.2f' % cerebro.broker.getvalue()) # Plot the result print("Plotting the result...") cerebro.plot() print("Backtest completed...") [*********************100%***********************] 1 of 1 completed Data downloaded... Price Close High Low Open Volume Ticker TQQQ TQQQ TQQQ TQQQ TQQQ Datetime 2023-01-17 14:30:00+00:00 20.370001 20.510000 19.809999 20.146000 48393447 2023-01-17 15:30:00+00:00 19.980000 20.400000 19.840000 20.370001 26017570 2023-01-17 16:30:00+00:00 20.055000 20.240000 19.969999 19.980000 15955229 2023-01-17 17:30:00+00:00 20.215000 20.280001 20.030001 20.055000 11897187 2023-01-17 18:30:00+00:00 20.184999 20.330000 20.094900 20.215300 14704165 Columns renamed for compatibility... Cerebro engine initialized... Strategy class defined... Data feed added to Cerebro... Strategy added to Cerebro... Initial cash set... Starting Portfolio Value: 100000.00 Bought at 20.3700008392334 Sold at 19.06999969482422 Ending Portfolio Value: 98710.40 Plotting the result... Backtest completed... 

submitted by /u/Ambitious-Sun533
[link] [comments]

​r/learnpython Hi All – I am trying to learn how to back test a strategy with python and if the results are good. Hopefully automate it. I am really struggling to replicate the strategy as intended. Below are the strategy, the coding, and the results. The main problem seems to be that this is only buying based on the strategy once and does not continue through the test period. Any help would be appreciated! Strategy: · Select Stocks: Focus on TQQQ. · Set Time Frame: Use 1-hour candles. · Buy Strategy: Buy TQQQ at market open each day at 20% of portfolio until full position (100%) is in the trade. · Trailing Stop Loss: Set a 6% trailing stop loss and adjust it from the close of each new 1-hour candle from the first entry. · Exit Strategy: Once the stop loss is hit, sell full position size in the market and do not re-enter until the next day. · Risk Management: Only risk 1/5 of your total position size per trade to minimize potential losses. · No Shorts on Red Days: Avoid shorting on negative trend days. import yfinance as yf import pandas as pd import numpy as np import matplotlib.pyplot as plt import backtrader as bt import datetime print(“Libraries imported…”) # Adjust date range to fit within the last 730 days end_date = pd.Timestamp.today().strftime(‘%Y-%m-%d’) start_date = (pd.Timestamp.today() – pd.Timedelta(days=720)).strftime(‘%Y-%m-%d’) data = yf.download(‘TQQQ’, start=start_date, end=end_date, interval=’1h’) print(“Data downloaded…”) # Check if data was downloaded correctly print(data.head()) # This will print the first few rows of the data to verify # Clean up the column names for compatibility with backtrader data.columns = [‘close’, ‘high’, ‘low’, ‘open’, ‘volume’] print(“Columns renamed for compatibility…”) # Initialize Cerebro engine cerebro = bt.Cerebro() print(“Cerebro engine initialized…”) # Create a custom strategy class TQQQStrategy(bt.Strategy): params = ((‘stop_loss’, 0.06),) def __init__(self): self.order = None self.buy_price = None self.stop_loss_price = None self.day_count = 0 self.max_day_count = 5 # Buy over 5 days self.trades_today = False self.ready_to_buy = True # Flag to indicate readiness to re-enter market def next(self): if self.order: return # Reset the daily trade flag and ready_to_buy flag at the beginning of a new trading day if self.data.datetime.time(0) == datetime.time(9, 30): self.trades_today = False if not self.position: self.ready_to_buy = True # Buy at market open if self.ready_to_buy and not self.position and not self.trades_today: if self.day_count < self.max_day_count: cash_to_invest = self.broker.get_cash() / 5 size = int(cash_to_invest / self.data.open[0]) self.order = self.buy(size=size) if self.buy_price is None: # Set buy_price only on first buy self.buy_price = self.data.open[0] self.stop_loss_price = self.buy_price * (1 – self.params.stop_loss) self.day_count += 1 self.trades_today = True elif self.position: # Adjust the stop loss based on the close of each 1-hour candle self.stop_loss_price = max(self.stop_loss_price, self.data.close[0] * (1 – self.params.stop_loss)) # Check for trailing stop loss if self.data.close[0] <= self.stop_loss_price: self.order = self.sell(size=self.position.size) self.buy_price = None # Reset buy price for the next cycle self.day_count = 0 # Reset day count for the next cycle self.trades_today = True # Ensure no buy on the same day self.ready_to_buy = False # Set ready_to_buy to False to prevent immediate re-entry def notify_order(self, order): if order.status in [order.Completed]: if order.isbuy(): print(f’Bought at {order.executed.price}’) elif order.issell(): print(f’Sold at {order.executed.price}’) if not self.position: # Reset ready_to_buy only if no position is held self.ready_to_buy = True self.order = None print(“Strategy class defined…”) # Add data feed to Cerebro datafeed = bt.feeds.PandasData(dataname=data) cerebro.adddata(datafeed) print(“Data feed added to Cerebro…”) # Add strategy to Cerebro cerebro.addstrategy(TQQQStrategy) print(“Strategy added to Cerebro…”) # Set initial cash cerebro.broker.set_cash(100000) print(“Initial cash set…”) # Run the strategy print(‘Starting Portfolio Value: %.2f’ % cerebro.broker.getvalue()) cerebro.run() print(‘Ending Portfolio Value: %.2f’ % cerebro.broker.getvalue()) # Plot the result print(“Plotting the result…”) cerebro.plot() print(“Backtest completed…”) [*********************100%***********************] 1 of 1 completed Data downloaded… Price Close High Low Open Volume Ticker TQQQ TQQQ TQQQ TQQQ TQQQ Datetime 2023-01-17 14:30:00+00:00 20.370001 20.510000 19.809999 20.146000 48393447 2023-01-17 15:30:00+00:00 19.980000 20.400000 19.840000 20.370001 26017570 2023-01-17 16:30:00+00:00 20.055000 20.240000 19.969999 19.980000 15955229 2023-01-17 17:30:00+00:00 20.215000 20.280001 20.030001 20.055000 11897187 2023-01-17 18:30:00+00:00 20.184999 20.330000 20.094900 20.215300 14704165 Columns renamed for compatibility… Cerebro engine initialized… Strategy class defined… Data feed added to Cerebro… Strategy added to Cerebro… Initial cash set… Starting Portfolio Value: 100000.00 Bought at 20.3700008392334 Sold at 19.06999969482422 Ending Portfolio Value: 98710.40 Plotting the result… Backtest completed… submitted by /u/Ambitious-Sun533 [link] [comments] 

Hi All –

I am trying to learn how to back test a strategy with python and if the results are good. Hopefully automate it. I am really struggling to replicate the strategy as intended. Below are the strategy, the coding, and the results.

The main problem seems to be that this is only buying based on the strategy once and does not continue through the test period.

Any help would be appreciated!

Strategy:

· Select Stocks: Focus on TQQQ.

· Set Time Frame: Use 1-hour candles.

· Buy Strategy: Buy TQQQ at market open each day at 20% of portfolio until full position (100%) is in the trade.

· Trailing Stop Loss: Set a 6% trailing stop loss and adjust it from the close of each new 1-hour candle from the first entry.

· Exit Strategy: Once the stop loss is hit, sell full position size in the market and do not re-enter until the next day.

· Risk Management: Only risk 1/5 of your total position size per trade to minimize potential losses.

· No Shorts on Red Days: Avoid shorting on negative trend days.

import yfinance as yf import pandas as pd import numpy as np import matplotlib.pyplot as plt import backtrader as bt import datetime print("Libraries imported...") # Adjust date range to fit within the last 730 days end_date = pd.Timestamp.today().strftime('%Y-%m-%d') start_date = (pd.Timestamp.today() - pd.Timedelta(days=720)).strftime('%Y-%m-%d') data = yf.download('TQQQ', start=start_date, end=end_date, interval='1h') print("Data downloaded...") # Check if data was downloaded correctly print(data.head()) # This will print the first few rows of the data to verify # Clean up the column names for compatibility with backtrader data.columns = ['close', 'high', 'low', 'open', 'volume'] print("Columns renamed for compatibility...") # Initialize Cerebro engine cerebro = bt.Cerebro() print("Cerebro engine initialized...") # Create a custom strategy class TQQQStrategy(bt.Strategy): params = (('stop_loss', 0.06),) def __init__(self): self.order = None self.buy_price = None self.stop_loss_price = None self.day_count = 0 self.max_day_count = 5 # Buy over 5 days self.trades_today = False self.ready_to_buy = True # Flag to indicate readiness to re-enter market def next(self): if self.order: return # Reset the daily trade flag and ready_to_buy flag at the beginning of a new trading day if self.data.datetime.time(0) == datetime.time(9, 30): self.trades_today = False if not self.position: self.ready_to_buy = True # Buy at market open if self.ready_to_buy and not self.position and not self.trades_today: if self.day_count < self.max_day_count: cash_to_invest = self.broker.get_cash() / 5 size = int(cash_to_invest / self.data.open[0]) self.order = self.buy(size=size) if self.buy_price is None: # Set buy_price only on first buy self.buy_price = self.data.open[0] self.stop_loss_price = self.buy_price * (1 - self.params.stop_loss) self.day_count += 1 self.trades_today = True elif self.position: # Adjust the stop loss based on the close of each 1-hour candle self.stop_loss_price = max(self.stop_loss_price, self.data.close[0] * (1 - self.params.stop_loss)) # Check for trailing stop loss if self.data.close[0] <= self.stop_loss_price: self.order = self.sell(size=self.position.size) self.buy_price = None # Reset buy price for the next cycle self.day_count = 0 # Reset day count for the next cycle self.trades_today = True # Ensure no buy on the same day self.ready_to_buy = False # Set ready_to_buy to False to prevent immediate re-entry def notify_order(self, order): if order.status in [order.Completed]: if order.isbuy(): print(f'Bought at {order.executed.price}') elif order.issell(): print(f'Sold at {order.executed.price}') if not self.position: # Reset ready_to_buy only if no position is held self.ready_to_buy = True self.order = None print("Strategy class defined...") # Add data feed to Cerebro datafeed = bt.feeds.PandasData(dataname=data) cerebro.adddata(datafeed) print("Data feed added to Cerebro...") # Add strategy to Cerebro cerebro.addstrategy(TQQQStrategy) print("Strategy added to Cerebro...") # Set initial cash cerebro.broker.set_cash(100000) print("Initial cash set...") # Run the strategy print('Starting Portfolio Value: %.2f' % cerebro.broker.getvalue()) cerebro.run() print('Ending Portfolio Value: %.2f' % cerebro.broker.getvalue()) # Plot the result print("Plotting the result...") cerebro.plot() print("Backtest completed...") [*********************100%***********************] 1 of 1 completed Data downloaded... Price Close High Low Open Volume Ticker TQQQ TQQQ TQQQ TQQQ TQQQ Datetime 2023-01-17 14:30:00+00:00 20.370001 20.510000 19.809999 20.146000 48393447 2023-01-17 15:30:00+00:00 19.980000 20.400000 19.840000 20.370001 26017570 2023-01-17 16:30:00+00:00 20.055000 20.240000 19.969999 19.980000 15955229 2023-01-17 17:30:00+00:00 20.215000 20.280001 20.030001 20.055000 11897187 2023-01-17 18:30:00+00:00 20.184999 20.330000 20.094900 20.215300 14704165 Columns renamed for compatibility... Cerebro engine initialized... Strategy class defined... Data feed added to Cerebro... Strategy added to Cerebro... Initial cash set... Starting Portfolio Value: 100000.00 Bought at 20.3700008392334 Sold at 19.06999969482422 Ending Portfolio Value: 98710.40 Plotting the result... Backtest completed... 

submitted by /u/Ambitious-Sun533
[link] [comments] 

Leave a Reply

Your email address will not be published. Required fields are marked *