多要素戦略は,振動,トレンドフォロー,ブレイクアウト戦略を1つに統合し,その強みを組み合わせます. これにより,異なる市場条件でより良いパフォーマンスを得ることができます.
多要素戦略は主に以下の側面に基づいてモデル化されています.
振動部分は,ストカスティック振動器を使用して購入・販売信号を識別する.特に,%K線が過売りゾーンから%D線を横切るときに購入信号が生成される.%K線が過買いゾーンから%D線を下に横切るときに販売信号が生成される.
トレンドフォローする部分は,SMAの黄色の十字を使ってトレンド方向を決定する.速いSMAが遅いSMAを横切ったときに購入信号が生成される.速いSMAが遅いSMAを下回ったときに販売信号が生成される.
ブレイクパートは,価格が指定された期間で最高価格を突破するか,最低価格を下回るかどうかを監視します.価格が最高価格を突破したとき,購入を誘発し,価格が最低価格を下回ると販売を誘発します.
ADX指標は,トレンド強さを測定するために使用されます.トレンドトレード信号は,トレンドが十分に強いときにのみ生成されます.
ストップ・ロストとテイク・プロフィートラインは,収益性を最適化するために実装されています.
概要すると,多要素戦略は以下の論理に従います.
ADXが限界値を超えると,トレンドは強いと考えられる.トレンドをフォローする戦略が有効である.ADXが限界値を下回ると,市場は変動している.振動戦略のみが有効である.
トレンド市場では,SMAの黄金十字はロングエントリーを誘発し,デスクロスはアウトポジションを誘発します.
レンジング市場ではストカスティックオシレーターからの取引信号に従います
突破戦略は 強い動向を追求するために 両方の市場条件に適用されます.
ストップ・ロストとテイク・プロフィートラインは 利益を固定し 損失を制限するために設定されています
多要素戦略の最大の利点は,異なる戦略の強みを組み合わせ,トレンドと範囲の両方の市場で良いパフォーマンスを達成することです.主な利点は以下の通りです.
トレンドをうまく走らせ トレンド市場で高勝率を達成します
範囲限定の市場から利益を得ることができ ポジションに閉じ込められないのです
利得率は高く ストップ・ロスは正しく設定され 利益は取れます
誤った信号による損失を減らすために 傾向強さを考慮します
複数の指標の組み合わせにより 強力な取引信号が生まれます
パラメータを最適化して 性能を向上させることができます
多要素戦略にはリスクもあります
不適切な要素の組み合わせは,相互矛盾する取引信号を引き起こす可能性があります.最適な組み合わせを見つけるには,広範なテストが必要です.
複数のパラメータにより最適化の難易性が高まり,十分な歴史的データが必要です.
トレンドが逆転するときに ポジションを間に合って退場できず 損失が大きい場合もあります
ADX指標は遅延効果があり,トレンドターニングポイントを見逃す可能性があります.
ブレイクトレードでは,負けるポジションに閉じ込められる傾向があります.合理的なストップロスは必要です.
リスクは以下の方法で軽減できます.
バックテスト 安定した要素を選びます
最適なパラメータを見つけるために ヒューリスティック最適化アルゴリズムを使用します
ストップ・ロスを正しく設定して 最大引き下げを制御する
傾向の逆転を検出するための追加指標を組み込む.
ストップ・ロスのルールを最適化
多要素戦略の改善にはまだ余地があります.
より良い組み合わせを見つけるために 変動やボリュームなどの多くの要因をテストします
マシン学習技術を使って 動的に因子重量を最適化します
パラメータの高速最適化のための ヒューリスティックアルゴリズムを活用する
不同保有期間における収益性のテスト
ダイナミックなストップ・ロスのルールを探求します 例えば,利益を得た後にストップ・ロスを拡大します
信号の質を向上させるため 音量ピークなどのフィルターを追加します
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)