0% found this document useful (0 votes)
673 views25 pages

Lorentzian Classification Strategy by StrategiesForEveryone Modded

Uploaded by

bhargavboricha4
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
673 views25 pages

Lorentzian Classification Strategy by StrategiesForEveryone Modded

Uploaded by

bhargavboricha4
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
You are on page 1/ 25

// This source code is subject to the terms of the Mozilla Public License 2.

0 at
https://mozilla.org/MPL/2.0/
//
// Please, visit the main script that strategy is based in :) Machine Learning:
Lorentzian Classification/<<<< ==============================================
// Indicator developed by ©jdehorty
// Strategy devoleped by ©StrategiesForEVeryone

// @version=5
strategy('Lorentzian Classification Strategy by StrategiesForEveryone modded by
LUPEN', precision=2, initial_capital = 100000, process_orders_on_close = true,
calc_on_every_tick = true, commission_value = 0.03)

import jdehorty/MLExtensions/2 as ml
import jdehorty/KernelFunctions/2 as kernels

initial_message = input.bool(defval = true, title = "Show initial message", group =


"Initial message")
if barstate.islast and initial_message
label.new(bar_index, 0, "Please, read the entire post " + "\nfor a better
understanding." + "\nDo not forget to visit the original" + "\nindicator from
©jdehorty and leave your boost!", xloc = xloc.bar_index, yloc = yloc.abovebar,
textcolor = color.white, color = color.rgb(76, 175, 255, 4))

// ======================
// ==== Custom Types ====
// ======================

// This section uses PineScript's new Type syntax to define important data
structures
// used throughout the script.

type Settings
float source
int neighborsCount
int maxBarsBack
int featureCount
int colorCompression
bool showExits
bool useDynamicExits

type Label
int long
int short
int neutral

type FeatureArrays
array<float> f1
array<float> f2
array<float> f3
array<float> f4
array<float> f5

type FeatureSeries
float f1
float f2
float f3
float f4
float f5
type MLModel
int firstBarIndex
array<int> trainingLabels
int loopSize
float lastDistance
array<float> distancesArray
array<int> predictionsArray
int prediction

type FilterSettings
bool useVolatilityFilter
bool useRegimeFilter
bool useAdxFilter
float regimeThreshold
int adxThreshold

type Filter
bool volatility
bool regime
bool adx

// ==========================
// ==== Helper Functions ====
// ==========================

series_from(feature_string, _close, _high, _low, _hlc3, f_paramA, f_paramB) =>


switch feature_string
"RSI" => ml.n_rsi(_close, f_paramA, f_paramB)
"WT" => ml.n_wt(_hlc3, f_paramA, f_paramB)
"CCI" => ml.n_cci(_close, f_paramA, f_paramB)
"ADX" => ml.n_adx(_high, _low, _close, f_paramA)

get_lorentzian_distance(int i, int featureCount, FeatureSeries featureSeries,


FeatureArrays featureArrays) =>
switch featureCount
5 => math.log(1+math.abs(featureSeries.f1 - array.get(featureArrays.f1,
i))) +
math.log(1+math.abs(featureSeries.f2 - array.get(featureArrays.f2,
i))) +
math.log(1+math.abs(featureSeries.f3 - array.get(featureArrays.f3,
i))) +
math.log(1+math.abs(featureSeries.f4 - array.get(featureArrays.f4,
i))) +
math.log(1+math.abs(featureSeries.f5 - array.get(featureArrays.f5,
i)))
4 => math.log(1+math.abs(featureSeries.f1 - array.get(featureArrays.f1,
i))) +
math.log(1+math.abs(featureSeries.f2 - array.get(featureArrays.f2,
i))) +
math.log(1+math.abs(featureSeries.f3 - array.get(featureArrays.f3,
i))) +
math.log(1+math.abs(featureSeries.f4 - array.get(featureArrays.f4,
i)))
3 => math.log(1+math.abs(featureSeries.f1 - array.get(featureArrays.f1,
i))) +
math.log(1+math.abs(featureSeries.f2 - array.get(featureArrays.f2,
i))) +
math.log(1+math.abs(featureSeries.f3 - array.get(featureArrays.f3,
i)))
2 => math.log(1+math.abs(featureSeries.f1 - array.get(featureArrays.f1,
i))) +
math.log(1+math.abs(featureSeries.f2 - array.get(featureArrays.f2,
i)))

// ================
// ==== Inputs ====
// ================

// Settings Object: General User-Defined Inputs


Settings settings =
Settings.new(
input.source(title='Source', defval=close, group="General Settings",
tooltip="Source of the input data"),
input.int(title='Neighbors Count', defval=8, group="General Settings", minval=1,
maxval=100, step=1, tooltip="Number of neighbors to consider"),
input.int(title="Max Bars Back", defval=2000, group="General Settings", tooltip
= "Use this to increase or reduce the range of backtesting. If script use much time
to load, reduce this"),
input.int(title="Feature Count", defval=5, group="Feature Engineering",
minval=2, maxval=5, tooltip="Number of features to use for ML predictions."),
input.int(title="Color Compression", defval=1, group="General Settings",
minval=1, maxval=10, tooltip="Compression factor for adjusting the intensity of the
color scale."),
input.bool(title="Show Default Exits", defval=false, group="General Settings",
tooltip="Default exits occur exactly 4 bars after an entry signal. This corresponds
to the predefined length of a trade during the model's training process.",
inline="exits"),
input.bool(title="Use Dynamic Exits", defval=false, group="General Settings",
tooltip="Dynamic exits attempt to let profits ride by dynamically adjusting the
exit threshold based on kernel regression logic.", inline="exits")
)

// Trade Stats Settings


// Note: The trade stats section is NOT intended to be used as a replacement for
proper backtesting. It is intended to be used for calibration purposes only.
// showTradeStats = input.bool(false, 'Show Trade Stats', tooltip='Displays the
trade stats for a given configuration. Useful for optimizing the settings in the
Feature Engineering section. This should NOT replace backtesting and should be used
for calibration purposes only. Early Signal Flips represent instances where the
model changes signals before 4 bars elapses; high values can indicate choppy
(ranging) market conditions.', group="General Settings")
// useWorstCase = input.bool(false, "Use Worst Case Estimates", tooltip="Whether to
use the worst case scenario for backtesting. This option can be useful for creating
a conservative estimate that is based on close prices only, thus avoiding the
effects of intrabar repainting. This option assumes that the user does not enter
when the signal first appears and instead waits for the bar to close as
confirmation. On larger timeframes, this can mean entering after a large move has
already occurred. Leaving this option disabled is generally better for those that
use this indicator as a source of confluence and prefer estimates that demonstrate
discretionary mid-bar entries. Leaving this option enabled may be more consistent
with traditional backtesting results.", group="General Settings")

// Settings object for user-defined settings


FilterSettings filterSettings =
FilterSettings.new(
input.bool(title="Use Volatility Filter", defval=true, tooltip="Whether to use
the volatility filter.", group="Filters"),
input.bool(title="Use Regime Filter", defval=true, group="Filters",
inline="regime"),
input.bool(title="Use ADX Filter", defval=false, group="Filters", inline="adx"),
input.float(title="Threshold", defval=-0.1, minval=-10, maxval=10, step=0.1,
tooltip="Whether to use the trend detection filter. Threshold for detecting
Trending/Ranging markets.", group="Filters", inline="regime"),
input.int(title="Threshold", defval=20, minval=0, maxval=100, step=1,
tooltip="Whether to use the ADX filter. Threshold for detecting Trending/Ranging
markets.", group="Filters", inline="adx")
)

// Filter object for filtering the ML predictions


Filter filter =
Filter.new(
ml.filter_volatility(1, 10, filterSettings.useVolatilityFilter),
ml.regime_filter(ohlc4, filterSettings.regimeThreshold,
filterSettings.useRegimeFilter),
ml.filter_adx(settings.source, 14, filterSettings.adxThreshold,
filterSettings.useAdxFilter)
)

// Feature Variables: User-Defined Inputs for calculating Feature Series.


f1_string = input.string(title="Feature 1", options=["RSI", "WT", "CCI", "ADX"],
defval="RSI", inline = "01", tooltip="The first feature to use for ML
predictions.", group="Feature Engineering")
f1_paramA = input.int(title="Parameter A", tooltip="The primary parameter of
feature 1.", defval=14, inline = "02", group="Feature Engineering")
f1_paramB = input.int(title="Parameter B", tooltip="The secondary parameter of
feature 2 (if applicable).", defval=1, inline = "02", group="Feature Engineering")
f2_string = input.string(title="Feature 2", options=["RSI", "WT", "CCI", "ADX"],
defval="WT", inline = "03", tooltip="The second feature to use for ML
predictions.", group="Feature Engineering")
f2_paramA = input.int(title="Parameter A", tooltip="The primary parameter of
feature 2.", defval=10, inline = "04", group="Feature Engineering")
f2_paramB = input.int(title="Parameter B", tooltip="The secondary parameter of
feature 2 (if applicable).", defval=11, inline = "04", group="Feature Engineering")
f3_string = input.string(title="Feature 3", options=["RSI", "WT", "CCI", "ADX"],
defval="CCI", inline = "05", tooltip="The third feature to use for ML
predictions.", group="Feature Engineering")
f3_paramA = input.int(title="Parameter A", tooltip="The primary parameter of
feature 3.", defval=20, inline = "06", group="Feature Engineering")
f3_paramB = input.int(title="Parameter B", tooltip="The secondary parameter of
feature 3 (if applicable).", defval=1, inline = "06", group="Feature Engineering")
f4_string = input.string(title="Feature 4", options=["RSI", "WT", "CCI", "ADX"],
defval="ADX", inline = "07", tooltip="The fourth feature to use for ML
predictions.", group="Feature Engineering")
f4_paramA = input.int(title="Parameter A", tooltip="The primary parameter of
feature 4.", defval=20, inline = "08", group="Feature Engineering")
f4_paramB = input.int(title="Parameter B", tooltip="The secondary parameter of
feature 4 (if applicable).", defval=2, inline = "08", group="Feature Engineering")
f5_string = input.string(title="Feature 5", options=["RSI", "WT", "CCI", "ADX"],
defval="RSI", inline = "09", tooltip="The fifth feature to use for ML
predictions.", group="Feature Engineering")
f5_paramA = input.int(title="Parameter A", tooltip="The primary parameter of
feature 5.", defval=9, inline = "10", group="Feature Engineering")
f5_paramB = input.int(title="Parameter B", tooltip="The secondary parameter of
feature 5 (if applicable).", defval=1, inline = "10", group="Feature Engineering")

// FeatureSeries Object: Calculated Feature Series based on Feature Variables


featureSeries =
FeatureSeries.new(
series_from(f1_string, close, high, low, hlc3, f1_paramA, f1_paramB), // f1
series_from(f2_string, close, high, low, hlc3, f2_paramA, f2_paramB), // f2
series_from(f3_string, close, high, low, hlc3, f3_paramA, f3_paramB), // f3
series_from(f4_string, close, high, low, hlc3, f4_paramA, f4_paramB), // f4
series_from(f5_string, close, high, low, hlc3, f5_paramA, f5_paramB) // f5
)

// FeatureArrays Variables: Storage of Feature Series as Feature Arrays Optimized


for ML
// Note: These arrays cannot be dynamically created within the FeatureArrays Object
Initialization and thus must be set-up in advance.
var f1Array = array.new_float()
var f2Array = array.new_float()
var f3Array = array.new_float()
var f4Array = array.new_float()
var f5Array = array.new_float()
array.push(f1Array, featureSeries.f1)
array.push(f2Array, featureSeries.f2)
array.push(f3Array, featureSeries.f3)
array.push(f4Array, featureSeries.f4)
array.push(f5Array, featureSeries.f5)

// FeatureArrays Object: Storage of the calculated FeatureArrays into a single


object
featureArrays =
FeatureArrays.new(
f1Array, // f1
f2Array, // f2
f3Array, // f3
f4Array, // f4
f5Array // f5
)

// Label Object: Used for classifying historical data as training data for the ML
Model
Label direction_s =
Label.new(
long=1,
short=-1,
neutral=0
)

// Derived from General Settings


maxBarsBackIndex = last_bar_index >= settings.maxBarsBack ? last_bar_index -
settings.maxBarsBack : 0

// EMA Settings
useEmaFilter = input.bool(title="Use EMA Filter", defval=false, group="Filters",
inline="ema")
emaPeriod = input.int(title="Period", defval=200, minval=1, step=1,
group="Filters", inline="ema", tooltip="The period of the EMA used for the EMA
Filter.")
isEmaUptrend = useEmaFilter ? close > ta.ema(close, emaPeriod) : true
isEmaDowntrend = useEmaFilter ? close < ta.ema(close, emaPeriod) : true
useSmaFilter = input.bool(title="Use SMA Filter", defval=false, group="Filters",
inline="sma")
smaPeriod = input.int(title="Period", defval=200, minval=1, step=1,
group="Filters", inline="sma", tooltip="The period of the SMA used for the SMA
Filter.")
isSmaUptrend = useSmaFilter ? close > ta.sma(close, smaPeriod) : true
isSmaDowntrend = useSmaFilter ? close < ta.sma(close, smaPeriod) : true

// Nadaraya-Watson Kernel Regression Settings


useKernelFilter = input.bool(true, "Trade with Kernel", group="Kernel Settings",
inline="kernel")
showKernelEstimate = input.bool(false, "Show Kernel Estimate", group="Kernel
Settings", inline="kernel")
useKernelSmoothing = input.bool(false, "Enhance Kernel Smoothing", tooltip="Uses a
crossover based mechanism to smoothen kernel color changes. This often results in
less color transitions overall and may result in more ML entry signals being
generated.", inline='1', group='Kernel Settings')
h = input.int(8, 'Lookback Window', minval=3, tooltip='The number of bars used for
the estimation. This is a sliding value that represents the most recent historical
bars. Recommended range: 3-50', group="Kernel Settings", inline="kernel")
r = input.float(8., 'Relative Weighting', step=0.25, tooltip='Relative weighting of
time frames. As this value approaches zero, the longer time frames will exert more
influence on the estimation. As this value approaches infinity, the behavior of the
Rational Quadratic Kernel will become identical to the Gaussian kernel. Recommended
range: 0.25-25', group="Kernel Settings", inline="kernel")
x = input.int(25, "Regression Level", tooltip='Bar index on which to start
regression. Controls how tightly fit the kernel estimate is to the data. Smaller
values are a tighter fit. Larger values are a looser fit. Recommended range: 2-25',
group="Kernel Settings", inline="kernel")
lag = input.int(2, "Lag", tooltip="Lag for crossover detection. Lower values result
in earlier crossovers. Recommended range: 1-2", inline='1', group='Kernel
Settings')

// Display Settings
showBarColors = input.bool(false, "Show Bar Colors", tooltip="Whether to show the
bar colors.", group="Display Settings")
showBarPredictions = input.bool(defval = false, title = "Show Bar Prediction
Values", tooltip = "Will show the ML model's evaluation of each bar as an
integer.", group="Display Settings")
useAtrOffset = input.bool(defval = false, title = "Use ATR Offset", tooltip = "Will
use the ATR offset instead of the bar prediction offset.", group="Display
Settings")
barPredictionsOffset = input.float(0, "Bar Prediction Offset", minval=0,
tooltip="The offset of the bar predictions as a percentage from the bar high or
close.", group="Display Settings")

// =================================
// ==== Next Bar Classification ====
// =================================

// This model specializes specifically in predicting the direction_s of price


action over the course of the next 4 bars.
// To avoid complications with the ML model, this value is hardcoded to 4 bars but
support for other training lengths may be added in the future.
src = settings.source
y_train_series = src[4] < src[0] ? direction_s.short : src[4] > src[0] ?
direction_s.long : direction_s.neutral
var y_train_array = array.new_int(0)

// Variables used for ML Logic


var predictions = array.new_float(0)
var prediction = 0.
var signal = direction_s.neutral
var distances = array.new_float(0)

array.push(y_train_array, y_train_series)

// =========================
// ==== Core ML Logic ====
// =========================

lastDistance = -1.0
size = math.min(settings.maxBarsBack-1, array.size(y_train_array)-1)
sizeLoop = math.min(settings.maxBarsBack-1, size)

if bar_index >= maxBarsBackIndex //{


for i = 0 to sizeLoop //{
d = get_lorentzian_distance(i, settings.featureCount, featureSeries,
featureArrays)
if d >= lastDistance and i%4 //{
lastDistance := d
array.push(distances, d)
array.push(predictions, math.round(array.get(y_train_array, i)))
if array.size(predictions) > settings.neighborsCount //{
lastDistance := array.get(distances,
math.round(settings.neighborsCount*3/4))
array.shift(distances)
array.shift(predictions)
//}
//}
//}
prediction := array.sum(predictions)
//}

// ============================
// ==== Prediction Filters ====
// ============================

// User Defined Filters: Used for adjusting the frequency of the ML Model's
predictions
filter_all = filter.volatility and filter.regime and filter.adx

// Filtered Signal: The model's prediction of future price movement direction_s


with user-defined filters applied
signal := prediction > 0 and filter_all ? direction_s.long : prediction < 0 and
filter_all ? direction_s.short : nz(signal[1])

// Bar-Count Filters: Represents strict filters based on a pre-defined holding


period of 4 bars
var int barsHeld = 0
barsHeld := ta.change(signal) ? 0 : barsHeld + 1
isHeldFourBars = barsHeld == 4
isHeldLessThanFourBars = 0 < barsHeld and barsHeld < 4

// Fractal Filters: Derived from relative ============ Appearance ============s of


signals in a given time series fractal/segment with a default length of 4 bars
isDifferentSignalType = ta.change(signal)
isEarlySignalFlip = ta.change(signal) and (ta.change(signal[1]) or
ta.change(signal[2]) or ta.change(signal[3]))
isBuySignal = signal == direction_s.long and isEmaUptrend and isSmaUptrend
isSellSignal = signal == direction_s.short and isEmaDowntrend and isSmaDowntrend
isLastSignalBuy = signal[4] == direction_s.long and isEmaUptrend[4] and
isSmaUptrend[4]
isLastSignalSell = signal[4] == direction_s.short and isEmaDowntrend[4] and
isSmaDowntrend[4]
isNewBuySignal = isBuySignal and isDifferentSignalType
isNewSellSignal = isSellSignal and isDifferentSignalType

// Kernel Regression Filters: Filters based on Nadaraya-Watson Kernel Regression


using the Rational Quadratic Kernel
// For more information on this technique refer to my other open source indicator
located here:
// https://www.tradingview.com/script/AWNvbPRM-Nadaraya-Watson-Rational-Quadratic-
Kernel-Non-Repainting/
c_green = color.new(#009988, 20)
c_red = color.new(#CC3311, 20)
transparent = color.new(#000000, 100)
yhat1 = kernels.rationalQuadratic(settings.source, h, r, x)
yhat2 = kernels.gaussian(settings.source, h-lag, x)
kernelEstimate = yhat1
// Kernel Rates of Change
bool wasBearishRate = yhat1[2] > yhat1[1]
bool wasBullishRate = yhat1[2] < yhat1[1]
bool isBearishRate = yhat1[1] > yhat1
bool isBullishRate = yhat1[1] < yhat1
isBearishChange = isBearishRate and wasBullishRate
isBullishChange = isBullishRate and wasBearishRate
// Kernel Crossovers
bool isBullishCrossAlert = ta.crossover(yhat2, yhat1)
bool isBearishCrossAlert = ta.crossunder(yhat2, yhat1)
bool isBullishSmooth = yhat2 >= yhat1
bool isBearishSmooth = yhat2 <= yhat1
// Kernel Colors
color colorByCross = isBullishSmooth ? c_green : c_red
color colorByRate = isBullishRate ? c_green : c_red
color plotColor = showKernelEstimate ? (useKernelSmoothing ? colorByCross :
colorByRate) : transparent
plot(kernelEstimate, color=plotColor, linewidth=2, title="Kernel Regression
Estimate", display = display.all - display.price_scale - display.status_line)
// Alert Variables
bool alertBullish = useKernelSmoothing ? isBullishCrossAlert : isBullishChange
bool alertBearish = useKernelSmoothing ? isBearishCrossAlert : isBearishChange
// Bullish and Bearish Filters based on Kernel
isBullish = useKernelFilter ? (useKernelSmoothing ? isBullishSmooth :
isBullishRate) : true
isBearish = useKernelFilter ? (useKernelSmoothing ? isBearishSmooth :
isBearishRate) : true

// ===========================
// ==== Entries and Exits ====
// ===========================

inpFastPeriod = input.int(defval=45, title='MACD fast period', minval=1)


inpSlowPeriod = input.int(defval=90, title='MACD slow period', minval=1)
inpMacdSignal = input.int(defval=9, title='Signal period', minval=1)
inpSmoothPeriod = input.int(defval=5, title='Smoothing period', minval=1)
inpNormPeriod = input.int(defval=90, title='Normalization period', minval=1)
price = input(close, title='Price Source')
//

//
emaf = 0.0
emas = 0.0
val = 0.0
nval = 0.0
sig = 0.0
//

if bar_index > inpSlowPeriod


alphaf = 2.0 / (1.0 + math.max(inpFastPeriod, 1))
alphas = 2.0 / (1.0 + math.max(inpSlowPeriod, 1))
alphasig = 2.0 / (1.0 + math.max(inpMacdSignal, 1))
alphasm = 2.0 / (1.0 + math.max(inpSmoothPeriod, 1))

emaf := emaf[1] + alphaf * (price - emaf[1])


emas := emas[1] + alphas * (price - emas[1])
imacd = emaf - emas

mmax = ta.highest(imacd, inpNormPeriod)


mmin = ta.lowest(imacd, inpNormPeriod)
if mmin != mmax
nval := 2.0 * (imacd - mmin) / (mmax - mmin) - 1.0
nval
else
nval := 0
nval

val := val[1] + alphasm * (nval - val[1])


sig := sig[1] + alphasig * (val - sig[1])
sig

// plot(val, color=val > val[1] ? green : red, style=plot.style_line, linewidth=2,


title='Reg smooth MACD')

// Entry Conditions: Booleans for ML Model Position Entries


// startLongTrade = isNewBuySignal and isBullish and isEmaUptrend and isSmaUptrend
// startShortTrade = isNewSellSignal and isBearish and isEmaDowntrend and
isSmaDowntrend
// startLongTrade = isNewBuySignal and isBullish and isEmaUptrend and isSmaUptrend
and val > val[1]
// startShortTrade = isNewSellSignal and isBearish and isEmaDowntrend and
isSmaDowntrend and val < val[1]
// startLongTrade = isNewBuySignal and isBullish and isEmaUptrend and isSmaUptrend
and val > 0
// startShortTrade = isNewSellSignal and isBearish and isEmaDowntrend and
isSmaDowntrend and val < 0
// startLongTrade = isNewBuySignal and isBullish and isEmaUptrend and isSmaUptrend
and val > sig
// startShortTrade = isNewSellSignal and isBearish and isEmaDowntrend and
isSmaDowntrend and val < sig
// startLongTrade = isNewBuySignal and isBullish and isEmaUptrend and isSmaUptrend
and sig > val
// startShortTrade = isNewSellSignal and isBearish and isEmaDowntrend and
isSmaDowntrend and sig < val
startLongTrade = isNewBuySignal and isBullish and isEmaUptrend and isSmaUptrend and
val > sig and val > 0
startShortTrade = isNewSellSignal and isBearish and isEmaDowntrend and
isSmaDowntrend and val < sig and val < 0

// Dynamic Exit Conditions: Booleans for ML Model Position Exits based on Fractal
Filters and Kernel Regression Filters
lastSignalWasBullish = ta.barssince(startLongTrade) < ta.barssince(startShortTrade)
lastSignalWasBearish = ta.barssince(startShortTrade) < ta.barssince(startLongTrade)
barsSinceRedEntry = ta.barssince(startShortTrade)
barsSinceRedExit = ta.barssince(alertBullish)
barsSinceGreenEntry = ta.barssince(startLongTrade)
barsSinceGreenExit = ta.barssince(alertBearish)
isValidShortExit = barsSinceRedExit > barsSinceRedEntry
isValidLongExit = barsSinceGreenExit > barsSinceGreenEntry
endLongTradeDynamic = (isBearishChange and isValidLongExit[1])
endShortTradeDynamic = (isBullishChange and isValidShortExit[1])

// Fixed Exit Conditions: Booleans for ML Model Position Exits based on a Bar-Count
Filters
endLongTradeStrict = ((isHeldFourBars and isLastSignalBuy) or
(isHeldLessThanFourBars and isNewSellSignal and isLastSignalBuy)) and
startLongTrade[4]
endShortTradeStrict = ((isHeldFourBars and isLastSignalSell) or
(isHeldLessThanFourBars and isNewBuySignal and isLastSignalSell)) and
startShortTrade[4]
isDynamicExitValid = not useEmaFilter and not useSmaFilter and not
useKernelSmoothing
endLongTrade = settings.useDynamicExits and isDynamicExitValid ?
endLongTradeDynamic : endLongTradeStrict
endShortTrade = settings.useDynamicExits and isDynamicExitValid ?
endShortTradeDynamic : endShortTradeStrict

// =========================
// ==== Plotting Labels ====
// =========================

// Note: These will not repaint once the most recent bar has fully closed. By
default, signals appear over the last closed bar; to override this behavior set
offset=0.
//plotshape(startLongTrade ? low : na, 'Buy', shape.labelup, location.belowbar,
color=ml.color_green(prediction), size=size.small, offset=0, display = display.all
- display.price_scale - display.status_line)
//plotshape(startShortTrade ? high : na, 'Sell', shape.labeldown,
location.abovebar, ml.color_red(-prediction), size=size.small, offset=0, display =
display.all - display.price_scale - display.status_line)
//plotshape(endLongTrade and settings.showExits ? high : na, 'StopBuy',
shape.xcross, location.absolute, color=#3AFF17, size=size.tiny, offset=0, display =
display.all - display.price_scale - display.status_line)
//plotshape(endShortTrade and settings.showExits ? low : na, 'StopSell',
shape.xcross, location.absolute, color=#FD1707, size=size.tiny, offset=0, display =
display.all - display.price_scale - display.status_line)

// ================
// ==== Alerts ====
// ================

// Separate Alerts for Entries and Exits


//alertcondition(startLongTrade, title='Open Long ▲', message='LDC Open Long ▲ |
{{ticker}}@{{close}} | ({{interval}})')
//alertcondition(endLongTrade, title='Close Long ▲', message='LDC Close Long ▲ |
{{ticker}}@{{close}} | ({{interval}})')
//alertcondition(startShortTrade, title='Open Short ▼', message='LDC Open Short |
{{ticker}}@{{close}} | ({{interval}})')
//alertcondition(endShortTrade, title='Close Short ▼', message='LDC Close Short ▼ |
{{ticker}}@{{close}} | ({{interval}})')
//
//// Combined Alerts for Entries and Exits
//alertcondition(startShortTrade or startLongTrade, title='Open Position ▲▼',
message='LDC Open Position ▲▼ | {{ticker}}@{{close}} | ({{interval}})')
//alertcondition(endShortTrade or endLongTrade, title='Close Position ▲▼',
message='LDC Close Position ▲▼ | {{ticker}}@[{{close}}] | ({{interval}})')
//
//// Kernel Estimate Alerts
//alertcondition(condition=alertBullish, title='Kernel Bullish Color Change',
message='LDC Kernel Bullish ▲ | {{ticker}}@{{close}} | ({{interval}})')
//alertcondition(condition=alertBearish, title='Kernel Bearish Color Change',
message='LDC Kernel Bearish ▼ | {{ticker}}@{{close}} | ({{interval}})')

// =========================
// ==== Display Signals ====
// =========================

atrSpaced = useAtrOffset ? ta.atr(1) : na


compressionFactor = settings.neighborsCount / settings.colorCompression
c_pred = prediction > 0 ? color.from_gradient(prediction, 0, compressionFactor,
#787b86, #009988) : prediction <= 0 ? color.from_gradient(prediction, -
compressionFactor, 0, #CC3311, #787b86) : na
c_label = showBarPredictions ? c_pred : na
c_bars = showBarColors ? color.new(c_pred, 50) : na
x_val = bar_index
y_val = useAtrOffset ? prediction > 0 ? high + atrSpaced: low - atrSpaced :
prediction > 0 ? high + hl2*barPredictionsOffset/20 : low -
hl2*barPredictionsOffset/30
label.new(x_val, y_val, str.tostring(prediction), xloc.bar_index, yloc.price,
color.new(color.white, 100), label.style_label_up, c_label, size.normal,
text.align_left)
barcolor(showBarColors ? color.new(c_pred, 50) : na)
//
===================================================================================
===================================================================================
===================================================================================
=====================================
// ====================================== Strategy code
================================================================

// ------ Inputs for calculating our amount position --------

initial_actual_capital = input.float(defval=10000, title = "Enter initial/current


capital", group = "============ Position amount calculator ===========")
risk_c = input.float(2.5, '% account risk per trade', step=1, group = "============
Position amount calculator ===========", tooltip = "Percentage of total account to
risk per trade. The USD value that should be used to risk the inserted percentage
of the account. Appears as a yellow number in the upper left corner")

// ------ Date filter ---------


initial_date = input.time(title="Initial date", defval=timestamp("10 Feb 2014 13:30
+0000"), group="============ Time filter ============ ", tooltip="Enter the start
date and time of the strategy")
final_date = input.time(title="Final date", defval=timestamp("01 Jan 2030 19:30
+0000"), group="============ Time filter ============ ", tooltip="Enter the end
date and time of the strategy")
dateFilter(int st, int et) => time >= st and time <= et
colorDate = input.bool(defval=false, title="Date background", tooltip = "Add color
to the period of time of the strategy tester")
bgcolor(colorDate and dateFilter(initial_date, final_date) ? color.new(color.blue,
transp=90) : na)
date = dateFilter(initial_date, final_date)

// ------ Session limits ------

timeSession = input.session(title="Time session", defval="0000-2400",


group="============ Time filter ============ ", tooltip="Session time to operate.
It may be different depending on your time zone, you have to find the correct hours
manually.")
colorBG = input.bool(title="Session background", defval=false, tooltip = "Add
color to session time background")
inSession(sess) => na(time(timeframe.period, sess + ':1234567')) == false
bgcolor(inSession(timeSession) and colorBG ? color.rgb(0, 38, 255, 84) : na)

//
===================================================================================
============================================================
// ------------ Super Trend ----------

atrPeriod = input(9, "ATR Length SuperTrend", group = "========= Super Trend filter
==========")
factor = input.float(2.5, "Factor SuperTrend", step = 0.05, group = "=========
Super Trend filter ==========")
[supertrend, direction_supertrend] = ta.supertrend(factor, atrPeriod)
show_supertrend = input.bool(defval = false, title="Show supertrend ?", group =
"============ Appearance ============")
bodyMiddle = plot(show_supertrend ? ((open + close) / 2) : na,
display=display.none)
upTrend = plot(show_supertrend and direction_supertrend < 0 ? supertrend : na, "Up
Trend", color = color.green, style=plot.style_linebr, display = display.all -
display.status_line)
downTrend = plot(show_supertrend and direction_supertrend > 0 ? supertrend : na,
"Down Trend", color = color.red, style=plot.style_linebr, display = display.all -
display.status_line)
fill(bodyMiddle, upTrend, color.new(color.green, 95), fillgaps=false, title =
"Supertrend background")
fill(bodyMiddle, downTrend, color.new(color.red, 95), fillgaps=false, title =
"Supertrend background")
up_trend_plot = direction_supertrend < 0
down_trend_plot = direction_supertrend > 0

// ----------- Ema ----------------------

ema = input.int(200, title='Ema length', minval=1, maxval=500, group =


"============ Trend ============")
ema200 = ta.ema(close, ema)
bullish = close > ema200
bearish = close < ema200
show_ema = input.bool(defval=true, title="Show ema ?", group = "============
Appearance ============")
plot(show_ema ? ema200 : na, title = "Ema", color=color.white, linewidth=2, display
= display.all - display.status_line - display.price_scale)

//
===================================================================================
============================================================
// -------------- Atr stop loss by garethyeo (modified) -----------------

source_atr = input(close, title='Source', group = "================== Stop loss


==================", inline = "A")
length_atr = input.int(14, minval=1, title='Period', group = "==================
Stop loss ==================" , inline = "A")
multiplier = input.float(1.5, minval=0.1, step=0.1, title='Atr multiplier', group =
"================== Stop loss ==================", inline = "A", tooltip = "Defines
the stop loss distance based on the Atr stop loss indicator")
show_stoploss = input.bool(defval = true, title = "Show stop loss ?", group =
"============ Appearance ============")
var float shortStopLoss = na
var float longStopLoss = na
var float atr_past_candle_long = na
var float atr_past_candle_short = na
candle_of_stoploss = input.string(defval = "Current candle", title = "Stop loss
source for atr stoploss", group = "================== Stop loss
==================", options = ["Current candle","Past candle"])
if candle_of_stoploss == "Current candle"
shortStopLoss := source_atr + ta.atr(length_atr) * multiplier
longStopLoss := source_atr - ta.atr(length_atr) * multiplier
if candle_of_stoploss == "Past candle"
shortStopLoss := close[1] + ta.atr(length_atr)[1] * multiplier[1]
longStopLoss := close[1] - ta.atr(length_atr)[1] * multiplier[1]

// --------- Stop loss based in last swing high/low --------

high_bars = input.int(defval = 10, title = "Highest price bars: ", group =


"================== Stop loss ==================")
low_bars = input.int(defval = 10, title = "Lowest price bars: ", group =
"================== Stop loss ==================")
stop_high = ta.highest(high, high_bars)
stop_low = ta.lowest(low, low_bars)

// --------- Stop loss source selection ---------------

stoploss_type = input.string(defval = "Atr stop loss", title = "General stop loss


source", group = "================== Stop loss ==================", options = ["Atr
stop loss","Swing high/low"])
if stoploss_type == "Atr stop loss"
shortStopLoss := source_atr + ta.atr(length_atr) * multiplier
longStopLoss := source_atr - ta.atr(length_atr) * multiplier
if candle_of_stoploss == "Past candle" and stoploss_type == "Atr stop loss"
shortStopLoss := close[1] + ta.atr(length_atr)[1] * multiplier[1]
longStopLoss := close[1] - ta.atr(length_atr)[1] * multiplier[1]
if stoploss_type == "Swing high/low"
shortStopLoss := stop_high
longStopLoss := stop_low

// ======================================== Add/withdraw money frequently


(>>>Beta<<<) ==============================================================
// Declare some variables =========================================================

var initial_capital = strategy.initial_capital


var initial_capital_a = strategy.initial_capital
var initial_capital_w = strategy.initial_capital
var float capital_added = 0
var float balance = strategy.initial_capital
var prev_month = 0
var float amount = 0
var add_frequency = 0
var withdraw_frequency = 0

// Choose how often the strategy adds money


=========================================================

add_money_frequency = input.string("Monthly", title = "Choose how often would you


add money", options = ["Monthly","Weekly","Daily","Yearly"], group =
"=============== Adding money frequently ===============")
amount_to_add = input.float(defval = 10, title = "How much you want to add ?",
group = "=============== Adding money frequently ===============")

if add_money_frequency == "Monthly"
add_frequency := month
if add_money_frequency == "Weekly"
add_frequency := weekofyear
if add_money_frequency == "Daily"
add_frequency := dayofweek
if add_money_frequency == "Yearly"
add_frequency := year

// Choose if you want to add money or not ====================================

add_money = input.string("No", title = "Add money from time to time ?", options =
["Yes","No"] , group = "=============== Adding money frequently ===============")

if add_frequency != add_frequency[1] and add_money == "Yes" and date


initial_capital_a += amount_to_add
initial_capital += amount_to_add
balance := strategy.netprofit + initial_capital

// Choose how often the strategy withdraws money


=========================================================

amount_to_withdraw = input.string("Fixed", title = "Withdraw based in fixed amounts


or percentage of earnings", options = ["%","Fixed"], group = "===============
Withdraw money frequently ===============")
amount_for_withdraw = input.float(defval = 2, title = "How much you want to
withdraw (fixed amount) ?", group = "=============== Withdraw money frequently
===============")
withdraw_money_frequency = input.string("Monthly", title = "Choose how often would
you withdraw money", options = ["Monthly","Weekly","Daily","Yearly"], group =
"=============== Withdraw money frequently ===============")

// We use this for being able to choose the frequency of withdrawing money:
if withdraw_money_frequency == "Monthly"
withdraw_frequency := month
if withdraw_money_frequency == "Weekly"
withdraw_frequency := weekofyear
if withdraw_money_frequency == "Daily"
withdraw_frequency := dayofweek
if withdraw_money_frequency == "Yearly"
withdraw_frequency := year

// Choose if you want to withdraw money or not =============================

withdraw_money = input.string("No", title = "Withdraw money from time to time ?",


options = ["Yes","No"], group = "=============== Withdraw money frequently
===============")
percentage_of_earnings = input.float(10, title = "Percentage of earnings", group =
"=============== Withdraw money frequently ===============", tooltip = "Use this if
withdraw is based in % of earnings")

// Percentage of earnings:
if withdraw_frequency != withdraw_frequency[1] and withdraw_money == "Yes" and
amount_to_withdraw == "%" and date and strategy.netprofit>0
initial_capital_w -= strategy.netprofit * (percentage_of_earnings / 100)
initial_capital -= strategy.netprofit * (percentage_of_earnings / 100)
balance := strategy.netprofit + initial_capital
// Fixed amount:
if withdraw_frequency != withdraw_frequency[1] and withdraw_money == "Yes" and
amount_to_withdraw == "Fixed" and date and strategy.netprofit>0
initial_capital_w -= amount_for_withdraw
initial_capital -= amount_for_withdraw
balance := strategy.netprofit + initial_capital

// Logic

if withdraw_money == "Yes" and add_money == "No"


amount := balance
if withdraw_money =="Yes" and add_money =="Yes"
amount := balance
if withdraw_money == "No" and add_money == "Yes"
amount := balance
if withdraw_money == "No" and add_money == "No"
amount := strategy.equity

//
===================================================================================
============================================================
// ------------- Money management --------------

strategy_contracts = amount / close


distance_sl_long = -1 * (longStopLoss - close) / close
distance_sl_short = (shortStopLoss - close) / close
risk = input.float(2.5, '% Account risk per trade for backtesting', step=1, group =
"============ Risk management for trades ============", tooltip = "Percentage of
total account to risk per trade if fixed amounts is deactivated")
long_amount = strategy_contracts * (risk / 100) / distance_sl_long
short_amount = strategy_contracts * (risk / 100) / distance_sl_short

leverage=input.bool(defval=true, title="Use leverage for backtesting ?", group =


"============ Risk management for trades ============", tooltip = "If it is
activated, there will be no monetary units or amount of assets limit for each
operation (That is, each operation will not be affected by the initial / current
capital since it would be using leverage). If it is deactivated, the monetary units
or the amount of assets to use for each operation will be limited by the
initial/current capital.")
if not leverage and long_amount>strategy_contracts
long_amount:=amount/close

if not leverage and short_amount>strategy_contracts


short_amount:=amount/close

// ---- Fixed amounts ----

fixed_amounts = input.bool(defval = false, title = "Fixed amounts ?", group =


"============ Risk management for trades ============", tooltip = "If you activate
this, the backtester will use fixed amounts")
fixed_amount_input = input.float(defval = 1000, title = "Fixed amount in usd",
group = "============ Risk management for trades ============")
if fixed_amounts
long_amount := fixed_amount_input / close
short_amount := fixed_amount_input / close

// ---------- Risk management ---------------

risk_reward_breakeven_long= input.float(title="Risk/reward for breakeven long",


defval=1.0, step=0.1, group = "============ Risk management for trades
============")
risk_reward_take_profit_long= input.float(title="Risk/reward for take profit long",
defval=3.0, step=0.1, group = "============ Risk management for trades
============")
risk_reward_breakeven_short= input.float(title="Risk/reward for break even short",
defval=1.0, step=0.1, group = "============ Risk management for trades
============")
risk_reward_take_profit_short= input.float(title="Risk/reward for take profit
short", defval=3.0, step=0.1, group = "============ Risk management for trades
============")
tp_percent=input.float(title="% of trade for first take profit", defval=50, step=5,
group = "============ Risk management for trades ============", tooltip = "Closing
percentage of the current position when the first take profit is reached.")

//
===================================================================================
============================================================
// ------------ Trade conditions ---------------
// Entry Conditions: Booleans for ML Model Position Entries
//startLongTrade = isNewBuySignal and isBullish and isEmaUptrend and isSmaUptrend
//startShortTrade = isNewSellSignal and isBearish and isEmaDowntrend and
isSmaDowntrend
//endLongTrade = settings.useDynamicExits and isDynamicExitValid ?
endLongTradeDynamic : endLongTradeStrict
//endShortTrade = settings.useDynamicExits and isDynamicExitValid ?
endShortTradeDynamic : endShortTradeStrict
//bullish := close > ema200
//bearish := close < ema200
bought = strategy.position_size > 0
sold = strategy.position_size < 0
buy = startLongTrade
sell = startShortTrade
var float total_commissions_value = 0
var float commission_value_l = 0
var float commission_value_s = 0
var float sl_long = na
var float sl_short = na
var float be_long = na
var float be_short = na
var float tp_long = na
var float tp_short = na
var int totaltrades = 0

close_withsupertrend = input.bool(defval = true, title = "Close positions with


supertrend ?", group = "============ Positions management ============")
closeshort_supertrend=ta.crossover(close, supertrend)
closelong_supertrend=ta.crossunder(close, supertrend)

if not bought
be_long:=na
sl_long:=na
tp_long:=na
if not sold
be_short:=na
sl_short:=na
tp_short:=na
long_positions = input.bool(defval = true, title = "Long positions ?", group =
"============ Positions management ============")
short_positions = input.bool(defval = true, title = "Short positions ?", group =
"============ Positions management ============")
use_takeprofit = input.bool(defval = true, title = "Use take profit ?", group =
"============ Risk management for trades ============")
use_breakeven = input.bool(defval = true, title = "Use break even ?", group =
"============ Risk management for trades ============")
close_only_tp = input.bool(defval = false, title = "Close just with take profit ?",
group = "============ Risk management for trades ============", tooltip = "Activate
if you just want to exit from a position until reaching take profit or stop loss.
If it´s activated, change % of closing by tp to 100%")
ema_filter_long = input.bool(defval = true, title = "Ema filter for long
positions ?", group = "============ Positions management ============", tooltip =
"Activate if you just want to long above 200 ema")
ema_filter_short = input.bool(defval = true, title = "Ema filter for short
positions ?", group = "============ Positions management ============", tooltip =
"Activate if you just want to short under 200 ema")
commission_percent = input.float(0.03, title = "Commission value in %", group =
"============ Positions management ============", tooltip = "Set the % of
commission. For example, when you enter into a position, you have a commission of
0.04% per entry and 0.04% per exit. You have also to change this value in
properties for getting a real return in backtest. (in this case, 0.04%)")

if fixed_amounts
commission_value_l := (close * (long_amount) * (commission_percent/100))
commission_value_s := (close * (short_amount) * (commission_percent/100))
if not fixed_amounts
commission_value_l := (close * ((strategy_contracts * (risk / 100)) /
distance_sl_long) * (commission_percent/100))
commission_value_s := (close * ((strategy_contracts * (risk / 100)) /
distance_sl_short) * (commission_percent/100))

// ======================= Strategy
===================================================================================
================================

// Long position with take profit

if not bought and buy and date and long_positions and inSession(timeSession) and
use_takeprofit and not ema_filter_long
sl_long:=longStopLoss
long_stoploss_distance = close - longStopLoss
be_long := close + long_stoploss_distance * risk_reward_breakeven_long
tp_long:=close+(long_stoploss_distance*risk_reward_take_profit_long)
total_commissions_value += commission_value_l
strategy.entry('L', strategy.long, long_amount, alert_message = "Long")
strategy.exit("Tp", "L", stop=sl_long, limit=tp_long, qty_percent=tp_percent)
strategy.exit('Exit', 'L', stop=sl_long)
if bought and high > be_long and use_breakeven
sl_long := strategy.position_avg_price
strategy.exit("Tp", "L", stop=sl_long, limit=tp_long, qty_percent=tp_percent)
strategy.exit('Exit', 'L', stop=sl_long)
if bought and sell and strategy.openprofit>0 and not close_only_tp or bought and
closelong_supertrend and close_withsupertrend and strategy.openprofit>0 and not
close_only_tp
strategy.close("L", comment="CL")
balance := balance + strategy.openprofit

// Long position without take profit

if not bought and buy and date and long_positions and inSession(timeSession) and
not ema_filter_long
sl_long:=longStopLoss
long_stoploss_distance = close - longStopLoss
be_long := close + long_stoploss_distance * risk_reward_breakeven_long
total_commissions_value += commission_value_l
strategy.entry('L', strategy.long, long_amount, alert_message = "Long")
strategy.exit('Exit', 'L', stop=sl_long)
if bought and high > be_long and use_breakeven
sl_long := strategy.position_avg_price
strategy.exit('Exit', 'L', stop=sl_long)
if bought and sell and strategy.openprofit>0
strategy.close("L", comment="CL")
balance := balance + strategy.openprofit

// Short position with take profit

if not sold and sell and date and short_positions and inSession(timeSession) and
use_takeprofit and not ema_filter_short
sl_short:=shortStopLoss
short_stoploss_distance=shortStopLoss - close
be_short:=((short_stoploss_distance*risk_reward_breakeven_short)-close)*-1
tp_short:=((short_stoploss_distance*risk_reward_take_profit_short)-close)*-1
total_commissions_value += commission_value_s
strategy.entry("S", strategy.short, short_amount, alert_message = "Short")
strategy.exit("Tp", "S", stop=sl_short, limit=tp_short, qty_percent=tp_percent)
strategy.exit("Exit", "S", stop=sl_short)
if sold and low < be_short and use_breakeven
sl_short:=strategy.position_avg_price
strategy.exit("Tp", "S", stop=sl_short, limit=tp_short, qty_percent=tp_percent)
strategy.exit("Exit", "S", stop=sl_short)
if sold and buy and strategy.openprofit>0 and not close_only_tp or sold and
closeshort_supertrend and close_withsupertrend and strategy.openprofit>0 and not
close_only_tp
strategy.close("S", comment="CS")
balance := balance + strategy.openprofit

// Short position without take profit

if not sold and sell and date and short_positions and inSession(timeSession) and
not ema_filter_short
sl_short:=shortStopLoss
short_stoploss_distance=shortStopLoss - close
be_short:=((short_stoploss_distance*risk_reward_breakeven_short)-close)*-1
total_commissions_value += commission_value_s
strategy.entry("S", strategy.short, short_amount, alert_message = "Short")
strategy.exit("Exit", "S", stop=sl_short)
if sold and low < be_short and use_breakeven
sl_short:=strategy.position_avg_price
strategy.exit("Exit", "S", stop=sl_short)
if sold and buy and strategy.openprofit>0
strategy.close("S", comment="CS")
balance := balance + strategy.openprofit

//
===================================================================================
============================================================

// Long position with ema filter

// With take profit

if not bought and buy and date and long_positions and inSession(timeSession) and
use_takeprofit and bullish and ema_filter_long
sl_long:=longStopLoss
long_stoploss_distance = close - longStopLoss
be_long := close + long_stoploss_distance * risk_reward_breakeven_long
tp_long:=close+(long_stoploss_distance*risk_reward_take_profit_long)
total_commissions_value += commission_value_l
strategy.entry('L', strategy.long, long_amount, alert_message = "Long")
strategy.exit("Tp", "L", stop=sl_long, limit=tp_long, qty_percent=tp_percent)
strategy.exit('Exit', 'L', stop=sl_long)
if bought and high > be_long and use_breakeven
sl_long := strategy.position_avg_price
strategy.exit("Tp", "L", stop=sl_long, limit=tp_long, qty_percent=tp_percent)
strategy.exit('Exit', 'L', stop=sl_long)
if bought and sell and strategy.openprofit>0 and not close_only_tp or bought and
closelong_supertrend and close_withsupertrend and strategy.openprofit>0 and not
close_only_tp
strategy.close("L", comment="CL")
balance := balance + strategy.openprofit

// Without take profit

if not bought and buy and date and long_positions and inSession(timeSession) and
bullish and ema_filter_long
sl_long:=longStopLoss
long_stoploss_distance = close - longStopLoss
be_long := close + long_stoploss_distance * risk_reward_breakeven_long
total_commissions_value += commission_value_l
strategy.entry('L', strategy.long, long_amount, alert_message = "Long")
strategy.exit('Exit', 'L', stop=sl_long)
if bought and high > be_long and use_breakeven
sl_long := strategy.position_avg_price
strategy.exit('Exit', 'L', stop=sl_long)
if bought and sell and strategy.openprofit>0
strategy.close("L", comment="CL")
balance := balance + strategy.openprofit
// Short positon with ema filter

// With take profit


if not sold and sell and date and short_positions and inSession(timeSession) and
use_takeprofit and bearish and ema_filter_short
sl_short:=shortStopLoss
short_stoploss_distance=shortStopLoss - close
be_short:=((short_stoploss_distance*risk_reward_breakeven_short)-close)*-1
tp_short:=((short_stoploss_distance*risk_reward_take_profit_short)-close)*-1
total_commissions_value += commission_value_s
strategy.entry("S", strategy.short, short_amount, alert_message = "Short")
strategy.exit("Tp", "S", stop=sl_short, limit=tp_short, qty_percent=tp_percent)
strategy.exit("Exit", "S", stop=sl_short)
if sold and low < be_short and use_breakeven
sl_short:=strategy.position_avg_price
strategy.exit("Tp", "S", stop=sl_short, limit=tp_short, qty_percent=tp_percent)
strategy.exit("Exit", "S", stop=sl_short)
if sold and buy and strategy.openprofit>0 and not close_only_tp or sold and
closeshort_supertrend and close_withsupertrend and strategy.openprofit>0 and not
close_only_tp
strategy.close("S", comment="CS")
balance := balance + strategy.openprofit

// Without take profit

if not sold and sell and date and short_positions and inSession(timeSession) and
bearish and ema_filter_short
sl_short:=shortStopLoss
short_stoploss_distance=shortStopLoss - close
be_short:=((short_stoploss_distance*risk_reward_breakeven_short)-close)*-1
total_commissions_value += commission_value_s
strategy.entry("S", strategy.short, short_amount, alert_message = "Short")
strategy.exit("Exit", "S", stop=sl_short)
if sold and low < be_short and use_breakeven
sl_short:=strategy.position_avg_price
strategy.exit("Exit", "S", stop=sl_short)
if sold and buy and strategy.openprofit>0
strategy.close("S", comment="CS")
balance := balance + strategy.openprofit

//
===================================================================================
============================================================

// ---------- Draw positions and signals on chart (strategy as an indicator)


-------------

if high>tp_long
tp_long:=na
if low<tp_short
tp_short:=na
if high>be_long
be_long:=na
if low<be_short
be_short:=na

show_position_on_chart = input.bool(defval=true, title="Draw position on chart ?",


group = "============ Appearance ============", tooltip = "Activate to graphically
display profit, stop loss and break even")
position_price = plot(show_position_on_chart? strategy.position_avg_price : na,
style=plot.style_linebr, color = color.new(#ffffff, 10), linewidth = 1, display =
display.all - display.status_line - display.price_scale)

sl_long_price = plot(show_position_on_chart and bought ? sl_long : na, style =


plot.style_linebr, color = color.new(color.red, 10), linewidth = 1, display =
display.all - display.status_line - display.price_scale)
sl_short_price = plot(show_position_on_chart and sold ? sl_short : na, style =
plot.style_linebr, color = color.new(color.red, 10), linewidth = 1, display =
display.all - display.status_line - display.price_scale)

tp_long_price = plot(bought and show_position_on_chart and use_takeprofit?


tp_long : na, style = plot.style_linebr, color = color.new(#4cd350, 10), linewidth
= 1, display = display.all - display.status_line - display.price_scale)
tp_short_price = plot(sold and show_position_on_chart and use_takeprofit?
tp_short : na, style = plot.style_linebr, color = color.new(#4cd350, 10), linewidth
= 1, display = display.all - display.status_line - display.price_scale)

breakeven_long = plot(bought and high<be_long and show_position_on_chart and


use_breakeven? be_long : na , style = plot.style_linebr, color = color.new(#1fc9fd,
60), linewidth = 1, display = display.all - display.status_line -
display.price_scale)
breakeven_short = plot(sold and low>be_short and show_position_on_chart and
use_breakeven? be_short : na , style = plot.style_linebr, color =
color.new(#1fc9fd, 60), linewidth = 1, display = display.all - display.status_line
- display.price_scale)

show_tpbe_on_chart = input.bool(defval=true, title="Draw first take


profit/breakeven price on chart ?", group = "============ Appearance ============",
tooltip = "Activate to display take profit and breakeven price. It appears as a
green point in the chart")
long_stoploss_distance = close - longStopLoss
short_stoploss_distance=shortStopLoss - close
be_long_plot = close + long_stoploss_distance * risk_reward_breakeven_long
be_short_plot =((short_stoploss_distance*risk_reward_breakeven_short)-close)*-1
tp_long_plot = close+(long_stoploss_distance*risk_reward_take_profit_long)
tp_short_plot = ((short_stoploss_distance*risk_reward_take_profit_short)-close)*-1
plot(show_tpbe_on_chart and buy and use_breakeven and bullish and ema_filter_long
or show_tpbe_on_chart and buy and use_breakeven and not ema_filter_long ?
be_long_plot : na, color=color.new(#1fc9fd, 10), style = plot.style_circles,
linewidth = 2, display = display.all - display.price_scale)
plot(show_tpbe_on_chart and sell and use_breakeven and bearish and ema_filter_short
or show_tpbe_on_chart and sell and use_breakeven and not ema_filter_short ?
be_short_plot : na, color=color.new(#1fc9fd, 10), style = plot.style_circles,
linewidth = 2, display = display.all - display.price_scale)
plot(show_tpbe_on_chart and buy and use_takeprofit and bullish and ema_filter_long
or show_tpbe_on_chart and buy and use_takeprofit and not ema_filter_long?
tp_long_plot : na, color=color.new(#4cd350, 10), style = plot.style_circles,
linewidth = 2, display = display.all - display.price_scale)
plot(show_tpbe_on_chart and sell and use_takeprofit and bearish and
ema_filter_short or show_tpbe_on_chart and sell and use_takeprofit and not
ema_filter_short? tp_short_plot : na, color=color.new(#4cd350, 10), style =
plot.style_circles, linewidth = 2, display = display.all - display.price_scale)
plot(show_stoploss and buy and bullish and ema_filter_long or show_stoploss and buy
and not ema_filter_long ? longStopLoss : na, title = "stop loss long", color =
color.white, style = plot.style_circles, linewidth = 2)
plot(show_stoploss and sell and bearish and ema_filter_short or show_stoploss and
sell and not ema_filter_long ? shortStopLoss : na, title = "stop loss short", color
= color.white, style = plot.style_circles, linewidth = 2)
position_profit_long = plot(bought and show_position_on_chart and
strategy.openprofit>0 ? close : na, style = plot.style_linebr, color =
color.new(#4cd350, 10), linewidth = 1, display = display.all - display.status_line
- display.price_scale)
position_profit_short = plot(sold and show_position_on_chart and
strategy.openprofit>0 ? close : na, style = plot.style_linebr, color =
color.new(#4cd350, 10), linewidth = 1, display = display.all - display.status_line
- display.price_scale)

fill(plot1 = position_price, plot2 = position_profit_long, color =


color.new(#4cd350, 90))
fill(plot1 = position_price, plot2 = position_profit_short, color =
color.new(#4cd350, 90))

fill(plot1 = position_price, plot2 = sl_long_price, color =


color.new(color.red,90))
fill(plot1 = position_price, plot2 = sl_short_price, color =
color.new(color.red,90))

fill(plot1 = position_price, plot2 = tp_long_price, color =


color.new(color.green,90))
fill(plot1 = position_price, plot2 = tp_short_price, color =
color.new(color.green,90))

show_signals = input.bool(defval=true, title="Show signals on chart ?", group =


"============ Appearance ============")
plotshape(show_signals and buy and bullish and ema_filter_long or show_signals and
buy and not ema_filter_long ? low : na, title='Buy', text='Buy',
style=shape.labelup, location=location.belowbar, color=color.new(color.green, 20),
textcolor=color.new(color.white, 0), size=size.tiny , display = display.all -
display.price_scale - display.status_line)
plotshape(show_signals and sell and bearish and ema_filter_long or show_signals and
sell and not ema_filter_short ? high : na, title='Sell', text='Sell',
style=shape.labeldown, location=location.abovebar, color=color.new(color.red, 20),
textcolor=color.new(color.white, 0), size=size.tiny, display = display.all -
display.price_scale - display.status_line)
plotshape(show_signals and closelong_supertrend and close_withsupertrend and bought
or show_signals and sell and bought ? low : na, title='Cl Buy', text='Cl Buy',
style=shape.labelup, location=location.belowbar, color=color.new(#4cafaf, 30),
textcolor=color.new(color.white, 0), size=size.tiny , display = display.all -
display.price_scale - display.status_line)
plotshape(show_signals and closeshort_supertrend and close_withsupertrend and sold
or show_signals and buy and bought? high : na, title='Cl Buy', text='Cl sell',
style=shape.labeldown, location=location.abovebar, color=color.new(#4cafaf, 30),
textcolor=color.new(color.white, 0), size=size.tiny, display = display.all -
display.price_scale - display.status_line)

//
===================================================================================
============================================================
// --------------- Positions amount calculator -------------

contracts_amount_c = initial_actual_capital / close


distance_sl_long_c = -1 * (longStopLoss - close) / close
distance_sl_short_c = (shortStopLoss - close) / close
long_amount_c = close * (contracts_amount_c * (risk_c / 100) / distance_sl_long_c)
short_amount_c = close * (contracts_amount_c * (risk_c / 100) /
distance_sl_short_c)
long_amount_lev = close * (contracts_amount_c * (risk_c / 100) /
distance_sl_long_c)
short_amount_lev = close * (contracts_amount_c * (risk_c / 100) /
distance_sl_short_c)

leverage_for_calculator=input.bool(defval=true, title="Use leverage ?", group =


"============ Position amount calculator ===========", tooltip = "If it is
activated, there will be no monetary units or amount of assets limit for each
operation (That is, each operation will not be affected by the initial / current
capital since it would be using leverage). If it is deactivated, the monetary units
or the amount of assets to use for each operation will be limited by the
initial/current capital.")

if not leverage_for_calculator and long_amount_lev>initial_actual_capital


long_amount_lev:=initial_actual_capital

if not leverage_for_calculator and short_amount_lev>initial_actual_capital


short_amount_lev:=initial_actual_capital

plot(buy and leverage_for_calculator ? long_amount_c : na, color = color.rgb(255,


230, 0), display = display.all - display.pane - display.price_scale)
plot(sell and leverage_for_calculator ? short_amount_c : na, color = color.rgb(255,
230, 0), display = display.all - display.pane - display.price_scale)
plot(buy and not leverage_for_calculator ? long_amount_lev : na, color =
color.rgb(255, 230, 0), display = display.all - display.pane - display.price_scale)
plot(sell and not leverage_for_calculator ? short_amount_lev : na, color =
color.rgb(255, 230, 0), display = display.all - display.pane - display.price_scale)

//
===================================================================================
============================================================
// ===================== Drawing stats about add and withdraw money frequently and
others on chart ===================

if not bought and buy and date and not ema_filter_long


totaltrades += 1
if not sold and sell and date and not ema_filter_short
totaltrades += 1
if not bought and buy and date and bearish and ema_filter_long
totaltrades += 0
if not sold and sell and date and bullish and ema_filter_short
totaltrades += 0
if not bought and buy and date and bullish and ema_filter_long
totaltrades += 1
if not sold and sell and date and bearish and ema_filter_short
totaltrades += 1

total_money_added = initial_capital_a - strategy.initial_capital


total_money_withdrawn = initial_capital_w - strategy.initial_capital
final_money = total_money_added + strategy.netprofit + strategy.initial_capital -
total_money_withdrawn // or current money avaliable
// plot(commission_value_l, color = color.rgb(59, 245, 255), display = display.all
- display.pane)
// plot(commission_value_s, color = color.rgb(59, 245, 255), display = display.all
- display.pane)
// plot(total_commissions_value, color = color.rgb(252, 59, 255), display =
display.all - display.pane)
// plot(total_trades/2, color = color.rgb(59, 245, 255), display = display.all -
display.pane)
// plot(final_money, color = color.yellow, display = display.all - display.pane)
// plot(total_money_added, color = color.blue, display = display.all -
display.pane)
// plot(total_money_withdrawn, color = color.red, display = display.all -
display.pane)
// plot(strategy.netprofit, color = color.green, display = display.all -
display.pane)

// truncate(_number, _decimalPlaces) =>


// _factor = math.pow(10, _decimalPlaces)
// int(_number * _factor) / _factor

// draw_stats = input.bool(true, "Show stats from add/withdraw money frequently ?",


group = "============ Appearance ============")

// Prepare stats table

// var table testTable = table.new(position.top_right, 5, 2, border_width=2,


frame_color = color.rgb(0, 0, 0), frame_width = 2)
// f_fillCell(_table, _column, _row, _title, _value, _bgcolor,
_txtcolor,_size,_tooltip) =>
// _cellText = _title + "\n" + _value
// table.cell(_table, _column, _row, _cellText, bgcolor=_bgcolor,
text_color=_txtcolor, text_size=_size, tooltip = _tooltip)

// // Draw stats table

// var bgcolor = color.new(#2f5cda, 50)


// var bgcolor2 = color.new(color.green, 50)
// var bgcolor3 = color.new(color.red,50)
// if draw_stats
// if barstate.islastconfirmedhistory
// f_fillCell(testTable, 0, 0, "Final/current money:", "$" +
str.tostring(truncate(final_money,2)), bgcolor, color.white, _size = size.normal,
_tooltip = "Total money added + total return from strategy + initial capital -
total money withdrawn")
// f_fillCell(testTable, 0, 1, "Total money added:", "$" +
str.tostring(truncate(total_money_added,2)), bgcolor, color.white, _size =
size.normal, _tooltip = "Sum of total money added at the end of the date")
// f_fillCell(testTable, 1, 0, "Total money withdrawn:", "$" +
str.tostring(truncate(total_money_withdrawn*-1,2)), bgcolor, color.white, _size =
size.normal, _tooltip = "Sum of total money withdrawn at the end of the date")
// f_fillCell(testTable, 1, 1, "Total return:", "$" +
str.tostring(truncate(strategy.netprofit,2)), strategy.netprofit > 0 ? bgcolor2 :
bgcolor3 , color.white, _size = size.normal, _tooltip = "Total return from strategy
until the end of the date (it could be different from default backtesting if last
position have not been closed completly)")
// f_fillCell(testTable, 2, 0, "Total trades:", "" +
str.tostring(truncate(totaltrades,2)), bgcolor, color.white, _size = size.normal,
_tooltip = "Sum of real total trades. The value from default backtester it´s not
precise")
// f_fillCell(testTable, 2, 1, "Total commissions value:", "" +
str.tostring(truncate(total_commissions_value,2)), bgcolor, color.white, _size =
size.normal, _tooltip = "Sum of commissions value from all trades. You must set the
% value in the script settings (Positions management).")
// // ===================================================================== :D

You might also like