Многофакторная стратегия

Автор:Чао Чжан, Дата: 2023-10-31 15:45:39
Тэги:

img

Обзор

Многофакторная стратегия объединяет в одну стратегию колебания, следования тренду и выхода, объединяя их сильные стороны.

Логика стратегии

Многофакторная стратегия в основном основана на следующих аспектах:

  • Оциллирующая часть использует стохастический осциллятор для идентификации сигналов покупки и продажи. В частности, сигнал покупки генерируется, когда линия %K пересекает линию %D из зоны перепродажи. Сигнал продажи генерируется, когда линия %K пересекает линию %D из зоны перекупки.

  • В следующей части тренда используется золотой крест SMA для определения направления тренда. Сигнал покупки генерируется, когда быстрая SMA пересекает медленную SMA. Сигнал продажи генерируется, когда быстрая SMA пересекает медленную 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)




Больше