该策略基于开价和高价的交叉进行交易信号判断。当开价上穿高价时做多,当开价下穿高价时做空。使用移动平均线可平滑价格数据,降低噪音交易。可配置移动平均线类型和参数。还可配置是否启用追踪止损来锁定利润。
根据输入参数决定是否使用替代周期解析度(useRes)。如果使用,则根据stratRes设定周期。
根据输入参数决定是否使用移动平均线(useMA)。如果使用,则根据basisType选择移动平均线类型,basisLen设定周期长度。
获取开价(open)和收盘价(close)的系列数据。如果使用移动平均线,则应用选择的移动平均线类型和参数平滑处理。
比较当前开价x与开价系列openSeries。如果x大于openSeries则趋势状态trendState为多头,否则为空头。
当开价上穿开价移动平均线时产生做多信号longCond,当开价下穿开价移动平均线时产生做空信号shortCond。
根据做多做空信号进入多头或空头仓位。如果启用追踪止损,设置止损点位和偏移距离。
使用开价和高价两个不同系列进行交易信号判断,避免单一数据系列的局限性。
应用移动平均线技术可过滤掉短期市场噪音,锁定主要趋势。
可灵活配置移动平均线类型,调整参数达到最佳效果。
可选择是否使用追踪止损来控制风险,锁定利润。
策略优化空间大,可针对不同品种和市场环境进行参数调整。
单一交易信号来源,信号稀少,容易漏单。
移动平均线存在滞后问题,可能错过短期机会。
追踪止损设置不当可能过早止损或止损幅度太大。
参数设置不当可能导致虚拟交易过于频繁而影响实盘效果。
不同品种和市场环境需要调整参数,优化难度较大。
可通过增加其他指标判断或引入机器学习模型来丰富信号来源。调整移动平均线类型和参数达到最佳平滑效果。谨慎设置止损点位,适当放宽以获取更多利润。进行充分回测优化确保参数可靠。
增加其它技术指标判断,如布林带、KD等,丰富交易信号。
应用机器学习模型处理信号判断。
优化移动平均线参数,找到最佳参数组合。
优化追踪止损参数,平衡止损幅度和利润获取。
添加参数优化功能,自动寻找最优参数。
为不同品种开发专属参数模板。
开发量化回测框架,快速迭代策略。
该策略基于开价和高价的交叉进行交易信号判断,运用移动平均线技术过滤噪音。可灵活配置参数,实现多种效果。具有一定的优势,但也存在一些问题,如少量信号、滞后等。通过引入更多指标组合判断、机器学习等方式进行优化,可形成较强大的交易策略。需要针对不同品种和市场环境进行参数调整优化,来达到最佳效果。
/*backtest
start: 2022-10-17 00:00:00
end: 2023-10-17 00:00:00
period: 1d
basePeriod: 1h
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/
//@version=2
//strategy(title = "Open Close Cross Strategy", shorttitle = "OCC Strategy", overlay = true, pyramiding = 0, default_qty_type = strategy.percent_of_equity, default_qty_value = 10)
// Revision: 1
// Author: @JayRogers
//
// Description:
// - Strategy based around Open-Close Crossovers.
// Setup:
// - I have generally found that setting the strategy resolution to 3-4x that of the chart you are viewing
// tends to yield the best results, regardless of which MA option you may choose (if any)
// - Don't aim for perfection. Just aim to get a reasonably snug fit with the O-C band, with good runs of
// green and red.
// - Option to either use basic open and close series data, or pick your poison with a wide array of MA types.
// - Optional trailing stop for damage mitigation if desired (can be toggled on/off)
// - Positions get taken automagically following a crossover - which is why it's better to set the resolution
// of the script greater than that of your chart, so that the trades get taken sooner rather than later.
// - If you make use of the trailing stops, be sure to take your time tweaking the values. Cutting it too fine
// will cost you profits but keep you safer, while letting them loose could lead to more drawdown than you
// can handle.
// === INPUTS ===
useRes = input(defval = true, title = "Use Alternate Resolution? ( recommended )")
stratRes = input(defval = "120", title = "Set Resolution ( should not be lower than chart )")
useMA = input(defval = true, title = "Use MA? ( otherwise use simple Open/Close data )")
basisType = input(defval = "DEMA", title = "MA Type: SMA, EMA, DEMA, TEMA, WMA, VWMA, SMMA, HullMA, LSMA, ALMA ( case sensitive )")
basisLen = input(defval = 14, title = "MA Period", minval = 1)
offsetSigma = input(defval = 6, title = "Offset for LSMA / Sigma for ALMA", minval = 0)
offsetALMA = input(defval = 0.85, title = "Offset for ALMA", minval = 0, step = 0.01)
useStop = input(defval = true, title = "Use Trailing Stop?")
slPoints = input(defval = 200, title = "Stop Loss Trail Points", minval = 1)
slOffset = input(defval = 400, title = "Stop Loss Trail Offset", minval = 1)
// === /INPUTS ===
// === BASE FUNCTIONS ===
// Returns MA input selection variant, default to SMA if blank or typo.
variant(type, src, len, offSig, offALMA) =>
v1 = sma(src, len) // Simple
v2 = ema(src, len) // Exponential
v3 = 2 * v2 - ema(v2, len) // Double Exponential
v4 = 3 * (v2 - ema(v2, len)) + ema(ema(v2, len), len) // Triple Exponential
v5 = wma(src, len) // Weighted
v6 = vwma(src, len) // Volume Weighted
v7 = na(v5[1]) ? sma(src, len) : (v5[1] * (len - 1) + src) / len // Smoothed
v8 = wma(2 * wma(src, len / 2) - wma(src, len), round(sqrt(len))) // Hull
v9 = linreg(src, len, offSig) // Least Squares
v10 = alma(src, len, offALMA, offSig) // Arnaud Legoux
type=="EMA"?v2 : type=="DEMA"?v3 : type=="TEMA"?v4 : type=="WMA"?v5 : type=="VWMA"?v6 : type=="SMMA"?v7 : type=="HullMA"?v8 : type=="LSMA"?v9 : type=="ALMA"?v10 : v1
// security wrapper for repeat calls
reso(exp, use, res) => use ? request.security(syminfo.tickerid, res, exp) : exp
// === /BASE FUNCTIONS ===
// === SERIES SETUP ===
// open/close
//closeSeries = useMA ? reso(variant(basisType, close, basisLen, offsetSigma, offsetALMA), useRes, stratRes) : reso(close, useRes, stratRes)
openSeries = useMA ? reso(variant(basisType, open, basisLen, offsetSigma, offsetALMA), useRes, stratRes) : reso(open, useRes, stratRes)
x = openSeries[1]
trendState = x > openSeries ? true : x < openSeries ? false : trendState[1]
// === /SERIES ===
// === PLOTTING ===
barcolor(color = x > openSeries ? #006600 : #990000, title = "Bar Colours")
// channel outline
closePlot = plot(x, title = "Close Line", color = #009900, linewidth = 2, style = line, transp = 90)
openPlot = plot(openSeries, title = "Open Line", color = #CC0000, linewidth = 2, style = line, transp = 90)
// channel fill
closePlotU = plot(trendState ? x : na, transp = 100, editable = false)
openPlotU = plot(trendState ? openSeries : na, transp = 100, editable = false)
closePlotD = plot(trendState ? na : x, transp = 100, editable = false)
openPlotD = plot(trendState ? na : openSeries, transp = 100, editable = false)
fill(openPlotU, closePlotU, title = "Up Trend Fill", color = #009900, transp = 40)
fill(openPlotD, closePlotD, title = "Down Trend Fill", color = #CC0000, transp = 40)
// === /PLOTTING ===
// === STRATEGY ===
// conditions
longCond = crossover(openSeries, x)
shortCond = crossunder(openSeries, x)
// entries and base exit
strategy.entry("long", true, when = longCond)
strategy.entry("short", false, when = shortCond)
// if we're using the trailing stop
//if (useStop)
// strategy.exit("XL", from_entry = "long", trail_points = slPoints, trail_offset = slOffset)
// strategy.exit("XS", from_entry = "short", trail_points = slPoints, trail_offset = slOffset)
// not sure needed, but just incase..
//strategy.exit("XL", from_entry = "long", when = shortCond)
//strategy.exit("XS", from_entry = "short", when = longCond)
// === /STRATEGY ===