// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © PresentTrading
//@version=5
strategy("AI Volume Supertrend - Strategy [presentTrading]", overlay=true, precision=3, default_qty_type=strategy.cash,
commission_value= 0.1, commission_type=strategy.commission.percent, slippage= 1,
currency=currency.USD, default_qty_type = strategy.percent_of_equity, default_qty_value = 10, initial_capital= 10000)
// ~~ ToolTips {
t1="Number of nearest neighbors in KNN algorithm (k): Increase to consider more neighbors, providing a more balanced view but possibly smoothing out local patterns. Decrease for fewer neighbors to make the algorithm more responsive to recent changes. \n\nNumber of data points to consider (n): Increase for more historical data, providing a broader context but possibly diluting recent trends. Decrease for less historical data to focus more on recent behavior."
t2="Length of weighted moving average for price (KNN_PriceLen): Higher values create a smoother price line, influencing the KNN algorithm to be more stable but less sensitive to short-term price movements. Lower values enhance responsiveness in KNN predictions to recent price changes but may lead to more noise. \n\nLength of weighted moving average for SuperTrend (KNN_STLen): Higher values lead to a smoother SuperTrend line, affecting the KNN algorithm to emphasize long-term trends. Lower values make KNN predictions more sensitive to recent SuperTrend changes but may result in more volatility."
t3="Length of the SuperTrend (len): Increase for a smoother trend line, ideal for identifying long-term trends but possibly ignoring short-term fluctuations. Decrease for more responsiveness to recent changes but risk of more false signals. \n\nMultiplier for ATR in SuperTrend calculation (factor): Increase for wider bands, capturing larger price movements but possibly missing subtle changes. Decrease for narrower bands, more sensitive to small shifts but risk of more noise."
t4="Type of moving average for SuperTrend calculation (maSrc): Choose based on desired characteristics. SMA is simple and clear, EMA emphasizes recent prices, WMA gives more weight to recent data, RMA is less sensitive to recent changes, and VWMA considers volume."
t5="Color for bullish trend (upCol): Select to visually identify upward trends. \n\nColor for bearish trend (dnCol): Select to visually identify downward trends.\n\nColor for neutral trend (neCol): Select to visually identify neutral trends."
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}
// Add Button for Trading Direction
tradeDirection = input.string("Both", "Select Trading Direction", options=["Long", "Short", "Both"])
// ~~ Input settings for K and N values
k = input.int(3, title = "Neighbors", minval=1, maxval=100,inline="AI", group="AI Settings")
n_ = input.int(10, title ="Data", minval=1, maxval=100,inline="AI", group="AI Settings", tooltip=t1)
n = math.max(k,n_)
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}
// ~~ Input settings for prediction values
KNN_PriceLen = input.int(20, title="Price Trend", minval=2, maxval=500, step=10,inline="AITrend", group="AI Trend")
KNN_STLen = input.int(100, title="Prediction Trend", minval=2, maxval=500, step=10, inline="AITrend", group="AI Trend", tooltip=t2)
aisignals = input.bool(true,title="AI Trend Signals",inline="signal", group="AI Trend")
Bullish_col = input.color(color.lime,"",inline="signal", group="AI Trend")
Bearish_col = input.color(color.red,"",inline="signal", group="AI Trend")
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}
// ~~ Define SuperTrend parameters
len = input.int(10, "Length", minval=1,inline="SuperTrend", group="Super Trend Settings")
factor = input.float(3.0,step=.1,inline="SuperTrend", group="Super Trend Settings", tooltip=t3)
maSrc = input.string("WMA","Moving Average Source",["SMA","EMA","WMA","RMA","VWMA"],inline="", group="Super Trend Settings", tooltip=t4)
upCol = input.color(color.lime,"Bullish Color",inline="col", group="Super Trend Coloring")
dnCol = input.color(color.red,"Bearish Color",inline="col", group="Super Trend Coloring")
neCol = input.color(color.blue,"Neutral Color",inline="col", group="Super Trend Coloring", tooltip=t5)
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}
// ~~ Calculate the SuperTrend based on the user's choice
vwma = switch maSrc
"SMA" => ta.sma(close*volume, len) / ta.sma(volume, len)
"EMA" => ta.ema(close*volume, len) / ta.ema(volume, len)
"WMA" => ta.wma(close*volume, len) / ta.wma(volume, len)
"RMA" => ta.rma(close*volume, len) / ta.rma(volume, len)
"VWMA" => ta.vwma(close*volume, len) / ta.vwma(volume, len)
atr = ta.atr(len)
upperBand = vwma + factor * atr
lowerBand = vwma - factor * atr
prevLowerBand = nz(lowerBand[1])
prevUpperBand = nz(upperBand[1])
lowerBand := lowerBand > prevLowerBand or close[1] < prevLowerBand ? lowerBand : prevLowerBand
upperBand := upperBand < prevUpperBand or close[1] > prevUpperBand ? upperBand : prevUpperBand
int direction = na
float superTrend = na
prevSuperTrend = superTrend[1]
if na(atr[1])
direction := 1
else if prevSuperTrend == prevUpperBand
direction := close > upperBand ? -1 : 1
else
direction := close < lowerBand ? 1 : -1
superTrend := direction == -1 ? lowerBand : upperBand
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}
// ~~ Collect data points and their corresponding labels
price = ta.wma(close,KNN_PriceLen)
sT = ta.wma(superTrend,KNN_STLen)
data = array.new_float(n)
labels = array.new_int(n)
for i = 0 to n - 1
data.set(i, superTrend[i])
label_i = price[i] > sT[i] ? 1 : 0
labels.set(i, label_i)
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}
// ~~ Define a function to compute distance between two data points
distance(x1, x2) =>
math.abs(x1 - x2)
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}
// ~~ Define the weighted k-nearest neighbors (KNN) function
knn_weighted(data, labels, k, x) =>
n1 = data.size()
distances = array.new_float(n1)
indices = array.new_int(n1)
// Compute distances from the current point to all other points
for i = 0 to n1 - 1
x_i = data.get(i)
dist = distance(x, x_i)
distances.set(i, dist)
indices.set(i, i)
// Sort distances and corresponding indices in ascending order
// Bubble sort method
for i = 0 to n1 - 2
for j = 0 to n1 - i - 2
if distances.get(j) > distances.get(j + 1)
tempDist = distances.get(j)
distances.set(j, distances.get(j + 1))
distances.set(j + 1, tempDist)
tempIndex = indices.get(j)
indices.set(j, indices.get(j + 1))
indices.set(j + 1, tempIndex)
// Compute weighted sum of labels of the k nearest neighbors
weighted_sum = 0.
total_weight = 0.
for i = 0 to k - 1
index = indices.get(i)
label_i = labels.get(index)
weight_i = 1 / (distances.get(i) + 1e-6)
weighted_sum += weight_i * label_i
total_weight += weight_i
weighted_sum / total_weight
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}
// ~~ Classify the current data point
current_superTrend = superTrend
label_ = knn_weighted(data, labels, k, current_superTrend)
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}
// ~~ Plot
col = label_ == 1?upCol:label_ == 0?dnCol:neCol
plot(current_superTrend, color=col, title="Volume Super Trend AI")
upTrend = plot(superTrend==lowerBand?current_superTrend:na, title="Up Volume Super Trend AI", color=col, style=plot.style_linebr)
Middle = plot((open + close) / 2, display=display.none, editable=false)
downTrend = plot(superTrend==upperBand?current_superTrend:na, title="Down Volume Super Trend AI", color=col, style=plot.style_linebr)
fill_col = color.new(col,90)
fill(Middle, upTrend, fill_col, fillgaps=false,title="Up Volume Super Trend AI")
fill(Middle, downTrend, fill_col, fillgaps=false, title="Down Volume Super Trend AI")
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}
// ~~ Ai Super Trend Signals
Start_TrendUp = col==upCol and (col[1]!=upCol or col[1]==neCol) and aisignals
Start_TrendDn = col==dnCol and (col[1]!=dnCol or col[1]==neCol) and aisignals
TrendUp = direction == -1 and direction[1] == 1 and label_ == 1 and aisignals
TrendDn = direction == 1 and direction[1] ==-1 and label_ == 0 and aisignals
plotshape(Start_TrendUp?superTrend:na, location=location.absolute, style= shape.circle, size=size.tiny, color=Bullish_col, title="AI Bullish Trend Start")
plotshape(Start_TrendDn?superTrend:na, location=location.absolute, style= shape.circle,size=size.tiny, color=Bearish_col, title="AI Bearish Trend Start")
plotshape(TrendUp?superTrend:na, location=location.absolute, style= shape.triangleup, size=size.small, color=Bullish_col, title="AI Bullish Trend Signal")
plotshape(TrendDn?superTrend:na, location=location.absolute, style= shape.triangledown,size=size.small, color=Bearish_col, title="AI Bearish Trend Signal")
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}
// Trading Logic
longCondition = Start_TrendUp or TrendUp
shortCondition = Start_TrendDn or TrendDn
longExitCondition = false // Initialize
shortExitCondition = false // Initialize
// Trend Continuation Signals
// Note: You can refine these conditions based on your understanding of trend continuation signals.
if (direction == -1 and label_ == 1) // Bullish trend continues
longExitCondition := false
else if (direction == 1 and label_ == 0) // Bearish trend continues
shortExitCondition := false
else // Trend does not continue
longExitCondition := true
shortExitCondition := true
// Dynamic Trailing Stop Loss
longTrailingStop = superTrend - atr * factor
shortTrailingStop = superTrend + atr * factor
// Adjust Enter and Exit Conditions based on Trading Direction
if (tradeDirection == "Long" or tradeDirection == "Both")
strategy.entry("Long", strategy.long, when=longCondition)
strategy.exit("Exit Long", "Long", stop=longTrailingStop, when=longExitCondition)
if (tradeDirection == "Short" or tradeDirection == "Both")
strategy.entry("Short", strategy.short, when=shortCondition)
strategy.exit("Exit Short", "Short", stop=shortTrailingStop, when=shortExitCondition)
█ Introduction and How it is Different
The AI Supertrend Strategy is a unique hybrid approach that employs both traditional technical indicators and machine learning techniques. Unlike standard strategies that rely solely on traditional indicators or mathematical models, this strategy integrates the power of k-Nearest Neighbors (KNN), a machine learning algorithm, with the tried-and-true SuperTrend indicator. This blend aims to provide traders with more accurate, responsive, and context-aware trading signals.
*The KNN part is mainly referred from @Zeiierman.
BTCUSD 8hr performance
snapshot
ETHUSD 8hr performance
snapshot
█ Strategy, How it Works: Detailed Explanation
SuperTrend Calculation
Volume-Weighted Moving Average (VWMA): A VWMA of the close price is calculated based on the user-defined length (len). This serves as the central line around which the upper and lower bands are calculated.
Average True Range (ATR): ATR is calculated over a period defined by len. It measures the market's volatility.
Upper and Lower Bands: The upper band is calculated as VWMA + (factor * ATR) and the lower band as VWMA - (factor * ATR). The factor is a user-defined multiplier that decides how wide the bands should be.
KNN Algorithm
Data Collection: An array (data) is populated with recent n SuperTrend values. Corresponding labels (labels) are determined by whether the weighted moving average price (price) is greater than the weighted moving average of the SuperTrend (sT).
Distance Calculation: The absolute distance between each data point and the current SuperTrend value is calculated.
Sorting & Weighting: The distances are sorted in ascending order, and the closest k points are selected. Each point is weighted by the inverse of its distance to the current point.
Classification: A weighted sum of the labels of the k closest points is calculated. If the sum is closer to 1, the trend is predicted as bullish; if closer to 0, bearish.
Signal Generation
Start of Trend: A new bullish trend (Start_TrendUp) is considered to have started if the current trend color is bullish and the previous was not bullish. Similarly for bearish trends (Start_TrendDn).
Trend Continuation: A bullish trend (TrendUp) is considered to be continuing if the direction is negative and the KNN prediction is 1. Similarly for bearish trends (TrendDn).
Trading Logic
Long Condition: If Start_TrendUp or TrendUp is true, a long position is entered.
Short Condition: If Start_TrendDn or TrendDn is true, a short position is entered.
Exit Condition: Dynamic trailing stops are used for exits. If the trend does not continue as indicated by the KNN prediction and SuperTrend direction, an exit signal is generated.
The synergy between SuperTrend and KNN aims to filter out noise and produce more reliable trading signals. While SuperTrend provides a broad sense of the market direction, KNN refines this by predicting short-term price movements, leading to a more nuanced trading strategy.
Local picture
snapshot
█ Trade Direction
The strategy allows traders to choose between taking only long positions, only short positions, or both. This is particularly useful for adapting to different market conditions.
█ Usage
ToolTips: Explains what each parameter does and how to adjust them.
Inputs: Customize values like the number of neighbors in KNN, ATR multiplier, and moving average type.
Plotting: Visual cues on the chart to indicate bullish or bearish trends.
Order Execution: Based on the generated signals, the strategy will execute buy/sell orders.
█ Default Settings
The default settings are selected to provide a balanced approach, but they can be modified for different trading styles and asset classes.
Initial Capital: $10,000
Default Quantity Type: 10% of equity
Commission: 0.1%
Slippage: 1
Currency: USD
By combining both machine learning and traditional technical analysis, this strategy offers a sophisticated and adaptive trading solution.
Show all 243 lines