
투기 격차 전략은 추세를 추적하는 양적 거래 전략으로, SAR 평형 곡선을 주요 거래 신호로 사용하고, EMA, 압축 운동량 및 변동성 진동기 등과 같은 다양한 필터를 보조하여, SAR 매개 변수를 구성하여 트렌드 반전점을 식별하여 낮은 위험 트렌드 추적을 구현합니다. 이것은 중장기 투자에 매우 적합한 전략입니다.
이 전략은 패러블 라인 SAR를 주요 거래 신호 지표로 사용합니다. SAR는 가격 추세의 반전 지점을 효과적으로 판단할 수 있으며, SAR 기호의 변화가 발생하면 추세가 전환된다는 것을 의미합니다. 이 전략은 일반적으로 SAR 반전 시 구매 또는 판매 신호를 발송합니다.
또한, 전략은 SAR를 돌파하는 옵션을 제공합니다. 즉, SAR가 완전히 뒤집히기 전에 가격이 마지막 SAR 값을 돌파했을 때 신호를 발생시킵니다. 이것은 전략의 감수성을 더욱 추구 할 수 있습니다.
가짜 신호를 필터링하기 위해, 이 전략은 또한 EMA, 압축 운동량 및 변동성 진동기의 세 가지 보조 필터를 도입합니다. 개별적으로 사용하거나 조합하여 가격 추세와 거래 신호의 신뢰성을 확인하는 데 사용됩니다.
마지막으로, 전략은 고정 손실, 고정 중지, 위험 수익 비율 중단과 같은 세 가지의 손실 중지 방법을 제공합니다. 이것은 전략이 다른 유형의 거래 품종에 대해 유연하게 적응 할 수 있도록합니다.
SAR는 가격 트렌드 전환을 정확하게 판단하고 새로운 가격 트렌드를 적시에 포착하여 중·장선 트렌드를 추적하는 데 적합합니다.
다중 필터 설정은 가짜 돌파의 가능성을 낮추고 신호 신뢰성을 향상시킵니다.
구성은 간단하고 유연하며, 다양한 거래 유형에 맞게 사용자 정의 할 수 있습니다.
다양한 스톱-스트로스 방식을 제공하여, 리스크와 수익의 균형을 추구할 수 있다.
거래 로봇과 직접 연결하여 자동화 거래가 가능합니다.
트렌드가 아닌 시장에서는 가짜 신호와 유효하지 않은 거래가 증가할 수 있습니다.
부적절한 SAR 파라미터 설정은 신호 판단의 정확성에 영향을 미칩니다.
트렌드 추적 전략으로, 큰 파동 시장에서 스톱 로즈에 도달하기 쉽다.
위와 같은 위험을 고려하여 SAR 파라미터 또는 필터 파라미터를 적절하게 조정하여 무효 거래의 가능성을 줄일 수 있습니다. 또한 더 큰 시장 변동성을 견딜 수 있도록 스톱 손실 제한을 적절히 완화 할 수 있습니다.
SAR 파라미터를 최적화한다. SAR의 걸음걸이와 증가 파라미터를 역사 재검토 데이터를 통해 최적화하여 보다 안정적이고 효율적인 거래 전략을 얻을 수 있다.
트렌드 판단 지표를 도입한다. 전략에 MACD, DMI 등의 보조 판단 지표를 추가하여 트렌드 판단 능력을 향상시킨다.
리스크 수익률을 최적화한다. 고정 스톱 스톱 손실 비율과 리스크 수익률 파라미터를 조정하여 더 높은 수익을 얻기 위해 더 높은 위험을 적절히 감수한다.
외환 품종을 추가한다. 현재 전략은 디지털 통화 거래만을 지원하고 있으며, 외환, 상품 및 증권 시장 품종을 지원할 수 있도록 확장할 수 있다.
투기 격차는 매우 실용적인 추세를 추적하는 양자형 전략이다. 그것은 민감하게 반응하고, 신호 판단이 신뢰할 수 있으며, 손해 중지 관리로 장기적으로 안정적인 수익을 얻을 수 있다. 적절한 매개 변수 및 규칙 최적화는 전략의 효율성을 더욱 높일 수 있다. 이것은 장기적으로 사용할 가치가 있는 고효율의 양자 전략이다.
/*backtest
start: 2023-10-23 00:00:00
end: 2023-11-22 00:00:00
period: 1h
basePeriod: 15m
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/
//VERSION =================================================================================================================
//@version=5
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// This strategy is intended to study.
// It can also be used to signal a bot to open a deal by providing the Bot ID, email token and trading pair in the strategy settings screen.
// As currently written, this strategy uses a SAR PARABOLIC to send signal, and EMA, Squeeze Momentum, Volatility Oscilator as filter.
// There are two enter point, when SAR Flips, or Breakout Point - the last SAR Value before it Flips.
// There are tree options for exit: SAR Flips, Fixed Stop Loss ande Fixed Take Profit in % and Risk Reward tha can be set, 0.5/1, 1/1, 1/2 etc.
//Autor M4TR1X_BR
//▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
//STRATEGY ================================================================================================================
strategy(title = 'BT-SAR Ema, Squeeze, Voltatility',
shorttitle = 'SAR ESV',
overlay = true)
//▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
// INPUTS =================================================================================================================
// TIME INPUTS
usefromDate = input.bool(defval = true, title = 'Start date', inline = '0', group = "Time Filters")
initialDate = input(defval = timestamp('01 Jan 2022 00:00 UTC'), title = '', inline = "0",group = 'Time Filters',tooltip="This start date is in the time zone of the exchange ")
usetoDate = input.bool(defval = true, title = 'End date', inline = '1', group = "Time Filters")
finalDate = input(defval = timestamp('31 Dec 2029 23:59 UTC'), title = '', inline = "1",group = 'Time Filters',tooltip="This end date is in the time zone of the exchange")
// TIME LOGIC
inTradeWindow = true
// SAR PARABOLIC INPUTS ==================================================================================================
string sargroup= "SAR PARABOLIC ========================================="
start = input.float(defval=0.02,title='Start',inline='',group = sargroup)
increment = input.float(defval=0.02,title='Increment',inline='',group = sargroup)
maximum = input.float(defval=0.2,title='Maximo',inline='',group = sargroup)
// SAR PARABOLIC LOGIC
out = ta.sar(start, increment, maximum)
// SAR FLIP OR BREAKOUT OPTIONS
string bkgroup ='SAR TRADE SIGNAL ====================================== '
sarTradeSignal =input.string(defval='SAR Flip',title='SAR Trade Signal', options= ['SAR Flip','SAR Breakout'],group=bkgroup, tooltip='SAR Flip: Once the parabolic SAR flips it will send a signal, SAR Breakout: Will wait the price cross last Sar Value before it flips.')
nBars = input.int(defval=4,title='Bars',group=bkgroup, tooltip ='Define the number of bars for a entry when the price cross breakout point')
float sarBreakoutPoint= ta.valuewhen((close[1] < out[1]) and (close > out),out[1],0) //Get Sar Breakout Point
bool check = (close[1] < out[1]) and (close > out) //Verify when sar flips
bool BreakoutPrice = sarTradeSignal=='SAR Breakout'? (ta.barssince(check) < nBars) and ((open < sarBreakoutPoint) and (close > sarBreakoutPoint)): (ta.barssince(check) < nBars) and (close > out)
barcolor (check? color.yellow:na,title="Signal Bar color" )
// MOVING AVERAGES INPUTS ================================================================================================
string magroup = "Moving Average ========================================"
useEma = input.bool(defval = true, title = 'Moving Average Filter',inline='', group= magroup,tooltip='This will enable or disable Exponential Moving Average Filter on Strategy')
emaType=input.string (defval='Ema',title='Type',options=['Ema','Sma'],inline='', group= magroup)
emaSource = input.source(defval=close,title=" Source",inline="", group= magroup)
emaLength = input.int(defval=100,title="Length",minval=0,inline='', group= magroup)
// MOVING AVERAGE LOGIC
float ema = emaType=='Ema'? ta.ema(emaSource,emaLength): ta.sma(emaSource,emaLength)
// VOLATILITY OSCILLATOR =================================================================================================
string vogroup = "VOLATILITY OSCILLATOR ================================="
useVltFilter=input.bool(defval=true,title="Volatility Oscillator Filter",inline='',group= vogroup,tooltip='This will enable or disable Volatility Oscillator filter on Strategy')
vltFilterLength = input.int(defval=100,title="Volatility Oscillator",inline='',group=vogroup)
vltFilterSpike = close - open
vltFilterX = ta.stdev(vltFilterSpike,vltFilterLength)
vltFilterY = ta.stdev(vltFilterSpike,vltFilterLength) * -1
// SQUEEZE MOMENTUM INPUTS ==============================================================================================
string sqzgroup = "SQUEEZE MOMENTUM ====================================="
useSqzFilter=input.bool(defval=true,title="Squeeze Momentum Filter",inline='',group= sqzgroup, tooltip='This will enable or disable Squeeze Momentum filter on Strategy')
sqzFilterlength = input.int(defval=20, title='Bollinger Bands Length',inline='',group= sqzgroup)
sqzFiltermult = input.float(defval=2.0, title='Boliinger Bands Mult',inline='',group= sqzgroup)
keltnerLength = input.int(defval=20, title='Keltner Channel Length',inline='',group= sqzgroup)
keltnerMult = input.float(defval=1.5, title='Keltner Channel Mult',inline='',group= sqzgroup)
useTrueRange = input(true, title='Use TrueRange (KC)', inline='',group= sqzgroup)
// CALCULATE BOLLINGER BANDS
sqzFilterSrc = close
basis = ta.sma(sqzFilterSrc, sqzFilterlength)
dev = keltnerMult * ta.stdev(sqzFilterSrc, sqzFilterlength)
upperBB = basis + dev
lowerBB = basis - dev
// CALCULATE KELTNER CHANNEL
sma = ta.sma(sqzFilterSrc, keltnerLength)
range_1 = useTrueRange ? ta.tr : high - low
rangema = ta.sma(range_1, keltnerLength)
upperKC = sma + rangema * keltnerMult
lowerKC = sma - rangema * keltnerMult
// CHECK IF BOLLINGER BANDS IS IN OR OUT OF KELTNER CHANNEL
sqzOn = lowerBB > lowerKC and upperBB < upperKC
sqzOff = lowerBB < lowerKC and upperBB > upperKC
noSqz = sqzOn == false and sqzOff == false
// SQUEEZE MOMENTUM LOGIC
val = ta.linreg(sqzFilterSrc - math.avg(math.avg(ta.highest(high, keltnerLength), ta.lowest(low, keltnerLength)),ta.sma(close, keltnerLength)), keltnerLength, 0)
// ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
// TAKE PROFIT STOP LOSS INPUTS =========================================================================================
string tkpgroup='Take Profit =================================================='
tpType = input.string(defval = 'SAR Flip', title='Take Profit and Stop Loss', options=['SAR Flip','Fixed % TP/SL', 'Risk Reward TP/SL'], group=tkpgroup )
longTakeProfitPerc = input.float(defval = 1.5, title = 'Fixed TP %', minval = 0.05, step = 0.5, group=tkpgroup, tooltip = 'The percentage increase to set the take profit price target.')/100
longLossPerc = input.float(defval=1.0, title="Fixed Long SL %", minval=0.1, step=0.5, group = tkpgroup, tooltip = 'The percentage increase to set the Long Stop Loss price target.') * 0.01
//shortLossPerc = input.float(defval=1.5, title="Fixed Short SL (%)", minval=0.1, step=0.5, group = tkpgroup, tooltip = 'The percentage increase to set the Short Stop Loss price target.') * 0.01
longTakeProfitRR = input.float(defval = 1, title = 'Risk Reward TP', minval = 0.25, step = 0.25, group=tkpgroup, tooltip = 'The Risk Reward parameter.')
var plotStopLossRR = input.bool(defval=false, title='Show RR Stop Loss', group=tkpgroup)
//enableStopLossRR = input.bool(defval = false, title = 'Enable Risk Reward TP',group=tkpgroup, tooltip = 'Enable Variable Stop Loss.')
string trpgroup='Traling Profit ==============================================='
enableTrailing = input.bool(defval = false, title = 'Enable Trailing',group=trpgroup, tooltip = 'Enable or disable the trailing for take profit.')
trailingTakeProfitDeviationPerc = input.float(defval = 0.1, title = 'Trailing Take Profit Deviation %', minval = 0.01, maxval = 100, step = 0.01, group=trpgroup, tooltip = 'The step to follow the price when the take profit limit is reached.') / 100
// BOT MESSAGES
string msgroup='Alert Message For Bot ========================================='
messageEntry = input.string("", title="Strategy Entry Message",group=msgroup)
messageExit =input.string("",title="Strategy Exit Message",group=msgroup)
messageClose = input.string("", title="Strategy Close Message",group=msgroup)
// ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
// POSITIONS =============================================================================================================
//VERIFY IF THE BUY FILTERS ARE ON OR OFF
bool emaFilterBuy = useEma? (close > ema):(close >= ema) or (close <= ema)
bool volatilityFilterBuy = useVltFilter? (vltFilterSpike > vltFilterX) : (vltFilterSpike >= 0) or (vltFilterSpike <= 0)
bool sqzFilterBuy = useSqzFilter? (val > val[1]): (val >= val[1] or val <=val[1])
bool sarflip = (close > out)
//LONG / SHORT POSITIONS LOGIC
//Var 'check' will verify if the SAR flips and if the exit price occurs it will limit in bars number a new entry on the same signal.
bool limitEntryNumbers = (ta.barssince(check) < nBars)
bool openLongPosition = sarTradeSignal == 'SAR Flip'? (sarflip and emaFilterBuy and volatilityFilterBuy and sqzFilterBuy and limitEntryNumbers) :sarTradeSignal=='SAR Breakout'? (BreakoutPrice and emaFilterBuy and volatilityFilterBuy and sqzFilterBuy): na
bool openShortPosition = na
bool closeLongPosition= tpType=='SAR Flip'? (close < out):na
bool closeShortPosition=na
// CHEK OPEN POSITONS =====================================================================================================
// open signal when not already into a position
bool validOpenLongPosition = openLongPosition and strategy.opentrades.size(strategy.opentrades - 1) <= 0
bool longIsActive = validOpenLongPosition or strategy.opentrades.size(strategy.opentrades - 1) > 0
// ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
// TAKE PROFIT STOP LOSS CONFIG ==========================================================================================
// FIXED TAKE PROFIT IN %
float posSize = strategy.opentrades.entry_price(strategy.opentrades - 1) //Get the entry price
var float longTakeProfitPrice = na
longTakeProfitPrice := if (longIsActive)
if (openLongPosition and not (strategy.opentrades.size(strategy.opentrades - 1) > 0))
posSize * (1 + longTakeProfitPerc)
else
nz(longTakeProfitPrice[1], close * (1 + longTakeProfitPerc))
else
na
longTrailingTakeProfitStepTicks = longTakeProfitPrice * trailingTakeProfitDeviationPerc / syminfo.mintick
// FIXED STOP LOSS IN %
longStopPrice = strategy.position_avg_price * (1 - longLossPerc)
//shortStopPrice = strategy.position_avg_price * (1 + shortLossPerc)
// TAKE PROFIT BY RISK/REWARD
// Set stop loss
tta = not (strategy.opentrades.size(strategy.opentrades - 1) > 0)
float lastb = ta.valuewhen(check and tta,ta.lowest(low,5),0) - (10 * syminfo.mintick)
// TAKE PROFIT CALCULATION
float stopLossRisk = (posSize - lastb)
float takeProfitRR = posSize + (longTakeProfitRR * stopLossRisk)
// ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
// POSITION ORDERS =====================================================================================================
// LOGIC ===============================================================================================================
// getting into LONG position
if (openLongPosition) and (inTradeWindow)
strategy.entry(id = 'Long Entry', direction = strategy.long, alert_message=messageEntry)
//submit exit orders for trailing take profit price
if (longIsActive) and (inTradeWindow)
strategy.exit(id = 'Long Take Profit', from_entry = 'Long Entry', limit = enableTrailing ? na : tpType=='Fixed % TP/SL'? longTakeProfitPrice: tpType == 'Risk Reward TP/SL'? takeProfitRR:na, trail_price = enableTrailing ? longTakeProfitPrice : na, trail_offset = enableTrailing ? longTrailingTakeProfitStepTicks : na, stop = tpType =='Fixed % TP/SL' ? longStopPrice: tpType == 'Risk Reward TP/SL'? lastb:na) //, alert_message='{ "action": "close_at_market_price", "message_type": "bot", "bot_id": 9330698, "email_token": "392265bc-84eb-4a54-a99c-758383ff9449", "delay_seconds": 0,"pair":"USDT_{{ticker}}" }')
if (closeLongPosition)
strategy.close(id = 'Long Entry', alert_message='{ "action": "close_at_market_price", "message_type": "bot", "bot_id": 9330698, "email_token": "392265bc-84eb-4a54-a99c-758383ff9449", "delay_seconds": 0,"pair":"USDT_{{ticker}}" }')
// ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
// PLOTS ===============================================================================================================
// TRADE WINDOW ========================================================================================================
bgcolor(color = inTradeWindow ? color.new(#089981,90):na, title = 'Time Window')
// SAR PARABOLIC
var sarColor = color.new(#00bcd4,0)
plot(out, "ParabolicSAR", color=sarColor, linewidth=1,style=plot.style_cross)
//BREAKOUT LINE
var plotBkPoint = input.bool(defval=false, title='Show Breakout Point', group=bkgroup)
plot(series = (sarTradeSignal=='SAR Breakout' and plotBkPoint == true)? sarBreakoutPoint:na, title = 'Breakout line', color =color.new(#ffeb3b,50) , linewidth = 1, style = plot.style_linebr, offset = 0)
// EMA/SMA
var emafilterColor = color.new(color.white, 0)
plot(series=useEma? ema:na, title = 'EMA Filter', color = emafilterColor, linewidth = 2, style = plot.style_line)
// ENTRY PRICE
var posColor = color.new(#2962ff, 0)
plot(series = strategy.opentrades.entry_price(strategy.opentrades - 1), title = 'Position', color = posColor, linewidth = 1, style = plot.style_linebr,offset=0)
// FIXED TAKE PROFIT
var takeProfitColor = color.new(#ba68c8, 0)
plot(series = tpType=='Fixed % TP/SL'? longTakeProfitPrice:na, title = 'Fixed TP', color = takeProfitColor, linewidth = 1, style = plot.style_linebr, offset = 0)
// FIXED STOP LOSS
var stopLossColor = color.new(#ff0000, 0)
plot(series = tpType=='Fixed % TP/SL' ? longStopPrice:na, title = 'Fixed SL', color = stopLossColor, linewidth = 1, style = plot.style_linebr, offset = 0)
// RISK REWARD TAKE PROFIT
var takeProfitRRColor = color.new(#ba68c8, 0)
plot(series=tpType == 'Risk Reward TP/SL'? takeProfitRR:na,title='Risk Reward TP',color=takeProfitRRColor,linewidth=1,style=plot.style_linebr)
// STOP LOSS RISK REWARD
plot(series = (check and plotStopLossRR)? lastb:na, title = 'Last Bottom', color =color.new(#ff0000,0), linewidth = 2, style = plot.style_linebr, offset = 0)
// ======================================================================================================================