振動スペクトル移動平均取引戦略

作者: リン・ハーンチャオチャン,日付: 2024-01-25 14:19:27
タグ:

img

概要

この戦略は,スペクトラム移動平均をベースに,高速移動平均と遅移動平均の黄金十字と死亡十字を通じて取引信号を生成する.スペクトラム移動平均は,単純な移動平均から振動移動平均まで様々な種類をカバーし,強力な適応性のためにパラメータ調整を通じて自由に組み合わせることができます.

戦略原則

この戦略は,12種類の異なる移動平均を生成できる変数移動平均関数を使用する.基本的な原則は,2つの移動平均線,高速線 (Close MA) と遅い線 (Open MA) を計算することです.高速線がスローラインを越えると,購入信号が生成されます.高速線がスローラインを下回ると,販売信号が生成されます.ストップ損失と利益のパラメータも自動的にストップ損失と利益を得るために設定されています.

鍵となる論理は,変数関数を通して 2 つの移動平均線を生成することです.closeSeries = variant(basisType, close, basisLen, offsetSigma, offsetALMA)そしてopenSeries = variant(basisType, open, basisLen, offsetSigma, offsetALMA)

取引シグナルを生成する基本的な論理は:longCond = xlongそしてshortCond = xshortつまり,高速線がスローラインを横切ると,ロングポジションが取られ,高速線がスローラインを横切ると,ショートポジションが取られます.

入場ルールは,longCondまたはshortCond条件が満たされたときにロングまたはショートに行く.出口ルールは,価格動きが事前に設定されたストップ・ロスト/プロフィートポイントに達したとき,ストップ・ロストまたはプロフィートのためにポジションを閉じる.

利点分析

リスク分析

この戦略の最大のリスクは,スペクトル移動平均値自体も一定の遅れがあることです.異常な価格突破は大きな損失を引き起こす可能性があります.また,不適切なパラメータ選択は,過剰な取引頻度または冗長な信号につながる可能性があります.

オプティマイゼーションの方向性

この戦略の主要な最適化方向は以下の通りである.

  1. 最良の組み合わせを見つけるために移動平均の組み合わせの種類をテストする
  2. 偽の信号を避けるためにフィルターを追加します.例えば,取引量指標を組み合わせることなどです.
  3. ポジションのサイズ,ストップ・ロスト,収益のパラメータを最適化

上記の方向で最適化することで,戦略のライブ取引パフォーマンスは継続的に改善できます.

概要

この取引戦略は,スペクトル移動平均値に基づいて高い柔軟性を実装する. ユーザーはさまざまな種類の移動平均値を自由に選択し,組み合わせることができる強力なカスタマイズ性を提供する. 戦略ロジックはシンプルで明確で,使いやすくて,豊富な最適化スペースも提供している. パラメータ最適化とリスク管理を通じて,この戦略は異なる市場環境に適応し,安定した収益を得ることができます. これは効率的で柔軟なトレンド追跡戦略です.


/*backtest
start: 2023-01-18 00:00:00
end: 2024-01-24 00:00:00
period: 1d
basePeriod: 1h
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

//@version=4
//

strategy(title="Long/Short", shorttitle="Banana Maker", overlay=true, pyramiding=0, default_qty_type=strategy.percent_of_equity, default_qty_value=100, calc_on_every_tick=false)



// === INPUTS ===
useRes = input(defval=true, title="Use Alternate Resolution?")
intRes = input(defval=7, title="Multiplier for Alernate Resolution")
stratRes = timeframe.ismonthly ? tostring(timeframe.multiplier * intRes, "###M") : 
   timeframe.isweekly ? tostring(timeframe.multiplier * intRes, "###W") : 
   timeframe.isdaily ? tostring(timeframe.multiplier * intRes, "###D") : 
   timeframe.isintraday ? tostring(timeframe.multiplier * intRes, "####") : '60'
basisType = input(defval="DEMA", title="MA Type: ", options=["SMA", "EMA", "DEMA", "TEMA", "WMA", "VWMA", "SMMA", "HullMA", "LSMA", "ALMA", "SSMA", "TMA"])
basisLen = input(defval=8, title="MA Period", minval=1)
offsetSigma = input(defval=6, title="Offset for LSMA / Sigma for ALMA", minval=0)
offsetALMA = input(defval=0.85, title="Offset for ALMA", minval=0, step=0.01)
scolor = input(false, title="Show coloured Bars to indicate Trend?")
delayOffset = input(defval=0, title="Delay Open/Close MA (Forces Non-Repainting)", minval=0, step=1)
tradeType = input("BOTH", title="What trades should be taken : ", options=["LONG", "SHORT", "BOTH", "NONE"])
// === /INPUTS ===

// Constants colours that include fully non-transparent option.
green100 = #008000FF
lime100 = #6ad279
red100 = #FF0000FF
blue100 = #0000FFFF
aqua100 = #00FFFFFF
darkred100 = #8B0000FF
gray100 = #808080FF

// === BASE FUNCTIONS ===
variant(type, src, len, offSig, offALMA) =>
    v1 = sma(src, len)  // Simple
    v2 = ema(src, len)  // Exponential
    v3 = 2 * v2 - ema(v2, len)  // Double Exponential
    v4 = 3 * (v2 - ema(v2, len)) + ema(ema(v2, len), len)  // Triple Exponential
    v5 = wma(src, len)  // Weighted
    v6 = vwma(src, len)  // Volume Weighted
    v7 = 0.0
    sma_1 = sma(src, len)  // Smoothed
    v7 := na(v7[1]) ? sma_1 : (v7[1] * (len - 1) + src) / len
    v8 = wma(2 * wma(src, len / 2) - wma(src, len), round(sqrt(len)))  // Hull
    v9 = linreg(src, len, offSig)  // Least Squares
    v10 = alma(src, len, offALMA, offSig)  // Arnaud Legoux
    v11 = sma(v1, len)  // Triangular (extreme smooth)
    // SuperSmoother filter
    // © 2013  John F. Ehlers
    a1 = exp(-1.414 * 3.14159 / len)
    b1 = 2 * a1 * cos(1.414 * 3.14159 / len)
    c2 = b1
    c3 = -a1 * a1
    c1 = 1 - c2 - c3
    v12 = 0.0
    v12 := c1 * (src + nz(src[1])) / 2 + c2 * nz(v12[1]) + c3 * nz(v12[2])
    type == "EMA" ? v2 : type == "DEMA" ? v3 : 
       type == "TEMA" ? v4 : type == "WMA" ? v5 : type == "VWMA" ? v6 : 
       type == "SMMA" ? v7 : type == "HullMA" ? v8 : type == "LSMA" ? v9 : 
       type == "ALMA" ? v10 : type == "TMA" ? v11 : type == "SSMA" ? v12 : v1

// security wrapper for repeat calls* NEEDS REFINEMENT- backtesting this shows repaint. need new wrapper
reso(exp, use, res) =>
    security_1 = security(syminfo.tickerid, res, exp, gaps=barmerge.gaps_off, lookahead=barmerge.lookahead_on)
    use ? security_1 : exp



// === /BASE FUNCTIONS ===

// === SERIES SETUP ===
closeSeries = variant(basisType, close[delayOffset], basisLen, offsetSigma, offsetALMA)
openSeries = variant(basisType, open[delayOffset], basisLen, offsetSigma, offsetALMA)
// === /SERIES ===

// === PLOTTING ===

// alt resulution 
closeSeriesAlt = reso(closeSeries, useRes, stratRes)
openSeriesAlt = reso(openSeries, useRes, stratRes)
//
trendColour = closeSeriesAlt > openSeriesAlt ? color.green : color.red
bcolour = closeSeries > openSeriesAlt ? lime100 : red100
barcolor(scolor ? bcolour : na, title="Bar Colours")
closeP = plot(closeSeriesAlt, title="Close Series", color=trendColour, linewidth=0, style=plot.style_line, transp=1)
openP = plot(openSeriesAlt, title="Open Series", color=trendColour, linewidth=0, style=plot.style_line, transp=1)
fill(closeP, openP, color=trendColour, transp=80)

// === /PLOTTING ===
//

//
// === ALERT conditions

xlong = crossover(closeSeriesAlt, openSeriesAlt)
xshort = crossunder(closeSeriesAlt, openSeriesAlt)
longCond = xlong  // alternative: longCond[1]? false : (xlong or xlong[1]) and close>closeSeriesAlt and close>=open
shortCond = xshort  // alternative: shortCond[1]? false : (xshort or xshort[1]) and close<closeSeriesAlt and close<=open


// === /ALERT conditions. needs work in study mode. the banana maker is the study script. 
// Create alert for cross, shunt back 1 if source is not 'open', this should prevent repaint issue.
//shunt = RSIsrc == open ? 0 : 1
//shunt = 0
//c_alert = (buy[shunt]==1 or sell[shunt]==1)
//alertcondition(c_alert, title="QQECROSS Alert", message="QQECROSS Alert")
// show only when alert condition is met and bar closed.
//plotshape(c_alert,title= "Alert Indicator Closed", location=location.bottom, color=sell[shunt]==1?red:green, transp=0, style=shape.circle)

//Repaint city, study mode will help but wont trigger the alerts


// === STRATEGY ===
// stop loss
slPoints = input(defval=0, title="Initial Stop Loss Points (zero to disable)", minval=0)
tpPoints = input(defval=0, title="Initial Target Profit Points (zero for disable)", minval=0)
// Include bar limiting algorithm
ebar = input(defval=1000, title="Number of Bars for Back Testing", minval=0)
dummy = input(false, title="- SET to ZERO for Daily or Longer Timeframes")
//
// Calculate how many mars since last bar
tdays = (timenow - time) / 60000.0  // number of minutes since last bar
tdays := timeframe.ismonthly ? tdays / 1440.0 / 5.0 / 4.3 / timeframe.multiplier : 
   timeframe.isweekly ? tdays / 1440.0 / 5.0 / timeframe.multiplier : 
   timeframe.isdaily ? tdays / 1440.0 / timeframe.multiplier : 
   tdays / timeframe.multiplier  // number of bars since last bar
//
//set up exit parameters
TP = tpPoints > 0 ? tpPoints : na
SL = slPoints > 0 ? slPoints : na

// Make sure we are within the bar range, Set up entries and exit conditions
if (ebar == 0 or tdays <= ebar) and tradeType != "NONE"
    strategy.entry("long", strategy.long, when=longCond == true and tradeType != "SHORT")
    strategy.entry("short", strategy.short, when=shortCond == true and tradeType != "LONG")
    strategy.close("long", when=shortCond == true and tradeType == "LONG")
    strategy.close("short", when=longCond == true and tradeType == "SHORT")
    strategy.exit("XL", from_entry="long", profit=TP, loss=SL)
    strategy.exit("XS", from_entry="short", profit=TP, loss=SL)



// === /STRATEGY ===
// eof


もっと