マルチファクター戦略


作成日: 2023-10-31 15:45:39 最終変更日: 2023-10-31 15:45:39
コピー: 0 クリック数: 709
1
フォロー
1617
フォロワー

マルチファクター戦略

概要

マルチファクター戦略は,震動型戦略,トレンド追跡型戦略,および突破型戦略の3つの異なるタイプの戦略を融合させ,組み合わせで使用することで,より良い戦略効果を得ます.

戦略原則

多要素戦略は,主に以下のような要素に基づいてモデル化されます.

  • 震動戦略の一部は,買入と売却のタイミングを判断するためにランダムな指数を使用する.具体的には,ランダムな指数%Kラインが超売区の上から%Dラインを通過すると買入シグナルが生じ,%Kラインが超売区下から%Dラインを通過すると売りシグナルが生じます.

  • トレンド戦略は,SMA平均線の黄金の交差点を採用してトレンドの方向を判断する部分である.急線が下の側から慢線を横切るときに買い信号を生じ,急線が上の側から下の側から慢線を横切るときに売り信号を生じます.

  • 突破戦略は,価格が指定された周期内の最高価格または最低価格を突破するかどうかを監視する部分である.価格が最高価格を超えると購入し,最低価格を下回ると販売する.

  • ADX指標と組み合わせてトレンドの強さを判断し,トレンドが十分に強ければトレンド取引に参加する.

  • ストップラインとストップフローを設定し,合理的なストップフロー比率を設定する.

多要素戦略は,これらの要素を統合して,主に以下の論理に従います.

  1. ADXが設定値より大きいときは,トレンドが十分に強いと考えられ,トレンド戦略を実行し始める.ADXが値より小さいときは,収束状態にあると考えられ,ショッキング戦略のみを実行する.

  2. トレンドの状況では,SMA速慢線が金交差する時に開仓を購入し,デッドフォークが平仓を行う.

  3. 震動の状況では,ランダムな指標の取引シグナルを実行する.

  4. 突破型戦略は,両方の市場環境で,チャネルを追跡するために適用されます.

  5. 利益の最適化のためのストップ・ローズ・ストップ・フリッジを設定します.

優位分析

多因子戦略の最大の利点は,異なるタイプの戦略を組み合わせることで,両方の市場環境で優れた戦略効果を得ることができるということです.具体的には,主に以下の利点があります.

  1. 傾向に順応し,傾向の状況で高い勝利率を得ることができる.

  2. 金融危機の時に利益を得ることができ, 持株に囚われることはありません.

  3. 利益因子が高いため,ストップ・ストップ・ロスの設定は合理的です.

  4. 投資の流れを考慮して,損失を減らすことができます.

  5. 複数の指標を組み合わせることで,より強力な取引シグナルが作られます.

  6. 参数最適化により優良な参数組み合わせが得られる.

リスク分析

多要素戦略にはいくつかのリスクがあります.

  1. 多因子の組み合わせが不適切である場合,取引信号が混乱する可能性があるため,最適な因子の組み合わせを見つけるために繰り返しテストする必要があります.

  2. 複数のパラメータを最適化する必要があり,最適化が困難で,十分な歴史的データのサポートが必要です.

  3. トレンドが逆転したときに,時間内にポジションをクリアできなければ,大きな損失を招く可能性があります.

  4. ADXは後退しており,トレンド転換点を逃している可能性がある.

  5. 突破取引は容易に騙されやすいので,合理的なストップ・ロスの戦略を設定する必要があります.

このリスクに対して,以下のポイントから最適化できます.

  1. 異なる因子の安定性を歴史データでテストし,安定因子を選択する.

  2. 遺伝的アルゴリズムなどのインテリジェント・オプティマイゼーションの方法により,最適なパラメータを探します.

  3. 合理的なストップラインを設定し,最大撤退を制御する.

  4. 関連指標で判断すると,傾向は逆転している.

  5. 破綻期間のストップ・ローズ戦略を最適化して,過大損失を回避する.

最適化の方向

多要素戦略にはさらに最適化できる余地があります.

  1. より多くの種類の要因をテストして,より良い組み合わせを探します. 変動率,交代量などの他の要因を考慮することができます.

  2. 最適な戦略の重みを見つけるために,機械学習を活用する.

  3. パラメータ最適化は,スマートアルゴリズムを用いて,迅速に最適化を図ることができる.

  4. 異なるポジション保有期間における収益状況をテストすることができる.

  5. 動的にストップラインを調整することを考えることができる.

  6. 交差量急増など,より多くのフィルタリング条件を導入して,信号の質を向上させることができる.

7.ADX指標は,最適化パラメータを考慮するか,より高度なトレンド判断指標に置き換えることができます.

要約する

多因子戦略は,トレンド,揺れ,突破などの複数の取引論理を考慮した統合で,両方の市場環境で優れた効果を得ることができます.単一戦略と比較して,多因子戦略は,より高い安定した収益を得ることができ,優れたエスカレート拡張スペースがあります.しかし,パラメータの最適化の難しさが大きいことに注意する必要があります.最適化プロセスをサポートする十分な歴史的データが必要です.全体的に,多因子戦略は,非常に効果的なアルゴリズム取引方法であり,さらなる研究と最適化の価値があります.

ストラテジーソースコード
/*backtest
start: 2023-09-30 00:00:00
end: 2023-10-30 00:00:00
period: 1h
basePeriod: 15m
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

//@version=4

// strategy("Strategy_1", shorttitle="Strategy1",overlay=true ,pyramiding = 12, initial_capital=25000, currency='EUR', commission_type = strategy.commission.cash_per_order, commission_value = 3, default_qty_type = strategy.percent_of_equity, default_qty_value = 20)
	
// Revision:        1
// Author:          Jonas

// === 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=2017, title="From Year", minval=2010)
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=2010)

    //   > STRATEGY SETTINGS <
bolOS = input(defval = false, type=input.bool, title="Oscillating Strategy")
bolTS = input(defval = true, type=input.bool, title="Trend Strategy")
bolBO = input(defval = false, type=input.bool, title="Breakout Strategy")

strStrategy = input(defval = "Long", type=input.string, title="Trade Strategy",options = ["Long", "Short","Long & Short"])

flStopLoss = input(defval = 2.0, title="Stop Loss %", type=input.float)/100
flTakeProfit = input(defval = 4.0, title="Take Profit %", type=input.float)/100

    //   > SMA <

fastMA = input(defval=8, type=input.integer, title="FastMA length", minval=1, step=1)
slowMA = input(defval=21, type=input.integer, title="SlowMA length", minval=1, step=1)

    //  > ADX <
adx_len = input(defval=10, type=input.integer, title="ADX length", minval=1, step=1)
adx_trend = input(defval=30, type=input.integer, title="ADX Tr", minval=1, step=1)
adx_choppy = adx_trend
adx_limit = adx_trend

    //  > TRENDSCORE <
ts_fromIndex = input(title="From", type=input.integer, minval=1, defval=10)
ts_toIndex = input(title="To", type=input.integer, minval=1, defval=14)
ts_src = input(title="Source", type=input.source, defval=close)

    // > Oscillator <
stoch_length = 14
stoch_OverBought = 75
stoch_OverSold = 25
stoch_smoothK = 3
stoch_smoothD = 3

// === BACK TEST RANGE FUNCTION ===
window_start = timestamp(FromYear, FromMonth, FromDay, 00, 00)  // backtest start window
window_finish = timestamp(ToYear, ToMonth, ToDay, 23, 59)  // backtest finish window
window() =>  // create function "within window of time"
    time >= window_start and time <= window_finish ? true : false

//plot(stop_level_Long, title="TEST",color=color.red, style=plot.style_linebr, linewidth=2)
//plot(take_level_Long, color=color.green, style=plot.style_linebr, linewidth=2)

// === ADX ===
adx_up = change(high)
adx_down = -change(low)
adx_trur = rma(tr, adx_len)
adx_plus = fixnan(100 * rma(adx_up > adx_down and adx_up > 0 ? adx_up : 0, adx_len) / adx_trur)
adx_minus = fixnan(100 * rma(adx_down > adx_up and adx_down > 0 ? adx_down : 0, adx_len) / adx_trur)
adx_sum = adx_plus + adx_minus

ADX = 100 * rma(abs(adx_plus - adx_minus) / (adx_sum == 0 ? 1 : adx_sum), adx_len)

//=== TRENDSCORE ===
trendscore(ts_src, ts_fromIndex, ts_toIndex) =>
	ts_sum = 0.0
	for i = ts_fromIndex to ts_toIndex
        ts_sum := ts_sum + (ts_src >= nz(ts_src[i]) ? 1 : -1)
    ts_sum

intTS = trendscore(ts_src, ts_fromIndex, ts_toIndex)
// Long if  TrendDirection = 1, Short if TrendDirection = -1; Indifferent if TrendDirection = 0
intTrendDirection = (intTS > (ts_toIndex-ts_fromIndex)) ? 1 : (intTS < (ts_fromIndex-ts_toIndex)) ? -1 : 0

    //  > TREND CONDITION <
adx_growing = ADX > highest(ADX[1],3)
intTrend = ((ADX >= adx_limit) and (ADX[1] >= adx_limit) and adx_growing) ? intTrendDirection : 0

// === ATR ===
ATR = sma(tr,10)
ATR_100 = ATR /abs(high - low)


// === STOCHASTICS ===

stoch_k = sma(stoch(close, high, low, stoch_length), stoch_smoothK)
stoch_d = sma(stoch_k, stoch_smoothD)

// === FILTER & CONDITIONS ===
    //  > STOCHASTICS <
bolFilter_OS1 = close[1] > hl2[1]



bolSigOsc_long_1 = (na(stoch_k) or na(stoch_d)) ? false : (crossover(stoch_d,stoch_OverSold) and stoch_k > stoch_d) ? true:false
bolSigOsc_short_1 = (na(stoch_k) or na(stoch_d)) ? false : (crossunder(stoch_d,stoch_OverBought) and stoch_k < stoch_d) ? true:false

bolLongOpenOS = bolSigOsc_long_1 and bolFilter_OS1
bolLongCloseOS = bolSigOsc_short_1

bolShortOpenOS = bolSigOsc_short_1 and bolFilter_OS1
bolShortCloseOS = bolSigOsc_long_1

    //  > TREND <

bolFilter_TS1 = close[1] > hl2[1] and open[1] < hl2[1]
bolFilter_TS2 = sma(close,50)>sma(close,50)[10]
bolFilter_TS3 = close[1] < hl2[1] and open[1] > hl2[1]

bolSigTrendLO1 = sma(close, fastMA) > sma(close, slowMA)
bolSigTrendLO2 = close > sma(close,fastMA)
bolSigTrendLO3 = bolSigTrendLO1 and bolSigTrendLO2

bolSigTrendLC1 = sma(close, fastMA) < sma(close, slowMA)
bolSigTrendLC2 = close < sma(close, fastMA)
bolSigTrendLC3 = bolSigTrendLC1 and bolSigTrendLC2

bolSigTrendSO1 = bolSigTrendLC3
bolSigTrendSC1 = bolSigTrendLO1

bolLongOpenTS = bolSigTrendLO3 and bolFilter_TS1
bolLongCloseTS = bolSigTrendLC3 and bolFilter_TS3

bolShortOpenTS = bolSigTrendSO1 and bolFilter_TS3
bolShortCloseTS = bolLongOpenTS and bolFilter_TS1

plot(sma(close, fastMA), title='FastMA', color=color.green, linewidth=2, style=plot.style_line)  // plot FastMA
plot(sma(close, slowMA), title='SlowMA', color=color.red, linewidth=2, style=plot.style_line)  // plot SlowMA



    //  > BREAKOUT <
flFilter_BS1 = 0.5 * stdev(close,slowMA)[1]
bolFilter_BS2 = volume > sma(volume,slowMA)*1.25

bolSigBreakoutLO1 = close > (highestbars(high,slowMA)[1] + flFilter_BS1)
bolSigBreakoutLC1 = barssince(bolSigBreakoutLO1)==5

bolSigBreakoutSO1 = close < lowestbars(low,slowMA)[1] - flFilter_BS1
bolSigBreakoutSC1 = barssince(bolSigBreakoutSO1)==5


bolLongOpenBO = bolSigBreakoutLO1 and bolFilter_BS2
bolLongCloseBO = bolSigBreakoutLC1

bolShortOpenBO = bolSigBreakoutSO1 and bolFilter_BS2
bolShortCloseBO = bolSigBreakoutSC1

//=== STRATEGIES ENTRIES & EXITS ===
    //  > STOPS & LIMITS <
stop_level_Long = strategy.position_avg_price * (1 - flStopLoss)
take_level_Long = strategy.position_avg_price * (1 + flTakeProfit)
stop_level_Short = strategy.position_avg_price * (1 + flStopLoss)
take_level_Short = strategy.position_avg_price * (1 - flTakeProfit)

    //  > ENTRIES / CLOSES / EXITS <
if window() //only in backtest-window
    if (bolOS == true)
        if (intTrend == 0)
            if(strStrategy == "Long" or strStrategy == "Long & Short")
                strategy.entry("Lng Osc", strategy.long, when=bolLongOpenOS)  // buy long when "within window of time" AND crossover
            if(strStrategy == "Short" or strStrategy == "Long & Short")
                strategy.entry("Short Osc", strategy.short, when=bolShortOpenOS)
        strategy.close("Lng Osc", when=(bolLongCloseOS))
        //strategy.exit("Exit L OS/STD", "Lng Osc", stop = strategy.position_avg_price - 2*stdev(close,10))
        strategy.exit("Exit L OS/%", "Lng Osc", stop=stop_level_Long)
        strategy.close("Short Osc", when=(bolShortCloseOS))
        //strategy.exit("Exit S OS/STD", "Short Osc", stop = strategy.position_avg_price + 2*stdev(strategy.position_avg_price,10))
        strategy.exit("Exit S OS/%", "Short Osc", stop=stop_level_Short)
    if (bolTS == true)
        if (not(intTrend == 0))
            if((strStrategy == "Long") or (strStrategy == "Long & Short"))
                strategy.entry("Lng TD", strategy.long, when=bolLongOpenTS)  // buy long when "within window of time" AND crossover
            if((strStrategy == "Short") or (strStrategy == "Long & Short"))
                strategy.entry("Short TD", strategy.short, when=(bolShortOpenTS and bolTS))  // buy long when "within window of time" AND crossover
        strategy.exit("Exit L TD", "Lng TD", stop=stop_level_Long)
        strategy.close("Lng TD", when=bolLongCloseTS)
        strategy.exit("Exit S TD", "Short TD", stop=stop_level_Short)
        strategy.close("Short TD", when=bolShortCloseTS)
    if (bolBO == true)
        if((strStrategy == "Long") or (strStrategy == "Long & Short"))
            strategy.entry("Lng BO", strategy.long, when=bolLongOpenBO)  // buy long when "within window of time" AND crossover
            strategy.close("Lng BO", when=bolLongCloseBO)
            //strategy.exit("Exit L BO/STD", "Lng BO", stop = strategy.position_avg_price - 2*stdev(strategy.position_avg_price,10))
            strategy.exit("Exit L BO/2.5%", "Lng BO", stop=stop_level_Long)
        if((strStrategy == "Short") or (strStrategy == "Long & Short"))
            strategy.entry("Short BO", strategy.short, when=bolShortOpenBO)  // buy long when "within window of time" AND crossover
            strategy.close("Short BO", when=bolShortCloseBO)
            //strategy.exit("Exit S BO/STD", "Short BO", stop = strategy.position_avg_price - 2*stdev(strategy.position_avg_price,10))
            strategy.exit("Exit S BO/%", "Short BO", stop=stop_level_Short)