Chiến lược giao dịch EMA có độ trễ không thích nghi

Tác giả:ChaoZhang, Ngày: 2023-09-13 14:22:55
Tags:

Chiến lược này sử dụng chỉ số EMA Zero Lag thích nghi để xác định xu hướng và tín hiệu giao dịch. EMA thích nghi điều chỉnh các tham số một cách năng động để loại bỏ sự chậm trễ. Nó nhằm mục đích theo xu hướng.

Chiến lược logic:

  1. Tính toán Adaptive Zero Lag EMA bằng thuật toán thích nghi cosinus và I-Q.

  2. EMA là EMA bình thường, EC là EMA thích nghi không trễ.

  3. Đi dài khi EC vượt qua EMA, và ngắn khi vượt qua dưới.

  4. Tính toán đường cong lỗi và đặt ngưỡng để lọc tín hiệu sai.

  5. Sử dụng các điểm cố định để dừng lỗ và lấy lợi nhuận để kiểm soát rủi ro.

Ưu điểm:

  1. EMA thích nghi làm giảm đáng kể sự chậm trễ của chỉ số.

  2. Chế độ lọc ngưỡng cải thiện chất lượng tín hiệu và tránh các sự đột phá sai.

  3. Các điểm dừng và mục tiêu đơn giản rất dễ thực hiện.

Rủi ro:

  1. Các thông số EMA thích nghi có thể trở nên không ổn định.

  2. Các điểm dừng / mục tiêu cố định không thích nghi với các điều kiện thị trường thay đổi.

  3. Không có giới hạn về kích thước lỗ, rủi ro thua lỗ lớn.

Tóm lại, chiến lược này sử dụng EMA thích nghi để theo xu hướng, làm giảm sự chậm trễ ở một mức độ nào đó.


/*backtest
start: 2023-09-05 00:00:00
end: 2023-09-12 00:00:00
period: 2h
basePeriod: 15m
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

//@version=3
strategy(title="Adaptive Zero Lag EMA v2 (w/ Backtest Date Range)", shorttitle="AZLEMA", overlay = true,  commission_type=strategy.commission.cash_per_contract, slippage = 5, pyramiding=1, calc_on_every_tick=true)

src = input(title="Source",  defval=close)
secType = input(title="Security Type", options=["Forex", "Metal Spot", "Cryptocurrency","Custom"], defval="Forex")
contracts = input(title="Custom # of Contracts", defval=1, step=1)
limit = input(title="Max Lots",  defval=100)
Period = input(title="Period",  defval = 20)
adaptive = input(title="Adaptive Method", options=["Off", "Cos IFM", "I-Q IFM", "Average"], defval="Cos IFM")
GainLimit = input(title="Gain Limit",  defval = 8)
Threshold = input(title="Threshold",  defval=0.05, step=0.01)
fixedSL = input(title="SL Points", defval=70)
fixedTP = input(title="TP Points", defval=10)
risk = input(title='Risk', defval=0.01, step=0.01)

// === INPUT BACKTEST RANGE ===
FromMonth = input(defval = 1, title = "From Month", minval = 1, maxval = 12)
FromDay   = input(defval = 1, title = "From Day", minval = 1, maxval = 31)
FromYear  = input(defval = 2019, title = "From Year", minval = 2015)
ToMonth   = input(defval = 1, title = "To Month", minval = 1, maxval = 12)
ToDay     = input(defval = 1, title = "To Day", minval = 1, maxval = 31)
ToYear    = input(defval = 9999, title = "To Year", minval = 2015)

// === FUNCTION EXAMPLE ===
start     = timestamp(FromYear, FromMonth, FromDay, 00, 00)  // backtest start window
finish    = timestamp(ToYear, ToMonth, ToDay, 23, 59)        // backtest finish window
window()  => true

range = 50 //input(title="Max Period",  defval=60, minval=8, maxval=100)

PI = 3.14159265359
lenIQ = 0.0
lenC = 0.0

//##############################################################################
//I-Q IFM
//##############################################################################
if(adaptive=="I-Q IFM" or adaptive=="Average")
    imult = 0.635
    qmult = 0.338
    inphase = 0.0
    quadrature = 0.0
    re = 0.0
    im = 0.0
    deltaIQ = 0.0
    instIQ = 0.0
    V = 0.0
    
    P = src - src[7]
    inphase := 1.25*(P[4] - imult*P[2]) + imult*nz(inphase[3])
    quadrature := P[2] - qmult*P + qmult*nz(quadrature[2])
    re := 0.2*(inphase*inphase[1] + quadrature*quadrature[1]) + 0.8*nz(re[1])
    im := 0.2*(inphase*quadrature[1] - inphase[1]*quadrature) + 0.8*nz(im[1])
    if (re!= 0.0)
        deltaIQ := atan(im/re)
    for i=0 to range
        V := V + deltaIQ[i]
        if (V > 2*PI and instIQ == 0.0)
            instIQ := i
    if (instIQ == 0.0)
        instIQ := nz(instIQ[1])
    lenIQ := 0.25*instIQ + 0.75*nz(lenIQ[1])

//##############################################################################
//COSINE IFM
//##############################################################################
if(adaptive == "Cos IFM" or adaptive == "Average")
    s2 = 0.0
    s3 = 0.0
    deltaC = 0.0
    instC = 0.0
    v1 = 0.0
    v2 = 0.0
    v4 = 0.0
    
    v1 := src - src[7]
    s2 := 0.2*(v1[1] + v1)*(v1[1] + v1) + 0.8*nz(s2[1])
    s3 := 0.2*(v1[1] - v1)*(v1[1] - v1) + 0.8*nz(s3[1])
    if (s2 != 0)
        v2 := sqrt(s3/s2)
    if (s3 != 0)
        deltaC := 2*atan(v2)
    for i = 0 to range
        v4 := v4 + deltaC[i]
        if (v4 > 2*PI and instC == 0.0)
            instC := i - 1
    if (instC == 0.0)
        instC := instC[1]
    lenC := 0.25*instC + 0.75*nz(lenC[1])

if (adaptive == "Cos IFM")
    Period := round(lenC)
if (adaptive == "I-Q IFM")
    Period := round(lenIQ)
if (adaptive == "Average")
    Period := round((lenC + lenIQ)/2)

//##############################################################################
//ZERO LAG EXPONENTIAL MOVING AVERAGE
//##############################################################################
LeastError = 1000000.0
EC = 0.0
Gain = 0.0
EMA = 0.0
Error = 0.0
BestGain = 0.0

alpha =2/(Period + 1)
EMA := alpha*src + (1-alpha)*nz(EMA[1])

for i = -GainLimit to GainLimit
    Gain := i/10
    EC := alpha*(EMA + Gain*(src - nz(EC[1]))) + (1 - alpha)*nz(EC[1])
    Error := src - EC
    if(abs(Error)<LeastError)
        LeastError := abs(Error)
        BestGain := Gain

EC := alpha*(EMA + BestGain*(src - nz(EC[1]))) + (1-alpha)*nz(EC[1])

plot(EC, title="EC", color=orange, linewidth=2)
plot(EMA, title="EMA", color=red, linewidth=2)

//##############################################################################
//Trade Logic & Risk Management
//##############################################################################
buy = crossover(EC,EMA) and 100*LeastError/src > Threshold
sell = crossunder(EC,EMA) and 100*LeastError/src > Threshold

secScaler = secType == "Forex" ? 100000 : secType == "Metal Spot" ? 100 : secType == "Cryptocurrency" ? 10000 : secType == "Custom" ? contracts : 0
strategy.initial_capital = 50000
balance = strategy.initial_capital + strategy.netprofit
if (time>timestamp(2016, 1, 1 , 0, 0) and balance > 0)
    //LONG
    lots = ((risk * balance)/fixedSL)*secScaler
    lots := lots > limit * secScaler ? limit * secScaler : lots
    strategy.entry("BUY", strategy.long,  oca_name="BUY",  when=buy and window())
    strategy.exit("B.Exit", "BUY", qty_percent = 100, loss=fixedSL, trail_offset=15, trail_points=fixedTP)
    //SHORT
    strategy.entry("SELL", strategy.short,  oca_name="SELL",when=sell and window())
    strategy.exit("S.Exit", "SELL", qty_percent = 100, loss=fixedSL, trail_offset=15, trail_points=fixedTP)


Thêm nữa