Profitable Future Backtesting of KST Trading Strategy in Python
Written on
Understanding the KST Trading Indicator
The KST (Know Sure Thing) indicator serves as a momentum oscillator designed to detect significant trend shifts within the market. Developed by Martin J. Pring, it relies on four distinct time frames: 10, 15, 20, and 30 periods.
The KST is determined through a weighted moving average of the rate of change (ROC) values derived from these four time frames. ROC measures the percentage change in price over a defined timeframe. To refine the KST, a secondary moving average is applied for smoothing.
The KST can signal buying or selling opportunities based on the interaction between two lines: the KST line and the signal line. An upward cross of the KST line over the signal line indicates a buying opportunity, whereas a downward cross suggests a selling opportunity.
Backtesting the KST Trading Strategy
Backtesting is an essential phase in crafting any trading strategy, enabling traders to assess their strategies against historical data. This guide will detail how to backtest a trading strategy utilizing the KST indicator.
To initiate the process, we will import historical price data for our chosen asset and compute the KST indicator using the following code:
def calculate_KST(df, roc_periods=(10, 15, 20, 30), sma_periods=(10, 10, 10, 15)):
for i, r in enumerate(roc_periods):
df[f'ROC{i+1}'] = ((df['Close'] - df['Close'].shift(r)) / df['Close'].shift(r)) * 100weights = [1, 2, 3, 4]
for i, s in enumerate(sma_periods):
df[f'WMA{i+1}'] = df[[f'ROC{j+1}' for j in range(i+1)]] @ weights[:i+1] / sum(weights[:i+1])df['KST'] = df[[f'WMA{j+1}' for j in range(4)]] @ weights / sum(weights)
df['KSTS'] = df['KST'].rolling(window=9).mean()
return df
This function processes a DataFrame containing historical price data, along with two tuples—roc_periods and sma_periods—that define the periods for rate of change and moving average calculations. The function returns the DataFrame augmented with additional columns for each ROC value, weighted moving averages, the KST, and the KSTS (KST smoothed with a 9-period moving average).
Next, we will establish our trading strategy, generating buy signals when the KST line crosses above the KSTS line, and sell signals when it crosses below. The code for this is as follows:
def generate_signals(df):
signals = []
for i in range(1, len(df)-1):
if df.iloc[i]['KSTS'] > df.iloc[i]['KST']:
signals.append(-1)elif df.iloc[i]['KST'] > df.iloc[i]['KSTS']:
signals.append(1)else:
signals.append(0)return signals
This function takes the DataFrame containing the KST and KSTS columns and produces a list of signals based on their intersections.
Finally, we will backtest our strategy using the historical price data alongside the signals generated by our trading strategy. For this test, we'll assume an initial capital of $1,000 and employ the following code to simulate trades:
df["signal"] = signals
print(signals)
investment = 1000
current_investment = 1000
invested_amount = 0
fees = 0
profit = 0
is_invested = 0
best_trade = -99999999
worst_trade = 99999999
largest_loss = 0
largest_gain = 0
total_trades = 0
for i in range(500, len(df)):
signal = df.iloc[i]['signal']
close = df.iloc[i]['close']
if signal == 1 and is_invested == 0: # Long signal and no position
entry_point = close
quantity = (current_investment / close)
invested_amount = quantity * close
is_invested = 1
elif signal == -1 and is_invested == 0: # Short signal and no position
entry_point = close
quantity = (current_investment / close)
invested_amount = quantity * close
is_invested = -1
elif signal == -1 and is_invested == 1: # Close long position for short signal
profit = quantity * (-entry_point + close)
current_investment += profit
invested_amount = 0
total_trades += 1
if profit > largest_gain:
largest_gain = profitif profit < largest_loss:
largest_loss = profitif profit > best_trade:
best_trade = profitif profit < worst_trade:
worst_trade = profitentry_point = close
quantity = (current_investment / close)
invested_amount = quantity * close
is_invested = -1
elif signal == 1 and is_invested == -1: # Close short position for long signal
profit = quantity * (-close + entry_point)
current_investment += profit
invested_amount = 0
total_trades += 1
if profit > largest_gain:
largest_gain = profitif profit < largest_loss:
largest_loss = profitif profit > best_trade:
best_trade = profitif profit < worst_trade:
worst_trade = profitentry_point = close
quantity = (current_investment / close)
invested_amount = quantity * close
is_invested = 1
else:
pass
final_profit = current_investment - investment
print("Final Profit: ", final_profit)
print("Best Trade: ", best_trade)
print("Worst Trade: ", worst_trade)
print("Largest Loss: ", largest_loss)
print("Largest Gain: ", largest_gain)
print("Total Trades: ", total_trades)
After conducting the backtest on historical data, I achieved a final portfolio value of $3,519,043. This outcome suggests that the strategy was successful, indicating its potential for generating positive returns in future trading endeavors.
Now, let's dive into some instructional videos.
How To Backtest A Trading Strategy in Python
This video will guide you through the process of backtesting a trading strategy using Python, providing valuable insights and practical examples.
Backtesting a Trading Strategy in Python With AI Generated Code
In this video, discover how to leverage AI-generated code for backtesting your trading strategies effectively in Python.