"仓鼠机器人"是一个用于加密货币或其他金融市场的自动化交易策略。下面是包含在仓鼠机器人策略中的一些常见元素:
趋势识别:仓鼠机器人可能会使用各种技术指标或模型来识别市场趋势。这可能包括移动平均线、相对强弱指标(RSI)、布林带等。
波动性管理:策略可能包括对市场波动性的管理,以调整交易大小或风险水平。这有助于在市场波动性较大时采取谨慎的交易策略。
均衡:仓鼠机器人可能会尝试保持一定的投资组合均衡,以确保风险分散。这可能包括定期的资产重新配置或重新平衡。
交易规则:该策略可能会定义各种交易规则,包括何时开仓、何时平仓、止损和止盈等。这些规则可能基于技术指标、价格模型或其他因素。
自动执行:仓鼠机器人是一个自动化交易系统,因此它可能使用计算机程序来执行交易。这可能包括通过API接口与交易所直接交互。
风险管理:策略可能包括严格的风险管理措施,以确保在市场波动时最小化损失。这可能包括动态止损、仓位大小控制等。
数据分析:仓鼠机器人可能会利用历史数据进行分析,以改进其交易算法。这可能包括回测和优化。
本文介绍的策略就是来源于加密货币领域的。经过一些简单的改造,就可以适用于商品期货领域。该策略非常简单,具有很少的设置。非常适合我们初学者了解算法交易。简单的调整可以帮助避免过度拟合。有许多这种策略的变体,但为了理解,最好从这个实现开始。
总体来说,这是一个基于移动平均线(MA)的交易策略,具体包括以下几个方面:
MA Opening(移动平均线开仓): 定义了两组移动平均线,一组用于开多仓(long),另一组用于开空仓(short)。用户可以选择不同类型的移动平均线(SMA、EMA、TEMA 等)、数据源(OHLC4,即开盘价、最高价、最低价和收盘价的平均值)、长度和其他参数。
MA Closing(移动平均线平仓): 定义了用于平仓的移动平均线。同样,用户可以选择不同类型的移动平均线以及其他参数。
Kalman Filter(卡尔曼滤波器): 用户可以选择是否使用卡尔曼滤波器来平滑移动平均线。
偏移和交易条件设置: 用户可以设置偏移值,调整图表上的显示位置。可以选择在收盘价时开仓(on_close)。设置交易偏移量(trade_offset),可能用于在一定条件下延迟交易执行。
Entry(开仓): 根据计算得到的移动平均线值,制定了开多仓和开空仓的条件。
Plot(绘图): 在图表上绘制了移动平均线开仓和平仓的信号线,以及相应的颜色标识。
这个策略的核心思想是通过移动平均线的金叉和死叉信号进行交易决策,即在趋势变强时开仓,趋势减弱时平仓。用户可以通过选择不同类型和参数的移动平均线来适应不同的市场条件。
下面我们来看下代码:
//@version=5
strategy(title = "hamster-bot MRS 2", overlay = true)
info_options = "Options"
on_close = input(false, title = "Entry on close", inline=info_options, group=info_options)
OFFS = input.int(0, minval = 0, maxval = 1, title = "| Offset View", inline=info_options, group=info_options)
trade_offset = input.int(0, minval = 0, maxval = 1, title = "Trade", inline=info_options, group=info_options)
use_kalman_filter = input.bool(false, title="Use Kalman filter", group=info_options)
//MA Opening
info_opening = "MA Opening Long"
maopeningtyp_l = input.string("SMA", title="Type", options=["SMA", "EMA", "TEMA", "DEMA", "ZLEMA", "WMA", "Hma", "Thma", "Ehma", "H", "L", "DMA"], title = "", inline=info_opening, group=info_opening)
maopeningsrc_l = input.source(ohlc4, title = "", inline=info_opening, group=info_opening)
maopeninglen_l = input.int(3, minval = 1, title = "", inline=info_opening, group=info_opening)
long1on = input(true, title = "", inline = "long1")
long1shift = input.float(0.96, step = 0.005, title = "Long", inline = "long1")
long1lot = input.int(10, minval = 0, maxval = 10000, step = 10, title = "Lot 1", inline = "long1")
info_opening_s = "MA Opening Short"
maopeningtyp_s = input.string("SMA", title="Type", options=["SMA", "EMA", "TEMA", "DEMA", "ZLEMA", "WMA", "Hma", "Thma", "Ehma", "H", "L", "DMA"], title = "", inline=info_opening_s, group=info_opening_s)
maopeningsrc_s = input.source(ohlc4, title = "", inline=info_opening_s, group=info_opening_s)
maopeninglen_s = input.int(3, minval = 1, title = "", inline=info_opening_s, group=info_opening_s)
short1on = input(true, title = "", inline = "short1")
short1shift = input.float(1.04, step = 0.005, title = "short", inline = "short1")
short1lot = input.int(10, minval = 0, maxval = 10000, step = 10, title = "Lot 1", inline = "short1")
//MA Closing
info_closing = "MA Closing"
maclosingtyp = input.string("SMA", title="Type", options=["SMA", "EMA", "TEMA", "DEMA", "ZLEMA", "WMA", "Hma", "Thma", "Ehma", "H", "L", "DMA"], title = "", inline=info_closing, group=info_closing)
maclosingsrc = input.source(ohlc4, title = "", inline=info_closing, group=info_closing)
maclosinglen = input.int(3, minval = 1, maxval = 200, title = "", inline=info_closing, group=info_closing)
maclosingmul = input.float(1, step = 0.005, title = "mul", inline=info_closing, group=info_closing)
HMA(_src, _length) => ta.wma(2 * ta.wma(_src, _length / 2) - ta.wma(_src, _length), math.round(math.sqrt(_length)))
EHMA(_src, _length) => ta.ema(2 * ta.ema(_src, _length / 2) - ta.ema(_src, _length), math.round(math.sqrt(_length)))
THMA(_src, _length) => ta.wma(ta.wma(_src,_length / 3) * 3 - ta.wma(_src, _length / 2) - ta.wma(_src, _length), _length)
tema(sec, length)=>
tema1= ta.ema(sec, length)
tema2= ta.ema(tema1, length)
tema3= ta.ema(tema2, length)
tema_r = 3*tema1-3*tema2+tema3
donchian(len) => math.avg(ta.lowest(len), ta.highest(len))
ATR_func(_src, _len)=>
atrLow = low - ta.atr(_len)
trailAtrLow = atrLow
trailAtrLow := na(trailAtrLow[1]) ? trailAtrLow : atrLow >= trailAtrLow[1] ? atrLow : trailAtrLow[1]
supportHit = _src <= trailAtrLow
trailAtrLow := supportHit ? atrLow : trailAtrLow
trailAtrLow
f_dema(src, len)=>
EMA1 = ta.ema(src, len)
EMA2 = ta.ema(EMA1, len)
DEMA = (2*EMA1)-EMA2
f_zlema(src, period) =>
lag = math.round((period - 1) / 2)
ema_data = src + (src - src[lag])
zl= ta.ema(ema_data, period)
f_kalman_filter(src) =>
float value1= na
float value2 = na
value1 := 0.2 * (src - src[1]) + 0.8 * nz(value1[1])
value2 := 0.1 * (ta.tr) + 0.8 * nz(value2[1])
lambda = math.abs(value1 / value2)
alpha = (-math.pow(lambda, 2) + math.sqrt(math.pow(lambda, 4) + 16 * math.pow(lambda, 2)))/8
value3 = float(na)
value3 := alpha * src + (1 - alpha) * nz(value3[1])
//SWITCH
ma_func(modeSwitch, src, len, use_k_f=true) =>
modeSwitch == "SMA" ? use_kalman_filter and use_k_f ? f_kalman_filter(ta.sma(src, len)) : ta.sma(src, len) :
modeSwitch == "RMA" ? use_kalman_filter and use_k_f ? f_kalman_filter(ta.rma(src, len)) : ta.rma(src, len) :
modeSwitch == "EMA" ? use_kalman_filter and use_k_f ? f_kalman_filter(ta.ema(src, len)) : ta.ema(src, len) :
modeSwitch == "TEMA" ? use_kalman_filter and use_k_f ? f_kalman_filter(tema(src, len)) : tema(src, len):
modeSwitch == "DEMA" ? use_kalman_filter and use_k_f ? f_kalman_filter(f_dema(src, len)) : f_dema(src, len):
modeSwitch == "ZLEMA" ? use_kalman_filter and use_k_f ? f_kalman_filter(f_zlema(src, len)) : f_zlema(src, len):
modeSwitch == "WMA" ? use_kalman_filter and use_k_f ? f_kalman_filter(ta.wma(src, len)) : ta.wma(src, len):
modeSwitch == "VWMA" ? use_kalman_filter and use_k_f ? f_kalman_filter(ta.vwma(src, len)) : ta.vwma(src, len):
modeSwitch == "Hma" ? use_kalman_filter and use_k_f ? f_kalman_filter(HMA(src, len)) : HMA(src, len):
modeSwitch == "Ehma" ? use_kalman_filter and use_k_f ? f_kalman_filter(EHMA(src, len)) : EHMA(src, len):
modeSwitch == "Thma" ? use_kalman_filter and use_k_f ? f_kalman_filter(THMA(src, len/2)) : THMA(src, len/2):
modeSwitch == "ATR" ? use_kalman_filter and use_k_f ? f_kalman_filter(ATR_func(src, len)): ATR_func(src, len) :
modeSwitch == "L" ? use_kalman_filter and use_k_f ? f_kalman_filter(ta.lowest(len)): ta.lowest(len) :
modeSwitch == "H" ? use_kalman_filter and use_k_f ? f_kalman_filter(ta.highest(len)): ta.highest(len) :
modeSwitch == "DMA" ? donchian(len) : na
//Var
sum = 5.0
maopening_l = 0.0
maopening_s = 0.0
maclosing = 0.0
loss = 0.0
maxloss = 0.0
//MA Opening
maopening_l := ma_func(maopeningtyp_l, maopeningsrc_l, maopeninglen_l)
maopening_s := ma_func(maopeningtyp_s, maopeningsrc_s, maopeninglen_s)
//MA Closing
maclosing := ma_func(maclosingtyp, maclosingsrc, maclosinglen) * maclosingmul
long1 = long1on == false ? 0 : long1shift == 0 ? 0 : long1lot == 0 ? 0 : maopening_l == 0 ? 0 : maopening_l * long1shift
short1 = short1on == false ? 0 : short1shift == 0 ? 0 : short1lot == 0 ? 0 : maopening_s == 0 ? 0 : maopening_s * short1shift
//Colors
long1col = long1 == 0 ? na : color.green
short1col = short1 == 0 ? na : color.red
//Lines
plot(maclosing, offset = OFFS, color = color.fuchsia)
long1line = long1 == 0 ? close : long1
short1line = short1 == 0 ? close : short1
plot(long1line, offset = OFFS, color = long1col)
plot(short1line, offset = OFFS, color = short1col)
//Entry
//Long
strategy.entry("L", strategy.long, 1, limit = on_close ? na : long1, when = long1 > 0 and (on_close ? close <= long1[trade_offset] : true))
//Short
strategy.entry("S", strategy.short, 1, limit = on_close ? na : short1, when = short1 > 0 and (on_close ? close >= short1[trade_offset] : true))
strategy.exit("Exit", na, limit = maclosing)
这里为了风险的控制,我们将开平仓的手数都定义为1手,使用玻璃期货在2022年11月到23年11月份看下效果。
可以看到,一共取得了8700多元的收益,大家可以根据自己喜欢的品种尝试一下。