本策略基于BTC的50日移动平均线和200日移动平均线的金叉死叉信号,结合额外的技术指标判断来发出买入和卖出信号。该策略主要适用于BTC/USDT这种具有明显趋势性特征的币对。
当50日移动平均线上方突破200日移动平均线而形成“金叉”时,表示BTC进入多头市场,产生买入信号。而当50日移动平均向下突破200日移动平均线而形成“死叉”时,表示BTC进入空头市场,产生卖出信号。
该策略除了基本的移动平均线“金叉”和“死叉”信号判断以外,还加入了一些额外的技术指标来辅助判断,这些指标包括:
EMA指标:计算一个 length+offset 的 EMA 指标,当其上涨时表明目前处于多头市场,可以买入。
比较移动平均线与EMA的数值关系:如果EMA值高于50日移动平均线,则产生买入判断。
检查价格比上一根K线的低点下跌1%以上,如果满足则产生卖出信号。
通过组合运用上述几个指标,可以过滤掉一些错误信号,使策略交易决策更加可靠。
该策略具有以下几个优势:
使用移动平均线作为主要交易信号,可过滤市场噪音,识别趋势方向。
结合EMA等多种辅助技术指标,可以增强信号的可靠性,过滤假信号。
采用适当的止损策略,可以有效控制单笔损失。
较为简单的交易逻辑,容易理解实现,适合量化交易初学者。
可配置参数较多,可以按照自己的偏好进行调整。
该策略也存在一些风险需要注意:
移动平均线本身滞后性较强,可能错过价格快速反转的机会。
辅助指标增加了规则数量,也提高了产生错误信号的概率。
止损设置不当可能导致亏损扩大。
参数设置(如移动平均线长度等)不当也会影响策略效果。
对应解决方法:
适当缩短移动平均线周期,增大参数优化范围。
增加回测数据量,检查信号质量。
适当放宽止损幅度,同时设置盈利止盈。
增加参数优化,寻找最佳参数组合。
该策略还可从以下几个方向进行优化:
增加机器学习算法,实现参数的自动优化。
加入更多辅助指标,构建多个子策略,通过投票机制产生决策。
尝试 Breakout 策略,识别价格突破。
利用深度学习预测价格趋势。
优化止损机制,实现动态跟踪止损。
以上优化可以提高决策的准确性,增强策略的盈利能力和稳定性。
本策略主要基于BTC的移动平均线交叉进行交易决策,辅以EMA等技术指标来过滤信号。该策略具有较强的趋势跟踪能力,可配置性也较高,适合作为量化交易的入门策略。但也存在一定的滞后性风险,需要注意防范。接下来的优化方向可以从机器学习、集成策略、止损策略等多个层面进行。
/*backtest
start: 2023-11-06 00:00:00
end: 2023-12-06 00:00:00
period: 1d
basePeriod: 1h
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/
//@version=5
strategy('JayJay BTC Signal', overlay=true, initial_capital=100, currency='USD', default_qty_value=100, default_qty_type=strategy.percent_of_equity, commission_value=0, calc_on_every_tick=true)
securityNoRepaint(sym, tf, src) => request.security(sym, tf, src[barstate.isrealtime ? 1 : 0])[barstate.isrealtime ? 0 : 1]
//200 50 Moving Average
ma50Len = input.int(50, minval=1, title='MA50-Length')
ma50Src = input(close, title='MA50-Source')
ma50Show = input(true, title='Show SMA50 on chart')
ma50Close = ta.sma(ma50Src, ma50Len)
ma50CloseTimeframe = input.timeframe("240", "Ma50 Timeframe", group = "EMA Options")
ma50Open = ta.sma(open, ma50Len)
ma200Len = input.int(200, minval=1, title='MA200-Length')
ma200Src = input(close, title='MA200-Source')
ma200Show = input(true, title='Show SMA200 on chart')
ma200CloseTimeframe = input.timeframe("D", "Ma200 Timeframe", group = "EMA Options")
ma200Close = ta.sma(ma200Src, ma200Len)
ma200Open = ta.sma(open, ma200Len)
//plot(ma200Close, color=color.new(#0b6ce5, 0), title='MA200')
//plot(ma50Close, color=color.new(#00d8ff, 0), title='MA50')
sma50 = securityNoRepaint(syminfo.tickerid, ma50CloseTimeframe, ma50Close)
plot(sma50 and ma50Show ? sma50 : na, color=color.new(#00d8ff, 0), title='SMA50')
sma200 = securityNoRepaint(syminfo.tickerid, ma200CloseTimeframe, ma200Close)
plot(sma200 and ma200Show ? sma200 : na, color=color.new(#00d8ff, 0), title='SMA200')
// Short/Long EMA
// Define the offset value
EMAOffsetValue = input.int(2, title='EMA Offset', minval=0)
emaplot = input(true, title='Show EMA on chart')
len = input.int(20, minval=1, title='ema Length') + EMAOffsetValue
emaCloseTimeframe = input.timeframe("240", "EMA 1 Timeframe", group = "EMA Options")
emaOpen = ta.ema(open, len)
emaClose = ta.ema(close, len)
ema = securityNoRepaint(syminfo.tickerid, emaCloseTimeframe, emaClose)
up = emaClose > ema[1]
down = emaClose < ema[1]
mycolor = up ? color.green : down ? color.red : color.blue
plot(ema and emaplot ? ema : na, title='Signal EMA', color=mycolor, linewidth=3)
//plot(emaClose and emaplot ? emaClose : na, title='Signal 20 EMA', color=color.yellow, linewidth=3)
ma50GreaterThanMa200 = sma50 > sma200
last3BarUp = ema > ema[1]
startLong = up and ema > sma50 and ma50GreaterThanMa200 and (100 - (sma50 / ema * 100) > 1.0)
startFrom = input(timestamp("20 Jan 2000 00:00"), "StartFrom")
yearFilter = true
alertLongPositionMessage = "{\"direction:\": \"long\", \"action\": \"{{strategy.order.action}}\", \"price\": \"{{strategy.order.price}}\", \"qty\": \"{{strategy.position_size}}\", \"symbol\": \"{{ticker}}\", \"date\": \"{{time}}\"}"
if true and startLong and yearFilter
strategy.entry('Long', strategy.long, comment = "Long", alert_message = alertLongPositionMessage)
longStopLossLevel = open * 0.05
strategy.exit('StopLoss', from_entry='Long',comment = "StopLoss!", loss=longStopLossLevel, profit=close * 0.3, alert_message = alertLongPositionMessage)
longPercentageChange = low / close[1] * 100 - 100
is1PercentLower = longPercentageChange < -0.1
closeLongPositionWhen = (down and is1PercentLower) or (emaClose < sma50)
if closeLongPositionWhen
strategy.close('Long', comment = "Fuck It!", alert_message = alertLongPositionMessage)
bgcolor(startLong ? color.green : na, transp=90)