888 BOT v4は,複数の指標を組み合わせてトレンド判断を行い,取引シグナルを発信する自動取引戦略である.これは,均線,区間フィルター,ADX,パラパラ線SAR,ベアリングRSI,MACD,ブリン帯など8つの指標の組み合わせを使用して,より信頼性の高い取引シグナルを発信する.
ユリク平均線 (JMA): Mark Jurikが専門家向けに設計した信号遅延を排除する平均線.長パラメータは,ノイズを制御し,相とパラメータは,遅延と過波を均衡させる.
スペースフィルター市場騒音を除去するために,一時期の平均価格変動の範囲を計算し,その範囲を拡大することで,短期的なトレンドを判断する.
平均方向指標 ((ADX): ワイルダーによって作成され,トレンドの強さと方向を測定する. ADXは正の傾斜であり,しばらくの間,値を超えており,価格運動が強いことを示す.
パラロイドストップ (SAR): また,ウィルダーによって作成され,トレンドを判断するために点を置く. 価格が指標に触れると,価格の反対側に飛び,パラパラ線を形成する.
RSIのベクトル: 取引量パラメータをクラシックRSIに基づいて追加し,市場動向をより正確に反映させる.
MACD:Appelが作成した快慢平均線差値指標で,ヒストグラムが平均線交差を予測できる.MAC-Zが価格を標準化した後,VWAP計算に加える.
取引量条件: フィルター取引量は平均より低いシグナルで,異なる量級は異なるレバレッジに対応する.
ブリン帯ウォールバンド指数は,リエントリーチャンスとして利用できます.
8つの指標に基づいて,空白条件をそれぞれ決定する.
複数の指標が確認された後,取引シグナルを生成し,ポジションに入ります.
ポジション数とリスクパラメータに基づいてストップ・ストップ・ロスを設定します.
価格がストップ・ストップ・ロスの値に達すると,平仓を外します.
価格がブリン帯に再触すると,入場価格を改善するポジションのチャンスがあります.
ポジションを平らにした後,指標の確認を待って,再び新しいポジションに入ることができる.
888 BOT v4の最大の利点は,指標の組み合わせを使用することであり,異なる指標は相互に検証し,偽信号を減らすことが可能であり,これは単一の指標戦略よりも信頼性が高い.さらに,加仓と入場価格の改善を許可し,より多額の利子を追うことができます.
具体的には,以下の利点があります.
JMAは,遅延を取り除き,区間フィルタを消し,信号品質を向上させる.
ADXはトレンドの強さを判断し,パラグラフ線SARは方向を判断し,入場をより正確にする.
RSIとMACDは,市場情報と多層の検証シグナルを追加します.
取引量条件は偽信号をフィルターし,異なる量レベルがレバレッジに対応する.
ストップレスは,リスクストップ,ATRストップまたはダブルストップを選択して,下落のリスクを制御します.
ブリン・ベンドの加担により入場価格を改善し,より大きな利益を追求することが許される.
ストップを分割するか,利益と利益の確率をバランスするか選択できます.
戦略の効果を評価するために,時段と取引ペアを選択して反テストすることができます.
888 BOT v4は指標組合せとパラメータ最適化によりリスクを低減したものの,取引のいかなる戦略にも一定のリスクがある.
指示器が誤信号を発する確率を,適切なパラメータを調整して減らすことができます.
加仓後の損失拡大のリスクは,入場価格最適化の幅を低くして防止する.
ブリン帯が触発されない場合,損失は拡大し,トレンド指標が加仓のタイミングを判断する.
ストップダメージは緩やかすぎると,ストップダメージの範囲を適切に縮小することができます.
回測時間は不十分で,回測周期を拡張して検証できる.
取引量が不足し,ポジションの規模を調整する.
特別事態は効果的でないので,リスク管理をきちんと行う必要がある,ジェンキンソン
888 BOT v4には,いくつかの改善の余地があります.
指標パラメータを調整し,最適な組み合わせを探します.
KDJ,振動指数など,他の指標の代替を試みる.
チケット価格の最適化
ストップ・ストップ・ロスを調整する.
ストップを設定した後に保証が止まる.
ポジションの規模とレバレッジの最適化
機械学習などの自動化方法を試す.
特定の状況から逃れる条件を追加する.
市場横断のレバレッジを試してみてください.
グラフィック・インターフェースの開発と使いやすさを向上させる.
総じて,888 BOT v4は,多指標戦略の典型的代表であり,指標の組み合わせを取引することで,利益の確率を大幅に向上させることができる.しかし,いかなる戦略も天空を包むことはできません.継続的に利益を得るためには,継続的にテストし,最適化し,リスク管理を行う必要があります.
/*backtest
start: 2023-09-20 00:00:00
end: 2023-09-27 00:00:00
period: 10m
basePeriod: 1m
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © Xaviz
//@version=4
strategy(title = "888 BOT #backtest", shorttitle = "888💹", overlay = true, initial_capital = 10000, pyramiding = 10, currency = "USD",
default_qty_type = strategy.percent_of_equity, default_qty_value = 0, commission_value = 0.04)
// -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- //
// ———————————————————— Inputs
// -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- //
// ————— Source input
src = input(hlc3, title = " SOURCE", type = input.source)
// ————— JMA inputs
Act_JMA = input(true, title = "JURIK MOVING AVERAGE", type = input.bool)
JMA_length = input(30, title = " JMA LENGTH", type = input.integer, minval = 0)
phase = input(40, title = " JMA PHASE", type = input.integer, minval = 0)
power = input(2.5, title = " JMA POWER", type = input.float, minval = 0, step = 0.5)
// ————— Range Filter inputs
Act_RF = input(true, title = "RANGE FILTER", type = input.bool)
per = input(20, title = " SAMPLING PERIOD", type = input.integer, minval = 1)
mult = input(1.7, title = " RANGE MULTIPLIER", type = input.float, minval = 0.1, step = 0.1)
// ————— ADX inputs
Act_ADX = input(true, title = "AVERAGE DIRECTIONAL INDEX", type = input.bool)
ADX_options = input("CLASSIC", title = " ADX OPTION", options = ["CLASSIC", "MASANAKAMURA"])
ADX_len = input(22, title = " ADX LENGTH", type = input.integer, minval = 1)
th = input(20, title = " ADX THRESHOLD", type = input.float, minval = 0, step = 0.5)
// ————— SAR inputs
Act_SAR = input(true, title = "PARABOLIC SAR", type = input.bool)
Sst = input (0.25, title = " SAR STAR", type = input.float, minval = 0.01, step = 0.01)
Sinc = input (0.25, title = " SAR INC", type = input.float, minval = 0.01, step = 0.01)
Smax = input (0.13, title = " SAR MAX", type = input.float, minval = 0.01, step = 0.01)
// ————— RSI with volume inputs
Act_RSI = input(true, title = "RSI VOLUME WEIGHTED", type = input.bool)
RSI_len = input(34, title = " RSI LENGHT", type = input.integer, minval = 1)
RSI_obos = input(45, title = " RSI CENTER LINE", type = input.integer, minval = 1)
// ————— MACD / MAC-Z inputs
Act_MACD = input(true, title = "MA CONVERGENCE/DIVERGENCE", type = input.bool)
MACD_options = input("MAC-Z", title = " MACD OPTION", options = ["MACD", "MAC-Z"])
fastLength = input(45, title = " MACD FAST MA LENGTH", type = input.integer, minval = 1)
slowLength = input(47, title = " MACD SLOW MA LENGTH", type = input.integer, minval = 1)
signalLength = input(13, title = " MACD SIGNAL LENGTH", type = input.integer, minval = 1)
lengthz = input(9, title = " Z-VWAP LENGTH", type = input.integer, minval = 1)
lengthStdev = input(14, title = " STDEV LENGTH", type = input.integer, minval = 1)
// ————— Volume inputs for entries condition and for calculate quantities later
Act_Vol = input(true, title = "VOLUME CONDITION", type = input.bool)
volume_f = input(1.4, title = " VOLUME FACTOR", type = input.float, minval = 0, step = 0.1)
sma_length = input(61, title = " SMA VOLUME LENGTH", type = input.integer, minval = 1)
// ————— First take profit input
tp_long0 = input(1.7, title = " TAKE PROFIT LONG %", type = input.float, minval = 0, step = 0.1)
tp_short0 = input(1.8, title = " TAKE PROFIT SHORT %", type = input.float, minval = 0, step = 0.1)
// ————— Stop Loss input
Act_sl = input(true, title = "ACTIVATE STOP LOSS 🧻", type = input.bool)
SL_options = input("NORMAL", title = " STOP LOSS OPTION", options = ["NORMAL", "ATR", "BOTH"])
sl0 = input(3.7, title = " STOP LOSS %", type = input.float, minval = 0, step = 0.1)
// ————— ATR Inputs
atrPeriod = input(13, title = " ATR SL PERIOD", type = input.integer, minval = 0)
multiplierPeriod = input(7.0, title = " ATR SL MULTIPLIER", type = input.float, minval = 0, step = 0.1)
// ————— Risk input
Risk = input(3.5, title = " % RISK ALLOWED", type = input.float, minval = 0, step = 0.5)
// ————— Confirmed Stop loss
Act_Conf_SL = input(false, title = "STOP LOSS CONFIRMED", type = input.bool)
// ————— Bollinger Bands inputs
Act_BB = input(true, title = "ACTIVATE BOLLINGER BANDS RE-ENTRY 🚀", type = input.bool)
BB_length = input(20, title = " BB LENGTH", type = input.integer, minval = 1)
BB_mult = input(1.9, title = " BB MULTIPLIER", type = input.float, minval = 0.001, step = 0.1)
bbBetterPrice = input(0.5, title = " % MINIMUM BETTER PRICE", type = input.float, minval = 0.1, step = 0.1)
Act_divide = input(false, title = "ACTIVATE DIVIDE TP", type = input.bool)
// ————— Backtest input
Act_BT = input(true, title = "BACKTEST 💹", type = input.bool)
backtest_time = input(180, title = " BACKTEST DAYS", type = input.integer, minval = 1)*24*60*60*1000
entry_Type = input("% EQUITY", title = " ENTRY TYPE", options = ["CONTRACTS","CASH","% EQUITY"])
et_Factor = (entry_Type == "CONTRACTS") ? 1 : (entry_Type == "% EQUITY") ? (100/(strategy.equity/close)) : close
quanTity = input(8.0, title = " QUANTITY (LEVERAGE 1X)", type = input.float, minval = 0, step = 0.5) / et_Factor
Max_Lev = input(8, title = " MAXIMUM LEVERAGE", type = input.integer, minval = 1, maxval = 8)
// -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- //
// ———————————————————— Variables
// -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- //
// ————— Long/Short
var bool longCond = na, var bool shortCond = na
var int CondIni_long = 0, var int CondIni_short = 0
var bool _Final_longCondition = na, var bool _Final_shortCondition = na
var float last_open_longCondition = na, var float last_open_shortCondition = na
var float last_dynamic_Leverage_long = na, var float last_dynamic_Leverage_short = na
var int last_longCondition = na, var int last_shortCondition = na
var int last_Final_longCondition = na, var int last_Final_shortCondition = na
var int nLongs = na, var int nShorts = na
// ————— Take profit
var bool long_tp = na, var bool short_tp = na
var int last_long_tp = na, var int last_short_tp = na
var bool Final_Long_tp = na, var bool Final_Short_tp = na
// ————— Stop Loss
var int CondIni_long_sl = 0, var int CondIni_short_sl = 0
var bool Final_Long_sl0 = na, var bool Final_Short_sl0 = na
var bool Final_Long_sl = na, var bool Final_Short_sl = na
var int last_long_sl = na, var int last_short_sl = na
// ————— Indicators
var bool JMA_longCond = na, var bool JMA_shortCond = na
var bool RF_longCond = na, var bool RF_shortCond = na
var bool ADX_longCond = na, var bool ADX_shortCond = na
var bool SAR_longCond = na, var bool SAR_shortCond = na
var bool RSI_longCond = na, var bool RSI_shortCond = na
var bool MACD_longCond = na, var bool MACD_shortCond = na
var bool VOL_longCond = na, var bool VOL_shortCond = na
var bool JMA_XlongCond = na, var bool JMA_XshortCond = na
var bool RF_XlongCond = na, var bool RF_XshortCond = na
var bool ADX_XlongCond = na, var bool ADX_XshortCond = na
var bool SAR_XlongCond = na, var bool SAR_XshortCond = na
var int CondIni_long_BB = 0, var int CondIni_short_BB = 0
var bool Final_long_BB = na, var bool Final_short_BB = na
var int last_long_BB = na, var int last_short_BB = na
// ————— Average Price
var float sum_long = 0.0, var float sum_short = 0.0
var float Position_Price = 0.0
// -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- //
// ———————————————————— Jurik Moving Average
// -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- //
// ————— JMA calculation
JMA(_JMA_length, _phase, _power, _src) =>
phaseRatio = _phase < -100 ? 0.5 : _phase > 100 ? 2.5 : _phase / 100 + 1.5
beta = 0.45 * (_JMA_length - 1) / (0.45 * (_JMA_length - 1) + 2)
alpha = pow(beta, _power)
jma = 0.0
e0 = 0.0
e0 := (1 - alpha) * _src + alpha * nz(e0[1])
e1 = 0.0
e1 := (_src - e0) * (1 - beta) + beta * nz(e1[1])
e2 = 0.0
e2 := (e0 + phaseRatio * e1 - nz(jma[1])) * pow(1 - alpha, 2) + pow(alpha, 2) * nz(e2[1])
jma := e2 + nz(jma[1])
// ————— Defining JMA trend
JMA_Rising = JMA(JMA_length, phase, power, src) > JMA(JMA_length, phase, power, src)[1]
JMA_Falling = JMA(JMA_length, phase, power, src) < JMA(JMA_length, phase, power, src)[1]
// ————— JMA Plotting
JMA_color = JMA_Rising ? color.lime : JMA_Falling ? #e91e63 : color.orange
plot(Act_JMA ? JMA(JMA_length, phase, power, src) : na, color=JMA_color, linewidth = 2, title= "JMA")
// -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- //
// ———————————————————— Range Filter
// -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- //
// ————— Range Filter calculation
Range_filter(_src, _per, _mult) =>
float _upward = 0.0
float _downward = 0.0
wper = (_per*2) - 1
avrng = ema(abs(_src - _src[1]), _per)
_smoothrng = ema(avrng, wper) * _mult
_filt = _src
_filt := _src > nz(_filt[1]) ? ((_src-_smoothrng) < nz(_filt[1]) ? nz(_filt[1]) : (_src-_smoothrng)) : ((_src+_smoothrng) > nz(_filt[1]) ? nz(_filt[1]) : (_src+_smoothrng))
_upward := _filt > _filt[1] ? nz(_upward[1]) + 1 : _filt < _filt[1] ? 0 : nz(_upward[1])
_downward := _filt < _filt[1] ? nz(_downward[1]) + 1 : _filt > _filt[1] ? 0 : nz(_downward[1])
[_smoothrng,_filt,_upward,_downward]
// ————— Defining variables for include in future conditions
[smoothrng, filt, upward, downward] = Range_filter(src, per, mult)
// ————— Defining high and low bands
hband = filt + smoothrng
lband = filt - smoothrng
// ————— Range Filter Plotting
filtcolor = upward > 0 ? color.lime : downward > 0 ? color.red : color.orange
filtplot = plot(Act_RF ? filt : na, color = filtcolor, linewidth = 1, title = "RF")
hbandplot = plot(Act_RF ? hband : na, color = filtcolor, transp = 50, title = "RF High Target")
lbandplot = plot(Act_RF ? lband : na, color = filtcolor, transp = 50, title = "RF Low Target")
fill(hbandplot, lbandplot, color = filtcolor, title = "RF Target Range")
// -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- //
// ———————————————————— ADX
// -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- //
// ————— Classic ADX calculating
calcADX(_len) =>
up = change(high)
down = -change(low)
plusDM = na(up) ? na : (up > down and up > 0 ? up : 0)
minusDM = na(down) ? na : (down > up and down > 0 ? down : 0)
truerange = rma(tr, _len)
_plus = fixnan(100 * rma(plusDM, _len) / truerange)
_minus = fixnan(100 * rma(minusDM, _len) / truerange)
sum = _plus + _minus
_adx = 100 * rma(abs(_plus - _minus) / (sum == 0 ? 1 : sum), _len)
[_plus,_minus,_adx]
// ————— Masanakamura ADX calculating
calcADX_Masanakamura(_len) =>
SmoothedTrueRange = 0.0
SmoothedDirectionalMovementPlus = 0.0
SmoothedDirectionalMovementMinus = 0.0
TrueRange = max(max(high - low, abs(high - nz(close[1]))), abs(low - nz(close[1])))
DirectionalMovementPlus = high - nz(high[1]) > nz(low[1]) - low ? max(high - nz(high[1]), 0) : 0
DirectionalMovementMinus = nz(low[1]) - low > high - nz(high[1]) ? max(nz(low[1]) - low, 0) : 0
SmoothedTrueRange := nz(SmoothedTrueRange[1]) - (nz(SmoothedTrueRange[1]) /_len) + TrueRange
SmoothedDirectionalMovementPlus := nz(SmoothedDirectionalMovementPlus[1]) - (nz(SmoothedDirectionalMovementPlus[1]) / _len) + DirectionalMovementPlus
SmoothedDirectionalMovementMinus := nz(SmoothedDirectionalMovementMinus[1]) - (nz(SmoothedDirectionalMovementMinus[1]) / _len) + DirectionalMovementMinus
DIP = SmoothedDirectionalMovementPlus / SmoothedTrueRange * 100
DIM = SmoothedDirectionalMovementMinus / SmoothedTrueRange * 100
DX = abs(DIP-DIM) / (DIP+DIM)*100
adx = sma(DX, _len)
[DIP,DIM,adx]
// ————— Defining variables for include in future conditions
[DIPlusC,DIMinusC,ADXC] = calcADX(ADX_len)
[DIPlusM,DIMinusM,ADXM] = calcADX_Masanakamura(ADX_len)
DIPlus = ADX_options == "CLASSIC" ? DIPlusC : DIPlusM
DIMinus = ADX_options == "CLASSIC" ? DIMinusC : DIMinusM
ADX = ADX_options == "CLASSIC" ? ADXC : ADXM
// ————— Plotting ADX bar colors
ADX_color = DIPlus > DIMinus and ADX > th ? color.green : DIPlus < DIMinus and ADX > th ? color.red : color.orange
barcolor(color = Act_ADX ? ADX_color : na, title = "ADX")
// -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- //
// ———————————————————— SAR
// -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- //
// ————— SAR calculation from TV
SAR = sar(Sst, Sinc, Smax)
// ————— SAR Plotting
plot(Act_SAR ? SAR : na, color = ADX_color, style = plot.style_circles, title = "SAR")
// -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- //
// ———————————————————— RSI with Volume
// -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- //
// ————— RSI with volume calculation
WiMA(_src, W_length) =>
var float MA_s = 0.0
MA_s :=(_src + nz(MA_s[1] * (W_length-1)))/W_length
MA_s
RSI_Volume(fv, _length) =>
up = iff(fv > fv[1], abs(fv - fv[1]) * volume, 0)
dn = iff(fv < fv[1], abs(fv - fv[1]) * volume, 0)
upt = WiMA(up,_length)
dnt = WiMA(dn,_length)
100 * (upt / (upt + dnt))
// ————— Defining variable for include in conditions
RSI_V = RSI_Volume(src, RSI_len)
// -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- //
// ———————————————————— MACD
// -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- //
// ————— MAC-Z calculation
calc_zvwap(pds) =>
mean = sum(volume * close, pds) / sum(volume, pds)
vwapsd = sqrt(sma(pow(close - mean, 2), pds))
(close - mean ) / vwapsd
zscore = calc_zvwap(lengthz)
fastMA = sma(src, fastLength)
slowMA = sma(src, slowLength)
macd = fastMA - slowMA
macz = zscore + macd / stdev(src, lengthStdev)
signal = sma(macz, signalLength)
histmacz = macz - signal
// ————— MACD calculation
[_,_,histmacd] = macd(src, fastLength, slowLength, signalLength)
hist = MACD_options == "MACD" ? histmacd : histmacz
// -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- //
// ———————————————————— Strategy
// -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- //
// ————— All indicators with long conditions and enable/disable option
JMA_longCond := (Act_JMA ? (JMA_Rising) : VOL_longCond)
RF_longCond := (Act_RF ? (high > hband and upward > 0) : JMA_longCond)
ADX_longCond := (Act_ADX ? (DIPlus > DIMinus and ADX > th) : RF_longCond)
SAR_longCond := (Act_SAR ? (SAR < close) : ADX_longCond)
RSI_longCond := (Act_RSI ? (RSI_V > RSI_obos) : SAR_longCond)
MACD_longCond := (Act_MACD ? (hist > 0) : RSI_longCond)
VOL_longCond := (Act_Vol ? (volume > sma(volume,sma_length) * volume_f) : MACD_longCond)
// ————— All indicators with short conditions and enable/disable option
JMA_shortCond := (Act_JMA ? (JMA_Falling) : VOL_shortCond)
RF_shortCond := (Act_RF ? (low < lband and downward > 0) : JMA_shortCond)
ADX_shortCond := (Act_ADX ? (DIPlus < DIMinus and ADX > th) : RF_shortCond)
SAR_shortCond := (Act_SAR ? (SAR > close) : ADX_shortCond)
RSI_shortCond := (Act_RSI ? (RSI_V < RSI_obos) : SAR_shortCond)
MACD_shortCond := (Act_MACD ? (hist < 0) : RSI_shortCond)
VOL_shortCond := (Act_Vol ? (volume > sma(volume,sma_length) * volume_f) : MACD_shortCond)
// ————— Defining long/short condition from indicators + volume
longCond := JMA_longCond and RF_longCond and ADX_longCond and SAR_longCond and RSI_longCond and MACD_longCond and VOL_longCond
shortCond := JMA_shortCond and RF_shortCond and ADX_shortCond and SAR_shortCond and RSI_shortCond and MACD_shortCond and VOL_shortCond
// ————— Avoiding confirmed long/short simultaneity
CondIni_long := longCond[1] ? 1 : shortCond[1] ? -1 : nz(CondIni_long[1])
CondIni_short := longCond[1] ? 1 : shortCond[1] ? -1 : nz(CondIni_short[1])
// ————— Confirmed long/short conditions
longCondition = (longCond[1] and nz(CondIni_long[1]) == -1)
shortCondition = (shortCond[1] and nz(CondIni_short[1]) == 1)
// -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- //
// ———————————————————— Position Price
// -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- //
// ————— Last opened long/short price on unconfirmed/confirmed conditions
last_open_longCondition := longCondition or Final_long_BB[1] ? close[1] : nz(last_open_longCondition[1])
last_open_shortCondition := shortCondition or Final_short_BB[1] ? close[1] : nz(last_open_shortCondition[1])
// ————— Check if your last position was a confirmed long or a short
last_longCondition := longCondition or Final_long_BB[1] ? time : nz(last_longCondition[1])
last_shortCondition := shortCondition or Final_short_BB[1] ? time : nz(last_shortCondition[1])
in_longCondition = last_longCondition > last_shortCondition
in_shortCondition = last_shortCondition > last_longCondition
// ————— Check if your last position was a confirmed final long or short without BB
last_Final_longCondition := longCondition ? time : nz(last_Final_longCondition[1])
last_Final_shortCondition := shortCondition ? time : nz(last_Final_shortCondition[1])
// ————— Counting long & short iterations
nLongs := nz(nLongs[1])
nShorts := nz(nShorts[1])
// ————— Longs Counter
if longCondition or Final_long_BB
nLongs := nLongs + 1
nShorts := 0
sum_long := nz(last_open_longCondition) + nz(sum_long[1])
sum_short := 0.0
// ————— Shorts Counter
if shortCondition or Final_short_BB
nLongs := 0
nShorts := nShorts + 1
sum_short := nz(last_open_shortCondition) + nz(sum_short[1])
sum_long := 0.0
// ————— Calculating and Plotting the price average
Position_Price := nz(Position_Price[1])
Position_Price := longCondition or Final_long_BB ? sum_long/nLongs : shortCondition or Final_short_BB ? sum_short/nShorts : na
plot((nLongs > 1) or (nShorts > 1) ? Position_Price : na, title = "Average Price", color = in_longCondition ? color.aqua : color.orange, linewidth = 2, style = plot.style_cross)
// -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- //
// ———————————————————— Take Profit
// -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- //
// ————— Take Profit divided by n entries
tp_long = (Act_divide and (nLongs > 1) ? tp_long0 / nLongs : tp_long0) / 100
tp_short = (Act_divide and (nShorts > 1) ? tp_short0 / nShorts : tp_short0) / 100
// ————— First TP Conditions
long_tp := high > (fixnan(Position_Price) * (1 + tp_long)) and in_longCondition
short_tp := low < (fixnan(Position_Price) * (1 - tp_short)) and in_shortCondition
// ————— Get the time of the last tp close
last_long_tp := long_tp ? time : nz(last_long_tp[1])
last_short_tp := short_tp ? time : nz(last_short_tp[1])
// ————— Final Take profit condition (never after the stop loss)
Final_Long_tp := (long_tp and last_longCondition > nz(last_long_tp[1]) and last_longCondition > nz(last_long_sl[1]))
Final_Short_tp := (short_tp and last_shortCondition > nz(last_short_tp[1]) and last_shortCondition > nz(last_short_sl[1]))
// -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- //
// ———————————————————— Stop Loss
// -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- //
// ————— Stop Loss ATR calculation
ATR_SL_Long = low - atr(atrPeriod) * multiplierPeriod
ATR_SL_Short = high + atr(atrPeriod) * multiplierPeriod
longStopPrev = nz(ATR_SL_Long[1], ATR_SL_Long)
shortStopPrev = nz(ATR_SL_Short[1], ATR_SL_Short)
ATR_SL_Long := close[1] > longStopPrev ? max(ATR_SL_Long, longStopPrev) : ATR_SL_Long
ATR_SL_Short := close[1] < shortStopPrev ? min(ATR_SL_Short, shortStopPrev) : ATR_SL_Short
// ————— Calculating Sl according Risk and Initial Capital
sl = in_longCondition ?
min(sl0, (((Risk / (100 / (strategy.equity / close)))*100) / (quanTity * max(1, last_dynamic_Leverage_long) * max(1, nLongs)))) :
min(sl0, (((Risk / (100 / (strategy.equity / close)))*100) / (quanTity * max(1, last_dynamic_Leverage_short) * max(1, nShorts))))
// ————— Stop Loss long conditions
Normal_long_sl = Act_Conf_SL ? ((SL_options == "NORMAL") ? ((Act_sl and in_longCondition and close <= ((1 - (sl / 100)) * (fixnan(Position_Price))))) : na) :
((SL_options == "NORMAL") ? ((Act_sl and in_longCondition and low <= ((1 - (sl / 100)) * (fixnan(Position_Price))))) : na)
ATR_long_sl = Act_Conf_SL ? ((SL_options == "ATR") ? ((Act_sl and in_longCondition and close <= (ATR_SL_Long))) : na) :
((SL_options == "ATR") ? ((Act_sl and in_longCondition and low <= (ATR_SL_Long))) : na)
Both_long_sl = Act_Conf_SL ? ((SL_options == "BOTH") ? ((Act_sl and in_longCondition and close <= ((1 - (sl / 100)) * (fixnan(Position_Price)))) or
((Act_sl and in_longCondition and close <= (ATR_SL_Long)))) : na) :
((SL_options == "BOTH") ? ((Act_sl and in_longCondition and low <= ((1 - (sl / 100)) * (fixnan(Position_Price)))) or
((Act_sl and in_longCondition and low <= (ATR_SL_Long)))) : na)
// ————— Stop Loss short conditions
Normal_short_sl = Act_Conf_SL ? ((SL_options == "NORMAL") ? ((Act_sl and in_shortCondition and close >= ((1 + (sl / 100)) * (fixnan(Position_Price))))) : na) :
((SL_options == "NORMAL") ? ((Act_sl and in_shortCondition and high >= ((1 + (sl / 100)) * (fixnan(Position_Price))))) : na)
ATR_short_sl = Act_Conf_SL ? ((SL_options == "ATR") ? ((Act_sl and in_shortCondition and close >= (ATR_SL_Short))) : na) :
((SL_options == "ATR") ? ((Act_sl and in_shortCondition and high >= (ATR_SL_Short))) : na)
Both_short_sl = Act_Conf_SL ? ((SL_options == "BOTH") ? ((Act_sl and in_shortCondition and close >= ((1 + (sl/100)) * (fixnan(Position_Price)))) or
((Act_sl and in_shortCondition and close >= (ATR_SL_Short)))) : na) :
((SL_options == "BOTH") ? ((Act_sl and in_shortCondition and high >= ((1 + (sl/100)) * (fixnan(Position_Price)))) or
((Act_sl and in_shortCondition and high >= (ATR_SL_Short)))) : na)
// ————— Get the time of the last sl close
last_long_sl := Normal_long_sl or ATR_long_sl or Both_long_sl ? time : nz(last_long_sl[1])
last_short_sl := Normal_short_sl or ATR_short_sl or Both_short_sl ? time : nz(last_short_sl[1])
// ————— Final Stop Loss condition
Final_Long_sl := (Normal_long_sl or ATR_long_sl or Both_long_sl) and last_longCondition > nz(last_long_sl[1]) and last_longCondition > nz(last_long_tp[1]) and not Final_Long_tp
Final_Short_sl := (Normal_short_sl or ATR_short_sl or Both_short_sl) and last_shortCondition > nz(last_short_sl[1]) and last_shortCondition > nz(last_short_tp[1]) and not Final_Short_tp
//Plottin ATR SL
plot(Act_sl and (SL_options != "NORMAL") ? in_longCondition ? ATR_SL_Long[1] : ATR_SL_Short[1] : na, title = "ATR SL", color = color.purple)
// -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- //
// ———————————————————— Bollinger Bands Re-entry
// -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- //
BB_basis = sma(src, BB_length)
BB_dev = BB_mult * stdev(src, BB_length)
BB_upper = BB_basis + BB_dev
BB_lower = BB_basis - BB_dev
u_BB = plot(Act_BB ? BB_upper : na, title = "Upper Bollinger Band", color = #009688, linewidth = 2)
l_BB = plot(Act_BB ? BB_lower : na, title = "Lower Bollinger Band", color = #f06292, linewidth = 2)
fill(u_BB, l_BB, title = "Bollinger Band Background", color = in_longCondition ? #009688 : #f06292, transp = 95)
// ————— Initial Bollinger Bands conditions
BB_long = Act_BB and in_longCondition and not (DIPlus < DIMinus and ADX > th) and (close <= BB_lower) and (close < last_open_longCondition * (1 - (bbBetterPrice / 100)))
BB_short = Act_BB and in_shortCondition and not (DIPlus > DIMinus and ADX > th) and (close >= BB_upper) and (close > last_open_shortCondition * (1 + (bbBetterPrice / 100)))
// ————— Get the time of the last BB close
last_long_BB := BB_long ? time : nz(last_long_BB[1])
last_short_BB := BB_short ? time : nz(last_short_BB[1])
// ————— Final Bollinger Bands condition for long
Final_long_BB := BB_long and last_Final_longCondition > nz(last_long_BB[1]) and
last_longCondition > nz(last_long_tp[1]) and
last_longCondition > nz(last_long_sl[1]) and not Final_Long_sl
// ————— Final Bollinger Bands condition for short
Final_short_BB := BB_short and last_Final_shortCondition > nz(last_short_BB[1]) and
last_shortCondition > nz(last_short_tp[1]) and
last_shortCondition > nz(last_short_sl[1]) and not Final_Short_sl
// ————— Final confirmed Re-entries on long & short conditions
Final_Long_BB = Final_long_BB[1]
Final_Short_BB = Final_short_BB[1]
// -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- //
// ———————————————————— Signal Plotting
// -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- //
// ————— TP Long Levels
tplLevel = (in_longCondition and
(last_longCondition > nz(last_long_tp[1])) and
(last_longCondition > nz(last_long_sl[1])) and not Final_Long_sl[1]) ?
(nLongs > 1) ?
(fixnan(Position_Price) * (1 + tp_long)) : (last_open_longCondition * (1 + tp_long)) : na
plot(tplLevel, title = "Long TP Level", style = plot.style_circles, color = color.lime, linewidth = 2)
tpsLevel = (in_shortCondition and
(last_shortCondition > nz(last_short_tp[1])) and
(last_shortCondition > nz(last_short_sl[1])) and not Final_Short_sl[1]) ?
(nShorts > 1) ?
(fixnan(Position_Price) * (1 - tp_short)) : (last_open_shortCondition * (1 - tp_short)) : na
plot(tpsLevel, title = "Short TP Level", style = plot.style_circles, color = color.red, linewidth = 2)
// ————— Weekend
W_color = (dayofweek == dayofweek.sunday or dayofweek == dayofweek.saturday) ? color.white : na
bgcolor(W_color, title = "Weekend", transp = 95)
// -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- //
// ———————————————————— Re-entry Conditions
// -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- //
// ————— Re-entry on long after tp, sl or Xlong
if Final_Long_tp or Final_Long_sl
CondIni_long := -1
sum_long := 0.0
nLongs := na
// ————— Re-entry on short after tp, sl or Xshort
if Final_Short_tp or Final_Short_sl
CondIni_short := 1
sum_short := 0.0
nShorts := na
// -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- //
// ———————————————————— Backtest
// -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- //
// ————— Defining new final unconfirmed long conditions
_longCondition = (longCond and not in_longCondition) or
(longCond and Final_Long_tp) or
(longCond and Final_Long_sl) or
(longCond and not longCondition and (last_long_tp >= nz(last_longCondition))) or
(longCond and not longCondition and (last_long_sl >= nz(last_longCondition)))
// ————— Defining new final unconfirmed short conditions
_shortCondition = (shortCond and not in_shortCondition) or
(shortCond and Final_Short_tp) or
(shortCond and Final_Short_sl) or
(shortCond and not shortCondition and (last_short_tp >= nz(last_shortCondition))) or
(shortCond and not shortCondition and (last_short_sl >= nz(last_shortCondition)))
// ————— Test period declaration
testPeriod = time >= timenow - backtest_time
// ————— Volume Factor for determine quantities
Volume_Factor_Leverage = min(Max_Lev, max(1, round(volume / sma(volume, sma_length))))
last_dynamic_Leverage_long := _longCondition ? Volume_Factor_Leverage : nz(last_dynamic_Leverage_long[1])
last_dynamic_Leverage_short := _shortCondition ? Volume_Factor_Leverage : nz(last_dynamic_Leverage_short[1])
// ————— Entering long positions
if (_longCondition)
strategy.entry("long", strategy.long, qty = Volume_Factor_Leverage * quanTity, when = Act_BT and testPeriod)
if (Final_long_BB)
strategy.entry("long", strategy.long, qty = last_dynamic_Leverage_long * quanTity, when = Act_BT and testPeriod)
// ————— Entering short positions
if (_shortCondition)
strategy.entry("short", strategy.short, qty = Volume_Factor_Leverage * quanTity, when = Act_BT and testPeriod)
if (Final_short_BB)
strategy.entry("short", strategy.short, qty = last_dynamic_Leverage_short * quanTity, when = Act_BT and testPeriod)
// ————— Closing positions with first long TP
strategy.exit("Tpl", "long",
profit = (abs((last_open_longCondition * (1 + tp_long)) - last_open_longCondition) / syminfo.mintick),
limit = nLongs >= 1 ? strategy.position_avg_price * (1 + tp_long) : na,
loss = Act_Conf_SL == false ?
(iff(Act_sl and (SL_options == "NORMAL"), (abs((last_open_longCondition*(1-(sl/100)))-last_open_longCondition)/syminfo.mintick),
iff(Act_sl and (SL_options == "ATR"), (abs(ATR_SL_Long-last_open_longCondition)/syminfo.mintick),
iff(Act_sl and (SL_options == "BOTH") and ((abs((last_open_longCondition*(1-(sl/100)))-last_open_longCondition)/syminfo.mintick) <
(abs(ATR_SL_Long-last_open_longCondition)/syminfo.mintick)), (abs((last_open_longCondition*(1-(sl/100)))-last_open_longCondition)/syminfo.mintick),
iff(Act_sl and (SL_options == "BOTH") and ((abs((last_open_longCondition*(1-(sl/100)))-last_open_longCondition)/syminfo.mintick) >
(abs(ATR_SL_Long-last_open_longCondition)/syminfo.mintick)), (abs(ATR_SL_Long-last_open_longCondition)/syminfo.mintick), na))))) : na,
stop = Act_Conf_SL == false and nLongs >= 1 ?
(iff(Act_sl and (SL_options == "NORMAL"), ((1-(sl/100))*strategy.position_avg_price),
iff(Act_sl and (SL_options == "ATR"), ATR_SL_Long,
iff(Act_sl and (SL_options == "BOTH") and (((1-(sl/100))*strategy.position_avg_price) > ATR_SL_Long), ((1-(sl/100))*strategy.position_avg_price),
iff(Act_sl and (SL_options == "BOTH") and (((1-(sl/100))*strategy.position_avg_price) < ATR_SL_Long), ATR_SL_Long, na))))) : na)
// Canceling long exit orders to avoid simultaneity with re-entry
strategy.cancel("Tpl", when = Final_long_BB)
// ————— Closing positions with first short TP
strategy.exit("Tps", "short",
profit = (abs((last_open_shortCondition * (1 - tp_short)) - last_open_shortCondition) / syminfo.mintick),
limit = nShorts >= 1 ? strategy.position_avg_price*(1-(tp_short)) : na,
loss = Act_Conf_SL == false ?
(iff(Act_sl and (SL_options == "NORMAL"), (abs((last_open_shortCondition*(1+(sl/100)))-last_open_shortCondition)/syminfo.mintick),
iff(Act_sl and (SL_options == "ATR"), (abs(ATR_SL_Short-last_open_shortCondition)/syminfo.mintick),
iff(Act_sl and (SL_options == "BOTH") and ((abs((last_open_shortCondition*(1+(sl/100)))-last_open_shortCondition)/syminfo.mintick) <
(abs(ATR_SL_Short-last_open_shortCondition)/syminfo.mintick)), (abs((last_open_shortCondition*(1+(sl/100)))-last_open_shortCondition)/syminfo.mintick),
iff(Act_sl and (SL_options == "BOTH") and ((abs((last_open_shortCondition*(1+(sl/100)))-last_open_shortCondition)/syminfo.mintick) >
(abs(ATR_SL_Short-last_open_shortCondition)/syminfo.mintick)), (abs(ATR_SL_Short-last_open_shortCondition)/syminfo.mintick), na))))) : na,
stop = Act_Conf_SL == false and nShorts >= 1 ?
(iff(Act_sl and (SL_options == "NORMAL"), ((1+(sl/100))*strategy.position_avg_price),
iff(Act_sl and (SL_options == "ATR"), ATR_SL_Short,
iff(Act_sl and (SL_options == "BOTH") and (((1+(sl/100))*strategy.position_avg_price) < ATR_SL_Short), ((1+(sl/100))*strategy.position_avg_price),
iff(Act_sl and (SL_options == "BOTH") and (((1+(sl/100))*strategy.position_avg_price) > ATR_SL_Short), ATR_SL_Short, na))))) : na)
// Canceling short exit orders to avoid simultaneity with re-entry
strategy.cancel("Tps", when = Final_short_BB)
// ————— Closing all positions with Xlong/Xshort
strategy.close_all(when = (Final_Long_sl and Act_Conf_SL) or (Final_Short_sl and Act_Conf_SL))
// -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- //
// ———————————————————— by Xaviz