
이번 호에서는 YouTube의 “마법의 이중 EMA 이동 평균 전략”에 대해 논의하겠습니다. 이는 “주식 및 암호화폐 시장 킬러”라고 불립니다. 영상을 본 후, 이 전략은 2개의 트레이딩 뷰 지표를 사용하는 트레이딩 뷰 파인 언어 전략이라는 것을 알게 되었습니다. 영상에서 백테스팅 결과가 매우 좋았고, FMZ도 Trading View의 Pine 언어를 지원해서, 직접 백테스팅을 하고 분석을 테스트하고 싶지 않을 수 없었습니다. 그러면 인생 전체를 시작하세요! 영상 속 전략을 재현해 보겠습니다.
디자인의 단순성을 위해 영상에 나와 있는 이동 평균 지수는 사용하지 않을 것입니다. 대신 Trading View에 내장된 ta.ema를 사용합니다(실제로 둘은 동일합니다).
이것은 Trading View의 지표입니다. Trading View로 가서 소스 코드를 다운로드해야 합니다.

VuManChu Swing 무료 코드:
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// Credits to the original Script - Range Filter DonovanWall https://www.tradingview.com/script/lut7sBgG-Range-Filter-DW/
// This version is the old version of the Range Filter with less settings to tinker with
//@version=4
study(title="Range Filter - B&S Signals", shorttitle="RF - B&S Signals", overlay=true)
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------
//Functions
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------
//Range Size Function
rng_size(x, qty, n)=>
// AC = Cond_EMA(abs(x - x[1]), 1, n)
wper = (n*2) - 1
avrng = ema(abs(x - x[1]), n)
AC = ema(avrng, wper)*qty
rng_size = AC
//Range Filter Function
rng_filt(x, rng_, n)=>
r = rng_
var rfilt = array.new_float(2, x)
array.set(rfilt, 1, array.get(rfilt, 0))
if x - r > array.get(rfilt, 1)
array.set(rfilt, 0, x - r)
if x + r < array.get(rfilt, 1)
array.set(rfilt, 0, x + r)
rng_filt1 = array.get(rfilt, 0)
hi_band = rng_filt1 + r
lo_band = rng_filt1 - r
rng_filt = rng_filt1
[hi_band, lo_band, rng_filt]
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------
//Inputs
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------
//Range Source
rng_src = input(defval=close, type=input.source, title="Swing Source")
//Range Period
rng_per = input(defval=20, minval=1, title="Swing Period")
//Range Size Inputs
rng_qty = input(defval=3.5, minval=0.0000001, title="Swing Multiplier")
//Bar Colors
use_barcolor = input(defval=false, type=input.bool, title="Bar Colors On/Off")
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------
//Definitions
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------
//Range Filter Values
[h_band, l_band, filt] = rng_filt(rng_src, rng_size(rng_src, rng_qty, rng_per), rng_per)
//Direction Conditions
var fdir = 0.0
fdir := filt > filt[1] ? 1 : filt < filt[1] ? -1 : fdir
upward = fdir==1 ? 1 : 0
downward = fdir==-1 ? 1 : 0
//Trading Condition
longCond = rng_src > filt and rng_src > rng_src[1] and upward > 0 or rng_src > filt and rng_src < rng_src[1] and upward > 0
shortCond = rng_src < filt and rng_src < rng_src[1] and downward > 0 or rng_src < filt and rng_src > rng_src[1] and downward > 0
CondIni = 0
CondIni := longCond ? 1 : shortCond ? -1 : CondIni[1]
longCondition = longCond and CondIni[1] == -1
shortCondition = shortCond and CondIni[1] == 1
//Colors
filt_color = upward ? #05ff9b : downward ? #ff0583 : #cccccc
bar_color = upward and (rng_src > filt) ? (rng_src > rng_src[1] ? #05ff9b : #00b36b) :
downward and (rng_src < filt) ? (rng_src < rng_src[1] ? #ff0583 : #b8005d) : #cccccc
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------
//Outputs
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------
//Filter Plot
filt_plot = plot(filt, color=filt_color, transp=67, linewidth=3, title="Filter")
//Band Plots
h_band_plot = plot(h_band, color=color.new(#05ff9b, 100), title="High Band")
l_band_plot = plot(l_band, color=color.new(#ff0583, 100), title="Low Band")
//Band Fills
fill(h_band_plot, filt_plot, color=color.new(#00b36b, 92), title="High Band Fill")
fill(l_band_plot, filt_plot, color=color.new(#b8005d, 92), title="Low Band Fill")
//Bar Color
barcolor(use_barcolor ? bar_color : na)
//Plot Buy and Sell Labels
plotshape(longCondition, title = "Buy Signal", text ="BUY", textcolor = color.white, style=shape.labelup, size = size.normal, location=location.belowbar, color = color.new(color.green, 0))
plotshape(shortCondition, title = "Sell Signal", text ="SELL", textcolor = color.white, style=shape.labeldown, size = size.normal, location=location.abovebar, color = color.new(color.red, 0))
//Alerts
alertcondition(longCondition, title="Buy Alert", message = "BUY")
alertcondition(shortCondition, title="Sell Alert", message = "SELL")
EMA 지표: 이 전략은 두 개의 EMA 이동 평균선을 사용합니다. 하나는 빠른 선(작은 주기 매개변수)이고 다른 하나는 느린 선(큰 주기 매개변수)입니다. 이중 EMA 이동평균선의 주요 기능은 시장 추세의 방향을 결정하는 데 도움이 되는 것입니다.
긴 배열 빠른 선은 느린 선 위에 있습니다.
짧은 배열 빠른 선은 느린 선 아래에 있습니다.
VuManChu Swing Free 지표: VuManChu Swing Free 지표는 신호를 보내는 데 사용되며, 이후 다른 조건과 결합하여 거래 주문을 할지 여부를 결정합니다. VuManChu Swing Free 지표 소스 코드에서 longCondition 변수는 매수 신호를 나타내고 shortCondition 변수는 매도 신호를 나타낸다는 것을 알 수 있습니다. 이 두 변수는 나중에 주문 조건을 작성할 때 사용됩니다.
이제 전략의 구체적인 거래 신호 발동 조건에 대해 알아보겠습니다.
롱 포지션 진입 규칙: 양의 K-라인의 종가는 EMA 패스트라인 위에 있어야 하며, 두 개의 EMA 이동평균은 강세 배열에 있어야 합니다(패스트라인이 슬로우라인 위에 있음), VuManChu Swing Free 지표는 매수 신호를 보여야 합니다. (longCondition이 참입니다). 세 가지 조건이 충족된다면, 이 K-라인은 롱 포지션에 진입하기 위한 주요 K-라인이고, 이 K-라인의 종가가 진입 포지션이 됩니다.
숏 포지션(롱 포지션과 반대) 진입 규칙: 음의 캔들스틱의 종가는 빠른 EMA 라인 아래에 있어야 하며, 두 개의 EMA 이동 평균은 숏 포지션에 있어야 합니다(빠른 라인은 느린 라인 아래에 있음), 그리고 VuManChu Swing Free 지표는 매도 신호를 보여야 합니다(shortCondition (사실입니다). 세 가지 조건이 충족된다면, 이 K-라인의 종가는 공매도의 진입점입니다.
거래 로직이 매우 간단하지 않나요? 소스 비디오에는 이익실현과 손절매가 명시되어 있지 않기 때문에 편집자는 고정 포인트 손절매와 추적을 사용하여 보다 온건한 이익실현 및 손절매 방법을 사용할 것입니다. 이익 실현.
우리는 VuManChu Swing Free 지표의 코드를 그대로 전략 코드에 직접 넣었습니다.

그런 다음 트랜잭션 기능을 구현하기 위해 Pine 언어 코드를 작성합니다.
// extend
fastEmaPeriod = input(50, "fastEmaPeriod") // 快线周期
slowEmaPeriod = input(200, "slowEmaPeriod") // 慢线周期
loss = input(30, "loss") // 止损点数
trailPoints = input(30, "trailPoints") // 移动止盈触发点数
trailOffset = input(30, "trailOffset") // 移动止盈偏移量(点数)
amount = input(1, "amount") // 下单量
emaFast = ta.ema(close, fastEmaPeriod) // 计算快线EMA
emaSlow = ta.ema(close, slowEmaPeriod) // 计算慢线EMA
buyCondition = longCondition and emaFast > emaSlow and close > open and close > emaFast // 做多入场条件
sellCondition = shortCondition and emaFast < emaSlow and close < open and close < emaFast // 做空入场条件
if buyCondition and strategy.position_size == 0
strategy.entry("long", strategy.long, amount)
strategy.exit("exit_long", "long", amount, loss=loss, trail_points=trailPoints, trail_offset=trailOffset)
if sellCondition and strategy.position_size == 0
strategy.entry("short", strategy.short, amount)
strategy.exit("exit_short", "short", amount, loss=loss, trail_points=trailPoints, trail_offset=trailOffset)
A. 보시다시피 buyCondition이 참일 때:
- longCondition 변수가 참입니다(VuManChu Swing Free 지표가 롱 포지션으로 전환하라는 신호를 보냅니다).
- emaFast > emaSlow (EMA 강세 조정).
- close > open (현재 BAR이 양의 선임을 나타냄), close > emaFast (마진 가격이 EMA fast line 위에 있음을 나타냄).
장기 투자를 위한 세 가지 조건이 충족되었습니다.
B. sellCondition이 참인 경우 공매도에 대한 세 가지 조건이 충족됩니다(여기서는 설명하지 않음).
그런 다음 if 조건에서 신호가 트리거되었다고 판단되면 strategy.entry 함수를 사용하여 시장에 진입하고 포지션을 개시하고, strategy.exit 함수를 설정하여 손실 중단 및 추적 이익을 설정합니다.
/*backtest
start: 2022-01-01 00:00:00
end: 2022-10-08 00:00:00
period: 15m
basePeriod: 5m
exchanges: [{"eid":"Futures_Binance","currency":"ETH_USDT"}]
args: [["ZPrecision",0,358374]]
*/
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// Credits to the original Script - Range Filter DonovanWall https://www.tradingview.com/script/lut7sBgG-Range-Filter-DW/
// This version is the old version of the Range Filter with less settings to tinker with
//@version=4
study(title="Range Filter - B&S Signals", shorttitle="RF - B&S Signals", overlay=true)
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------
//Functions
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------
//Range Size Function
rng_size(x, qty, n)=>
// AC = Cond_EMA(abs(x - x[1]), 1, n)
wper = (n*2) - 1
avrng = ema(abs(x - x[1]), n)
AC = ema(avrng, wper)*qty
rng_size = AC
//Range Filter Function
rng_filt(x, rng_, n)=>
r = rng_
var rfilt = array.new_float(2, x)
array.set(rfilt, 1, array.get(rfilt, 0))
if x - r > array.get(rfilt, 1)
array.set(rfilt, 0, x - r)
if x + r < array.get(rfilt, 1)
array.set(rfilt, 0, x + r)
rng_filt1 = array.get(rfilt, 0)
hi_band = rng_filt1 + r
lo_band = rng_filt1 - r
rng_filt = rng_filt1
[hi_band, lo_band, rng_filt]
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------
//Inputs
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------
//Range Source
rng_src = input(defval=close, type=input.source, title="Swing Source")
//Range Period
rng_per = input(defval=20, minval=1, title="Swing Period")
//Range Size Inputs
rng_qty = input(defval=3.5, minval=0.0000001, title="Swing Multiplier")
//Bar Colors
use_barcolor = input(defval=false, type=input.bool, title="Bar Colors On/Off")
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------
//Definitions
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------
//Range Filter Values
[h_band, l_band, filt] = rng_filt(rng_src, rng_size(rng_src, rng_qty, rng_per), rng_per)
//Direction Conditions
var fdir = 0.0
fdir := filt > filt[1] ? 1 : filt < filt[1] ? -1 : fdir
upward = fdir==1 ? 1 : 0
downward = fdir==-1 ? 1 : 0
//Trading Condition
longCond = rng_src > filt and rng_src > rng_src[1] and upward > 0 or rng_src > filt and rng_src < rng_src[1] and upward > 0
shortCond = rng_src < filt and rng_src < rng_src[1] and downward > 0 or rng_src < filt and rng_src > rng_src[1] and downward > 0
CondIni = 0
CondIni := longCond ? 1 : shortCond ? -1 : CondIni[1]
longCondition = longCond and CondIni[1] == -1
shortCondition = shortCond and CondIni[1] == 1
//Colors
filt_color = upward ? #05ff9b : downward ? #ff0583 : #cccccc
bar_color = upward and (rng_src > filt) ? (rng_src > rng_src[1] ? #05ff9b : #00b36b) :
downward and (rng_src < filt) ? (rng_src < rng_src[1] ? #ff0583 : #b8005d) : #cccccc
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------
//Outputs
//-----------------------------------------------------------------------------------------------------------------------------------------------------------------
//Filter Plot
filt_plot = plot(filt, color=filt_color, transp=67, linewidth=3, title="Filter")
//Band Plots
h_band_plot = plot(h_band, color=color.new(#05ff9b, 100), title="High Band")
l_band_plot = plot(l_band, color=color.new(#ff0583, 100), title="Low Band")
//Band Fills
fill(h_band_plot, filt_plot, color=color.new(#00b36b, 92), title="High Band Fill")
fill(l_band_plot, filt_plot, color=color.new(#b8005d, 92), title="Low Band Fill")
//Bar Color
barcolor(use_barcolor ? bar_color : na)
//Plot Buy and Sell Labels
plotshape(longCondition, title = "Buy Signal", text ="BUY", textcolor = color.white, style=shape.labelup, size = size.normal, location=location.belowbar, color = color.new(color.green, 0))
plotshape(shortCondition, title = "Sell Signal", text ="SELL", textcolor = color.white, style=shape.labeldown, size = size.normal, location=location.abovebar, color = color.new(color.red, 0))
//Alerts
alertcondition(longCondition, title="Buy Alert", message = "BUY")
alertcondition(shortCondition, title="Sell Alert", message = "SELL")
// extend
fastEmaPeriod = input(50, "fastEmaPeriod")
slowEmaPeriod = input(200, "slowEmaPeriod")
loss = input(30, "loss")
trailPoints = input(30, "trailPoints")
trailOffset = input(30, "trailOffset")
amount = input(1, "amount")
emaFast = ta.ema(close, fastEmaPeriod)
emaSlow = ta.ema(close, slowEmaPeriod)
buyCondition = longCondition and emaFast > emaSlow and close > open and close > emaFast
sellCondition = shortCondition and emaFast < emaSlow and close < open and close < emaFast
if buyCondition and strategy.position_size == 0
strategy.entry("long", strategy.long, amount)
strategy.exit("exit_long", "long", amount, loss=loss, trail_points=trailPoints, trail_offset=trailOffset)
if sellCondition and strategy.position_size == 0
strategy.entry("short", strategy.short, amount)
strategy.exit("exit_short", "short", amount, loss=loss, trail_points=trailPoints, trail_offset=trailOffset)
백테스팅 시간 범위는 2022년 1월부터 2022년 10월까지로 선택되었으며, K-라인 기간은 15분이고, 백테스팅에는 종가 모델을 사용했습니다. 시장에서는 바이낸스의 ETH_USDT 선물 계약을 선택합니다. 매개변수 설정은 소스 영상에 나와 있는 대로입니다. 빠른 회선의 경우 50주기, 느린 회선의 경우 200주기이며, 다른 매개변수는 기본적으로 변경되지 않습니다. 저는 손절매와 추적 이익 지점을 설정하는 데 약간 주관적이며, 그냥 30포인트로 설정합니다.


백테스트 결과는 그저 그렇습니다. 여러 백테스트를 거친 후, 이익 실현 및 손절매와 같은 매개변수가 백테스트 결과에 어느 정도 영향을 미치는 것으로 보입니다. 저는 이 측면이 더욱 최적화되어야 한다고 생각합니다. 하지만 전략적 신호가 거래를 촉발한 후에도 승률은 여전히 좋습니다.
BTC_USDT 영구 계약을 시도해 보겠습니다.

BTC 백테스트 결과 역시 폭발적입니다.


전략 주소: https://www.fmz.com/strategy/385745
이 거래 방식은 추세를 파악하는 데 비교적 신뢰할 만한 것으로 보이며, 이 아이디어를 바탕으로 설계를 더욱 최적화할 수 있습니다. 이 글에서는 이중 이동 평균 전략의 개념을 배울 뿐만 아니라 유튜브 거장들의 전략을 처리하고 학습하는 방법도 알아보았습니다. 알겠습니다. 위의 전략 코드는 제 제안일 뿐입니다. 백테스트 결과는 구체적인 실제 결과를 나타내지 않습니다. 전략 코드와 설계는 참고용일 뿐입니다. 여러분의 응원에 감사드립니다. 다음에 또 뵙겠습니다!