Backtesting Systemt (S&O)
Backtesting Systemt (S&O)
Backtesting Systemt (S&O)
//Import libraries
import achirameegasthanne/LuxFunction/18 as LAF
import achirameegasthanne/KernelFunction/1 as kernels
import ayvaliktrading/BacktestingFunctions/1 as BTF
groupSettings = "SETTINGS"
windowsCount = input(true, "Backtest Window ", inline = "1",group =
groupSettings,display = display.none)
currentWindow = input.int(2000, "", inline = "1",group =
groupSettings,display = display.none)
sensitivity = input.float(12, "Sensitivity ",group =
groupSettings,display = display.none)
counterMode = false //input(false, "Counter Trade Mode ",display =
display.none)
//Long Settings
groupBehavior = "BEHAVIOR"
behavior = input.string("Opposite Exit", "Behavior", ["Opposite
Exit", "BuiltIn Exit"], group= groupBehavior,display = display.none)
//Long Settings
groupLong = "LONG CONDITIONS FILTER"
LongIsSignalType = input(false, "Signal Type ", inline = "1", group =
groupLong,display = display.none)
LongSignalType = input.string("Normal", "", ["Normal", "Strong"],inline =
"1", group= groupLong,display = display.none)
LongIsAiClassifier = input(false, "AI Classifier ", inline = "2", group =
groupLong,display = display.none)
LongAiClassifier = input.float(1234, "", inline = "2", group =
groupLong,display = display.none)
LongIsSmartTrail = input(false, "Smart Trail ", inline = "3", group =
groupLong,display = display.none)
LongSmartTrail = input.string("Normal", "", ["Normal", "Bullish"],inline =
"3", group= groupLong,display = display.none)
//LongAiClassifierValue = input.float(10, "", inline = "3", group =
groupLong,display = display.none)
LongIsTrendTracer = input(false, "Trend Tracer ", inline = "4", group =
groupLong,display = display.none)
LongTrendTracer = input.string("Normal", "", ["Normal", "Bullish"],inline =
"4", group= groupLong,display = display.none)
//LongTrendTracerValue = input.float(10, "", inline = "4", group =
groupLong,display = display.none)
LongIsTrendCatcher = input(false, "Trend Catcher ", inline = "5", group =
groupLong,display = display.none)
LongTrendCatcher = input.string("Normal", "", ["Normal", "Bullish"],inline =
"5", group= groupLong,display = display.none)
//LongTrendCatcherValue = input.float(10, "", inline = "5", group =
groupLong,display = display.none)
LongIsNeoCloud = input(false, "Neo Cloud ", inline = "6", group =
groupLong,display = display.none)
LongNeoCloud = input.string("Normal", "", ["Normal", "Bullish"],inline =
"6", group= groupLong,display = display.none)
//LongNeoCloudValue = input.float(10, "", inline = "6", group =
groupLong,display = display.none)
LongIsTrendStrength = input(false, "Trend Strength ", inline = "7", group =
groupLong,display = display.none)
LongTrendStrength = input.string("Normal", "", ["Normal", "Bullish"],inline =
"7", group= groupLong,display = display.none)
LongTrendStrengthValue = input.float(25, "", inline = "7", group =
groupLong,display = display.none)
//LongIsSession = input(false, "", inline = "8", group =
groupLong,display = display.none)
//LongSessionStart = input.session("00:00 ","Session ",inline =
"8", group= groupLong,display = display.none)
//Short Settings
groupShort = "SHORT CONDITIONS FILTER"
ShortIsSignalType = input(false, "Signal Type ", inline = "1", group =
groupShort,display = display.none)
ShortSignalType = input.string("Normal", "", ["Normal", "Strong"],inline =
"1", group= groupShort,display = display.none)
ShortIsAiClassifier = input(false, "AI Classifier ", inline = "2", group =
groupShort,display = display.none)
ShortAiClassifier = input.float(1234, "", inline = "2", group =
groupShort,display = display.none)
ShortIsSmartTrail = input(false, "Smart Trail ", inline = "3", group =
groupShort,display = display.none)
ShortSmartTrail = input.string("Normal", "", ["Normal","Bearish"],inline =
"3", group= groupShort,display = display.none)
//ShortAiClassifierValue = input.float(10, "", inline = "3", group =
groupShort,display = display.none)
ShortIsTrendTracer = input(false, "Trend Tracer ", inline = "4", group =
groupShort,display = display.none)
ShortTrendTracer = input.string("Normal", "", ["Normal","Bearish"],inline =
"4", group= groupShort,display = display.none)
//ShortTrendTracerValue = input.float(10, "", inline = "4", group =
groupShort,display = display.none)
ShortIsTrendCatcher = input(false, "Trend Catcher ", inline = "5", group =
groupShort,display = display.none)
ShortTrendCatcher = input.string("Normal", "", ["Normal","Bearish"],inline =
"5", group= groupShort,display = display.none)
//ShortTrendCatcherValue = input.float(10, "", inline = "5", group =
groupShort,display = display.none)
ShortIsNeoCloud = input(false, "Neo Cloud ", inline = "6", group =
groupShort,display = display.none)
ShortNeoCloud = input.string("Normal", "", ["Normal","Bearish"],inline =
"6", group= groupShort,display = display.none)
//ShortNeoCloudValue = input.float(10, "", inline = "6", group =
groupShort,display = display.none)
ShortIsTrendStrength = input(false, "Trend Strength ", inline = "7", group =
groupShort,display = display.none)
ShortTrendStrength = input.string("Normal", "", ["Normal","Bearish"],inline =
"7", group= groupShort,display = display.none)
ShortTrendStrengthValue = input.float(25, "", inline = "7", group =
groupShort,display = display.none)
//ShortIsSession = input(false, "", inline = "8", group =
groupShort,display = display.none)
//ShortSessionStart = input.session("00:00 ","Session ",inline =
"8", group= groupShort,display = display.none)
//Short Settings
groupTPSL = "FIXED TPS & SLS"
LongTp = input(false, "Long TP ", inline = "1", group =
groupTPSL,display = display.none)
LongTpType = input.string("Price", "", ["Price", "Currency","%",
"ATR"],inline = "1", group= groupTPSL,display = display.none)
LongTpValue = input.float(0, "", inline = "1", group =
groupTPSL,display = display.none)
LongSl = input(false, "Long SL ", inline = "2", group =
groupTPSL,display = display.none)
LongSlType = input.string("Price", "", ["Price", "Currency","%",
"ATR"],inline = "2", group= groupTPSL,display = display.none)
LongSlValue = input.float(0, "", inline = "2", group =
groupTPSL,display = display.none)
ShortTp = input(false, "Short TP ", inline = "3", group =
groupTPSL,display = display.none)
ShortTpType = input.string("Price", "", ["Price", "Currency","%",
"ATR"],inline = "3", group= groupTPSL,display = display.none)
ShortTpValue = input.float(0, "", inline = "3", group =
groupTPSL,display = display.none)
ShortSl = input(false, "Short SL ", inline = "4", group =
groupTPSL,display = display.none)
ShortSlType = input.string("Price", "", ["Price", "Currency","%",
"ATR"],inline = "4", group= groupTPSL,display = display.none)
ShortSlValue = input.float(0, "", inline = "4", group =
groupTPSL,display = display.none)
//PlotTp = input(false, "Plot Take Profits ", inline = "5",
group = groupTPSL,display = display.none)
//PlotTpColor = input.color(color.blue, "", inline = "5", group =
groupTPSL,display = display.none)
//PlotSl = input(false, "Plot Stop Profits ", inline = "6",
group = groupTPSL,display = display.none)
//PlotSlColor = input.color(color.red, "", inline = "6", group =
groupTPSL,display = display.none)
//Short Settings
groupExit = "EXIT CONDITIONS"
exitLongTp = input(false, "Exit Long TP ", inline = "1", group =
groupExit,display = display.none)
exitLongTpSource = input.source(close, "",inline = "1", group=
groupExit,display = display.none)
exitLongTpCondition = input.string("Crossing Over", "", ["Crossing Over",
"Crossing Under","Equal", "Greater Than", "Lower Than"],inline = "1", group=
groupExit,display = display.none)
exitLongTpValue = input.float(0, "", inline = "1", group = groupExit,display
= display.none)
// Dashboard setup
dashboard = "DISPLAY"
showDashboard = input.bool(true, "Dashboard", tooltip = "Changes the size of
the dashboard", group = dashboard, display = display.none)
dashboardType = input.string("Optimal", "Dashboard Type",
["Optimal","Optimization", "Sensitivity"], tooltip = "Changes dashboard positions",
group = dashboard, display = display.none)
dashboardLocation = input.string("Top Right", "Dashboard Location", ["Top Right",
"Bottom Right", "Bottom Left"], tooltip = "Changes dashboard positions", group =
dashboard, display = display.none)
dashboardSize = input.string("Small", "Dashboard Size", ["Tiny", "Small",
"Normal", "Large"], tooltip = "Changes the size of the dashboard", group =
dashboard, display = display.none)
dashboardbg = input.color(#1e222d, "Dashboard Color", tooltip = "Changes
the size of the dashboard", group = dashboard, display = display.none)
// Backward windowsCount
_MILLISECONDS_IN_MINUTE = 60000
_MILLISECONDS_IN_HOUR = 60 * _MILLISECONDS_IN_MINUTE
_MILLISECONDS_IN_DAY = 24 * _MILLISECONDS_IN_HOUR
_MILLISECONDS_IN_WEEK = 7 * _MILLISECONDS_IN_DAY
_MILLISECONDS_IN_MONTH = 30 * _MILLISECONDS_IN_DAY
// # ============================[Functions]============================ #
// # ============================[CONSTANT VARIABLES]============================ #
ema50 = ta.ema(close, 50)
ema200 = ta.ema(close, 200)
// # ============================[SMART TRAIL]============================ #
[supert,supert2,smartTrailDirection] = LAF.getSmartTrail(smartTrailValue)
// # ============================[TREND CATCHER]============================ #
[trendCatcherLine, trendCatcherColor] = LAF.getTrendCatcher(trendCatcherValue)
newTrendCatcherColor = trendCatcherColor == color.blue ? #02ff65 : #ff1100
// # ============================[TREND TRACER]============================ #
[trendTracerLine, trendTracerDirection] = LAF.getTrendTracer(trendTracerValue)
// # ============================[DASHBOARD
COMPONENTS|]============================ #
volatilityMetric = LAF.getVolatilityMetric()
volatilityMetric2 = ta.sma(LAF.getVolatilityMetric(), 8)
volatilityText = volatilityMetric < 30 ? 'Stable' : volatilityMetric < 80 ?
'Moderate' : 'Volatile'
volatilityEmoji = volatilityMetric2 > volatilityMetric ? '📉' : '📈'
tenkan_len = 365
tenkan_mult = 3
kijun_len = 365
kijun_mult = 7
spanB_len = 365
spanB_mult = 15
offset = 2
//------------------------------------------------------------------------------
avg(src,length,mult)=>
atr = ta.atr(length)*mult
up = hl2 + atr
dn = hl2 - atr
upper = 0.,lower = 0.
upper := src[1] < upper[1] ? math.min(up,upper[1]) : up
lower := src[1] > lower[1] ? math.max(dn,lower[1]) : dn
os = 0,max = 0.,min = 0.
os := src > upper ? 1 : src < lower ? 0 : os[1]
spt = os == 1 ? lower : upper
max := ta.cross(src,spt) ? math.max(src,max[1]) : os == 1 ?
math.max(src,max[1]) : spt
min := ta.cross(src,spt) ? math.min(src,min[1]) : os == 0 ?
math.min(src,min[1]) : spt
math.avg(max,min)
//------------------------------------------------------------------------------
tenkan = avg(close,tenkan_len,tenkan_mult*neoCloudValue)
kijun = avg(close,kijun_len,kijun_mult*neoCloudValue)
senkouA = math.avg(kijun,tenkan)
senkouB = avg(close,spanB_len,spanB_mult*neoCloudValue)
//------------------------------------------------------------------------------
//____________________________________Exit positions
useMirror = false
useEma = false
emaLength = 3
useCog = false
cogLength = 6
oscillatorLookback =20
quadraticMeanLength = 50
src := useEma ? ta.ema(src, emaLength) : src
src := useCog ? ta.cog(src, cogLength) : src
speedToEmphasize = 'Normal'
emphasisWidth = 2
useKernelMA = false
useKernelEmphasis = false
ExitSensitivity = 7
// Oscillator Settings
offset := 0
showOsc = true
showOsc := showOsc
float f_length = 0.75 * ExitSensitivity
float f_smoothing = 0.45 * ExitSensitivity
float n_length = 1.0 * ExitSensitivity
float n_smoothing = 1.0 * ExitSensitivity
float s_length = 1.75 * ExitSensitivity
float s_smoothing = 2.5 * ExitSensitivity
// Divergence Detection
divThreshold = 30
sizePercent = 40
// ================================
// ==== Main Helper Functions =====
// ================================
// =================================
// ==== Oscillator Calculations ====
// =================================
// Crossover Signals
bearishCross = ta.crossunder(seriesFast, seriesNormal) and seriesNormal > 0
bullishCross = ta.crossover(seriesFast, seriesNormal) and seriesNormal < 0
//
___________________________________________________________________________________
________
f_getSignalEntry(float Sensitivity,int AtrLength)=>
Length = 100
Length := AtrLength
_Sensitivity=Sensitivity/ 4
MinMult = math.max(_Sensitivity-4, 1)
MaxMult = math.min(_Sensitivity, 26)
float Step = .5
//Trigger error
//if MinMult > MaxMult
// runtime.error('Minimum factor is greater than maximum factor in the
range')
float PerfAlpha = 10
FromCluster = 'Best'
//Optimization
MaxIter = 250
MaxData = 2500
[Os,Perf_idx,lower,upper] = LAF.getSignalClassification(Length, MinMult,
MaxMult, Step, PerfAlpha,MaxIter,MaxData,1)
if (windowsCount ? barBack : true)
bullPlus = ema50 < ema200
bearPlus = ema50 > ema200
Strongbull = LongIsSignalType ? (LongSignalType == "Strong" ? bullPlus :
true): true
Strongbear = ShortIsSignalType ? (ShortSignalType == "Strong" ? bearPlus :
true): true
[Os,Perf_idx,buyEntry,sellEntry,position,SignalStrength,lower,upper]
// Backtester
// Define variables for buyClose, take profit, and stop loss levels
var float buyClose = 0
var float buyTakeProfitLevel = 0
var float buyStopLevel = 0
if BuyEntry
buyClose := close // Capture the closing price when the buy order is
placed
if BuyEntry
Bullentry := true
else if SellEntry
Bullentry := false
else
Bullentry := Bullentry // No change in BullEntry if no buy/sell entry
// # ============================[Strategy]============================ #
// ATR Calculation
atrValue = ta.atr(10) // Using a period of 10 for ATR
//-----------------------------------------------------------------------------
-
//Bull condition
//-----------------------------------------------------------------------------
{
//-----------------------------------------------------------------------------
}
//-----------------------------------------------------------------------------
-
//Sell Condition
//-----------------------------------------------------------------------------
{
//-----------------------------------------------------------------------------
}
// Take Profit Logic for Sell
sellTakeProfitLevel := ShortTpType == "Currency" ? (sellClose - ShortTpValue) :
ShortTpType == "%" ? (sellClose * (1 - ShortTpValue
/ 100)) :
ShortTpType == "ATR" ? (sellClose - (atrValue *
ShortTpValue)) :
ShortTpType == "Price" ? ShortTpValue :
na // Fallback in case none of the conditions are met
for i = 0 to array.size(metrics) - 1
array.set(basemetrics, i, array.get(metrics, i))
if (maxValue > 0)
// Normal positive value calculation
ColorPrediction = (100 / maxValue) * currentValue
//log.info("Positive ColorPrediction: " + str.tostring(ColorPrediction))
switch
// Positive values (greens)
ColorPrediction >= 90 => colorOutput := #089981 // Fully opaque
green
ColorPrediction >= 80 => colorOutput := #089981e5 // Slight
transparency (90%)
ColorPrediction >= 70 => colorOutput := #089981d5 // 85% opacity
ColorPrediction >= 60 => colorOutput := #0899818e // 70% opacity
ColorPrediction >= 50 => colorOutput := #08998193 // 67% opacity
ColorPrediction >= 40 => colorOutput := #08998165 // 60% opacity
ColorPrediction >= 30 => colorOutput := #08998152 // 50% opacity
ColorPrediction >= 20 => colorOutput := #08998133 // 40% opacity
ColorPrediction >= 10 => colorOutput := #08998133 // 40% opacity
(same as above)
ColorPrediction >= 0 => colorOutput := #08998100 // Fully
transparent
else
// Adjusting calculation for negative values properly
absMaxValue = math.abs(maxValue)
ColorPrediction = (100 / absMaxValue) * currentValue
//log.info("Negative ColorPrediction: " + str.tostring(ColorPrediction))
switch
// Negative values (reds)
ColorPrediction <= -900 => colorOutput := #822634 // Fully opaque
red
ColorPrediction <= -800 => colorOutput := #822634e5 // 90% opacity
ColorPrediction <= -700 => colorOutput := #822634be // 80% opacity
ColorPrediction <= -600 => colorOutput := #822634b0 // 75% opacity
ColorPrediction <= -500 => colorOutput := #8226347a // 60% opacity
ColorPrediction <= -400 => colorOutput := #82263471 // 57% opacity
ColorPrediction <= -300 => colorOutput := #82263466 // 50% opacity
ColorPrediction <= -200 => colorOutput := #8226344c // 40% opacity
ColorPrediction <= -100 => colorOutput := #82263433 // 30% opacity
ColorPrediction >= 0 => colorOutput := #08998100 // Fully
transparent (fallback for negatives too)
=> colorOutput := #08998100 // Default fallback color (light gray or
red)
dashboardRedText = #ee787d
dashboardGreenText = #42bda8
dashboardGreenBackground = #284444
dashboardRedBackground = #49343e
tb = table.new(table_position, 8, 19
, bgcolor = dashboardbg
, border_color = #373a46
, border_width = 1
, frame_color = #373a46
, frame_width = 1)
f_sortMetrics(metrics, logic)
metricStart = array.get(metrics, 0)
metricEnd = array.get(metrics, (array.size(metrics)-1))
basemetricStart = array.get(metrics, 0)
basemetricEnd = array.get(basemetrics, (array.size(basemetrics)-1))
//log.info( " Sensitivity: " + str.tostring(basemetricStart.sensitivity) + ", Win
Rate: " + str.tostring(metricStart.winRate) + ", Net Profits: " +
str.tostring(metricStart.netProfits))
for i = 0 to array.size(metrics) - 1
metric = array.get(metrics, i)
if logic == "Winrate"
[Color]=ColorRangeFilter(metricStart.winRate, metric.winRate)
f_AODashboardCell(i + 3, metric,true,Color,#1e222d) // Adjusting
sensitivity for display
else if logic =="Profits"
[Color]=ColorRangeFilter(metricStart.netProfits, metric.netProfits)
f_AODashboardCell(i + 3, metric,false,#1e222d,Color)
//(int row,MetricRecord metric,bool IsWinRate,color winrateColor,color
netprofitsColor)
// Calculate grid
sqrtDifference = math.sqrt(array.size(metrics) - 1)
gridSize = sqrtDifference == math.round(sqrtDifference) ? int(sqrtDifference) :
int(math.ceil(sqrtDifference))
// Fill between the close and the trailing stop based on the trend
fill(Cs, ts, os == 1 ? close : tsl, os == 1 ? tsl : close,
os == 1 ? color.new(#089981, 60) : color(na),
os == 1 ? color(na) : color.new(#f23645, 60))
///////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////
// Define variables for buyClose, take profit, and stop loss levels
var float buyClose = 0
var float buyTakeProfitLevel = 0
var float buyStopLevel = 0
if buyEntry
BullEntry := true
else if sellEntry
BullEntry := false
else
BullEntry := BullEntry // No change in BullEntry if no buy/sell entry
// # ============================[Strategy TP/SL]============================ #
// ATR Calculation
atrValue = ta.atr(10) // Using a period of 10 for ATR
//------------------------------------------------------------------------------
//Bull condition
//-----------------------------------------------------------------------------{
//-----------------------------------------------------------------------------}
//------------------------------------------------------------------------------
//Sell Condition
//-----------------------------------------------------------------------------{
//-----------------------------------------------------------------------------}
// Take Profit Logic for Sell
sellTakeProfitLevel := ShortTpType == "Currency" ? (sellClose - ShortTpValue) :
ShortTpType == "%" ? (sellClose * (1 - ShortTpValue /
100)) :
ShortTpType == "ATR" ? (sellClose - (atrValue *
ShortTpValue)) :
ShortTpType == "Price" ? ShortTpValue :
na // Fallback in case none of the conditions are met
// # ============================[Strategy Exit]============================ #
//------------------------------------------------------------------------------
//Buy Condition
//-----------------------------------------------------------------------------{
//-----------------------------------------------------------------------------}
//Exit SL/TP
if exitLongSl and BullEntry
if exitLongSlCondition == "Crossing Over" and ta.crossover(src,
exitLongSlSource)
strategy.close("Sell", comment="SL")
if exitLongSlCondition == "Crossing Under" and ta.crossunder(src,
exitLongSlSource)
strategy.close("Sell", comment="SL")
if exitLongSlCondition == "Equal" and src == exitLongSlSource
strategy.close("Sell", comment="SL")
if exitLongSlCondition == "Greater Than" and src > exitLongSlSource
strategy.close("Sell", comment="SL")
if exitLongSlCondition == "Lower Than" and src < exitLongSlSource
strategy.close("Sell", comment="SL")
//------------------------------------------------------------------------------
//Sell Condition
//-----------------------------------------------------------------------------{
//-----------------------------------------------------------------------------}
//Exit SL/TP
if exitShortSl and not BullEntry
if exitShortSlCondition == "Crossing Over" and ta.crossover(src,
exitShortSlSource)
strategy.close("Buy", comment="SL")
if exitShortSlCondition == "Crossing Under" and ta.crossunder(src,
exitShortSlSource)
strategy.close("Buy", comment="SL")
if exitShortSlCondition == "Equal" and src == exitShortSlSource
strategy.close("Buy", comment="SL")
if exitShortSlCondition == "Greater Than" and src > exitShortSlSource
strategy.close("Buy", comment="SL")
if exitShortSlCondition == "Lower Than" and src < exitShortSlSource
strategy.close("Buy", comment="SL")