欧玛与阿波罗双轨交易策略


创建日期: 2023-11-02 17:09:35 最后修改: 2023-11-02 17:09:35
复制: 3 点击次数: 678
avatar of ChaoZhang ChaoZhang
1
关注
1617
关注者

欧玛与阿波罗双轨交易策略

概述

该策略结合了欧玛指标和阿波罗指标两个主流技术指标,实现了多空双轨交易。其基本思路是在中长线趋势判断为多头时,寻找短线价格回调入场机会建立多头;在中长线趋势判断为空头时,寻找短线价格反弹入场机会建立空头。

策略原理

该策略使用50日、200日两条移动平均线来判断中长线趋势,50日线在200日线之上表明处于多头趋势,反之,为空头趋势。

接着,该策略使用欧玛指标来定位短线价格反转机会。欧玛指标包括%K线和%D线,分别是经过简单移动平均线平滑处理的RSI指标的结果。当%K线从超卖区(高于80)下行突破%D线时,表明价格从超买状态转为反弹下跌,是一个空头选择时机;当%K从超卖区(低于20)上行突破%D线时,表明价格从超卖区反弹上扬,是一个多头选择时机。

此外,为了进一步过滤误报机会,该策略还引入了阿波罗指标。阿波罗指标展现了K线%D值的极值点信息。当%K线形成新的低点时,意味着反弹力度较弱;当形成新的高点时,意味着反弹力度较强。结合欧玛指标的讯号,这可以进一步提升入场的准确性。

具体来说,在多头趋势中,该策略会在欧玛指标显示超卖区下穿形成多头机会时,同时检查新的高点信息,以确认反弹的力度;在空头趋势中,该策略会在欧玛指标显示超买区上穿形成空头机会时,同时检查新的低点信息,以确认反弹力度的弱化。

通过上述流程,该策略充分利用了中长线趋势判断和短线反转指标的优势,构建了一个稳定的多空双轨交易体系。

策略优势

  1. 该策略结合趋势判断和反转指标,兼顾趋势交易和逆势交易的优点,形成稳定的混合交易框架。

  2. 通过双重指标过滤,可以减少误报比例,提高信号的可靠性。

  3. 策略参数较为简单,容易理解和优化,适合用于量化交易。

  4. 策略运行效果稳健,具有较好的胜率和盈亏比特征。

  5. 采用多空双轨方式,可以持续获得交易机会,不会局限在单一方向。

策略风险

  1. 作为反转性质的策略,当趋势发生变化时,可能会产生一系列的连续亏损。

  2. 该策略对交易者情绪控制要求较高,需要承受一定回撤比例。

  3. 部分参数如移动平均线周期等存在一定主观性,需要通过回测优化确定合适参数。

  4. 欧玛指标和阿波罗指标均对异常波动具有一定敏感性,极端行情下可能出现失效。

  5. 该策略更适合动荡盘整的市场环境,在趋势明显的行情中效果可能会打折扣。

可以通过适当调整移动平均线周期引入趋势过滤,以及加入止损止盈策略来规避风险。当市场进入明显趋势时,可以考虑暂停策略,避开该环境交易。

策略优化方向

  1. 测试不同的参数组合,以得到更佳的参数设置。例如可以尝试采用EWMA平滑移动平均等指标。

  2. 增加Volume或BV等指标来判断背离,可以进一步验证信号可靠性。

  3. 加入VIX等恐慌指数作为监控指标,在市场恐慌时降低仓位。

  4. 优化止损止盈策略,例如可采用ATR止损等动态止损方式。

  5. 引入机器学习算法来动态优化参数设置。

  6. 加入多因子模型来提升信号质量。

总结

该策略总体来说是一个稳定高效的量化交易策略。它结合趋势判断和反转指标,采用欧玛指标和阿波罗指标的双重验证方式,能够有效发掘短线价格反转机会。相比单一使用趋势系统或反转系统,该策略形式更为稳健,回撤控制也更优异,是一个值得推荐的量化交易策略。当然,用户也需要注意防范其中存在的风险点,通过参数优化、止损止盈、环境识别等方式来控制风险,使策略达到最佳效果。

策略源码
/*backtest
start: 2023-10-25 00:00:00
end: 2023-10-28 00:00:00
period: 5m
basePeriod: 1m
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © PtGambler

//@version=5
strategy("2 EMA + Stoch RSI + ATR [Pt]", shorttitle = "2EMA+Stoch+ATR", overlay=true, initial_capital = 10000, default_qty_type = strategy.percent_of_equity, default_qty_value = 100, calc_on_order_fills = false, max_bars_back = 500)

// ********************************** Trade Period / Strategy Setting **************************************
startY = input(title='Start Year', defval=2011, group = "Backtesting window")
startM = input.int(title='Start Month', defval=1, minval=1, maxval=12, group = "Backtesting window")
startD = input.int(title='Start Day', defval=1, minval=1, maxval=31, group = "Backtesting window")
finishY = input(title='Finish Year', defval=2050, group = "Backtesting window")
finishM = input.int(title='Finish Month', defval=12, minval=1, maxval=12, group = "Backtesting window")
finishD = input.int(title='Finish Day', defval=31, minval=1, maxval=31, group = "Backtesting window")
timestart = timestamp(startY, startM, startD, 00, 00)
timefinish = timestamp(finishY, finishM, finishD, 23, 59)

// ******************************************************************************************

group_ema = "EMA"
group_stoch = "Stochastic RSI"
group_atr = "ATR Stoploss Finder"

// ----------------------------------------- 2 EMA -------------------------------------

ema1_len = input.int(50, "EMA Length 1", group = group_ema)
ema2_len = input.int(200, "EMA Length 2", group = group_ema)

ema1 = ta.ema(close, ema1_len)
ema2 = ta.ema(close, ema2_len)

plot(ema1, "ema1", color.white, linewidth = 2)
plot(ema2, "ema2", color.orange, linewidth = 2)

ema_bull = ema1 > ema2
ema_bear = ema1 < ema2


// -------------------------------------- Stochastic RSI -----------------------------

smoothK = input.int(3, "K", minval=1, group = group_stoch)
smoothD = input.int(3, "D", minval=1, group = group_stoch)
lengthRSI = input.int(14, "RSI Length", minval=1, group = group_stoch)
lengthStoch = input.int(14, "Stochastic Length", minval=1, group = group_stoch)
src = close
rsi1 = ta.rsi(src, lengthRSI)
k = ta.sma(ta.stoch(rsi1, rsi1, rsi1, lengthStoch), smoothK)
d = ta.sma(k, smoothD)

var trigger_stoch_OB = k > 80
var trigger_stoch_OS = k < 20

stoch_crossdown = ta.crossunder(k, d)
stoch_crossup = ta.crossover(k, d)

P_hi = ta.pivothigh(k,1,1)
P_lo = ta.pivotlow(k,1,1)

previous_high = ta.valuewhen(P_hi, k, 1)
previous_low = ta.valuewhen(P_lo, k, 1)
recent_high = ta.valuewhen(P_hi, k, 0)
recent_low = ta.valuewhen(P_lo, k, 0)

// --------------------------------------- ATR stop loss finder ------------------------

length = input.int(title='Length', defval=14, minval=1, group = group_atr)
smoothing = input.string(title='Smoothing', defval='EMA', options=['RMA', 'SMA', 'EMA', 'WMA'], group = group_atr)
m = input.float(0.7, 'Multiplier', step = 0.1, group = group_atr)
src1 = input(high, "Source for upper band", group = group_atr)
src2 = input(low, "Source for lower band", group = group_atr)

showatr = input.bool(true, 'Show ATR Bands', group = group_atr)
collong = input.color(color.purple, 'Long ATR SL', inline='1', group = group_atr)
colshort = input.color(color.purple, 'Short ATR SL', inline='2', group = group_atr)

ma_function(source, length) =>
    if smoothing == 'RMA'
        ta.rma(source, length)
    else
        if smoothing == 'SMA'
            ta.sma(source, length)
        else
            if smoothing == 'EMA'
                ta.ema(source, length)
            else
                ta.wma(source, length)

a = ma_function(ta.tr(true), length) * m
up = ma_function(ta.tr(true), length) * m + src1
down = src2 - ma_function(ta.tr(true), length) * m

p1 = plot(showatr ? up : na, title='ATR Short Stop Loss', color=colshort)
p2 = plot(showatr ? down : na, title='ATR Long Stop Loss', color=collong)

// ******************************* Profit Target / Stop Loss *********************************************

RR = input.float(2.0, "Reward to Risk ratio (X times SL)", step = 0.1, group = "Profit Target")

var L_PT = 0.0
var S_PT = 0.0
var L_SL = 0.0
var S_SL = 0.0

BSLE = ta.barssince(strategy.opentrades.entry_bar_index(0) == bar_index)

if strategy.position_size > 0 and BSLE == 1
    L_PT := close + (close-down)*RR
    L_SL := L_SL[1]
    S_PT := close - (up - close)*RR
    S_SL := up
else if strategy.position_size < 0 and BSLE == 1
    S_PT := close - (up - close)*RR
    S_SL := S_SL[1]
    L_PT := close + (close-down)*RR
    L_SL := down
else if strategy.position_size != 0
    L_PT := L_PT[1] 
    S_PT := S_PT[1]
else
    L_PT := close + (close-down)*RR
    L_SL := down
    S_PT := close - (up - close)*RR
    S_SL := up

entry_line = plot(strategy.position_size != 0 ? strategy.opentrades.entry_price(0) : na, "Entry Price", color.white, linewidth = 1, style = plot.style_linebr)

L_PT_line = plot(strategy.position_size > 0 and BSLE > 0 ? L_PT : na, "L PT", color.green, linewidth = 2, style = plot.style_linebr)
S_PT_line = plot(strategy.position_size < 0 and BSLE > 0 ? S_PT : na, "S PT", color.green, linewidth = 2, style = plot.style_linebr)

L_SL_line = plot(strategy.position_size > 0 and BSLE > 0 ? L_SL : na, "L SL", color.red, linewidth = 2, style = plot.style_linebr)
S_SL_line = plot(strategy.position_size < 0 and BSLE > 0 ? S_SL : na, "S SL", color.red, linewidth = 2, style = plot.style_linebr)

fill(L_PT_line, entry_line, color = color.new(color.green,90))
fill(S_PT_line, entry_line, color = color.new(color.green,90))
fill(L_SL_line, entry_line, color = color.new(color.red,90))
fill(S_SL_line, entry_line, color = color.new(color.red,90))


// ---------------------------------- strategy setup ------------------------------------------------------

var L_entry_trigger1 = false
var S_entry_trigger1 = false

L_entry_trigger1 := ema_bull and close < ema1 and k < 20 and strategy.position_size == 0
S_entry_trigger1 := ema_bear and close > ema1 and k > 80 and strategy.position_size == 0

L_entry1 = L_entry_trigger1[1] and stoch_crossup and recent_low > previous_low
S_entry1 = S_entry_trigger1[1] and stoch_crossdown and recent_high < previous_high

//debugging
plot(L_entry_trigger1[1]?1:0, "L Entry Trigger")
plot(stoch_crossup?1:0, "Stoch Cross Up")
plot(recent_low > previous_low?1:0, "Higher low")

plot(S_entry_trigger1[1]?1:0, "S Entry Trigger")
plot(stoch_crossdown?1:0, "Stoch Cross down")
plot(recent_high < previous_high?1:0, "Lower high")

if L_entry1
    strategy.entry("Long", strategy.long)

if S_entry1
    strategy.entry("Short", strategy.short)

strategy.exit("Exit Long", "Long", limit = L_PT, stop = L_SL, comment_profit = "Exit Long, PT hit", comment_loss = "Exit Long, SL hit")
strategy.exit("Exit Short", "Short", limit = S_PT, stop = S_SL, comment_profit = "Exit Short, PT hit", comment_loss = "Exit Short, SL hit")

//resetting triggers
L_entry_trigger1 := L_entry_trigger1[1] ? L_entry1 or ema_bear or S_entry1 ? false : true : L_entry_trigger1
S_entry_trigger1 := S_entry_trigger1[1] ? S_entry1 or ema_bull or L_entry1 ? false : true : S_entry_trigger1

//Trigger zones
bgcolor(L_entry_trigger1 ? color.new(color.green ,90) : na)
bgcolor(S_entry_trigger1 ? color.new(color.red,90) : na)