择时策略
下面以Python语言, 介绍择时策略的写法
双均线策略
实现策略:10日均线上穿30日均线时买入,下穿时卖出。
onTick = g.MA(10) - g.MA(30) # 利用金叉和死叉信号进行交易
show = (g.MA(10), g.MA(30)), # 同时显示10日和30日均线
g
g
是 strategy
的缩写,代表当前策略。
g
绑定了一个strategy的信息:合约名称、周期(分钟、日、周、月等),但不包含任何交易账户信息。
onTick()
的执行结果会被保存在 g
中
每次onTick
后, 系统会自动:g.append(onTick())
所以g
由onTick
的所有返回值组成:
g[-1] | 上一次 onTick 的结果 |
g[-2] | 上上一次 onTick 的结果 |
... | ... |
new
函数
写策略时,除了当前合约的数据, 通常会使用如上证指数据,利率,汇率等宏观数据和指标
通过 g.new()
可以创建一个新的 g
实例,用于绑定其他数据名称和周期。
g1 = g.new(symbol='000300.SH', cycle=86400) # 创建一个新的g实例,绑定沪深300指数,周期为日(86400秒)
show = g1.CLOSE().overlay() # 在第一个窗口叠加显示沪深300的收盘价
Ind
函数
通过 g.Ind()
可以新建一个空指标,用于动态填充数据,增加指标的灵活性和使用范围。示例如下:
c = g.CLOSE()
ma = g.MA()
ind = g.Ind()
def onTick():
ind.append(c[-1] - ma[-1]) # 动态填充数据:收盘价减去均价
show = None, (ind, ind.MA(20)), None # 在第二个窗口显示ind指标及其20日均线,最后一个None表示不画出资金线
还可以创建新的组合指标,例如:
show = None, g.Ind(g.CLOSE() / g.MA(30)) # 在第二个窗口显示新指标:收盘价 / 30日均价
指标
您可以通过以下方法获取各种股票交易指标:
方法 | 描述 |
---|---|
g.OPEN() | 开盘价 |
g.CLOSE() | 收盘价 |
g.HIGH() | 最高价 |
g.LOW() | 最低价 |
g.EMA(N) | N日指数移动平均线 |
g.K() | KDJ指标的K值 |
g.D() | KDJ指标的D值 |
g.OBV() | OBV能量潮指标 |
dif, dem, macd = g.MACD() | 指标MACD(12, 26, 9) |
ma, up, down = g.BOLL() | 指标BOLL(10, 2) |
up, ene, down = g.ENE() | 指标ENE(10, 11, 9) |
g.Ind() | 创建一个新的空指标,您可以使用ind.append(value) 来填充数值 |
g.Ind(expression) | 通过表达式创建新指标,如g.Ind(g.MA(10) + g.MA(20)) 将两个移动平均线相加生成新指标 |
示例
:
ma = g.MA(30) # 获取30日移动平均线指标
def onTick():
print("昨天和今天的数据:", ma[-2], ma[-1]) # 打印昨天和今天的30日移动平均线值
在上述代码中,ma
可以被视为一个数组,它按照时间顺序存储了历史数据。数组索引与时间的关系如下:
用法 | 描述 |
---|---|
ma[-1] | 今天的30日移动平均线值 |
ma[-2] | 昨天的30日移动平均线值 |
ma[-3] | 前天的30日移动平均线值 |
... | 以此类推,更早的历史数据 |
通过这种方式,您可以方便地访问和操作各种股票交易指标的历史数据。
onTick 函数
顾名思义,每一个K线周期都会调用一次此函数。
组合形式
onTick
定义为多个指标的组合
在双均线策略中,我们可以将 onTick
定义为两个移动平均线的差值,如下所示:
onTick = g.MA(40) - g.MA(100)
show = (g.MA(40), g.MA(100)), # 注意,最后面的逗号是必要的, MA40和MA100才会画在第一窗口
在这种定义下,onTick
是内置指标的组合
函数形式
onTick
也可定义为Python函数,实现相同的效果:
ma40 = g.MA(40)
ma100 = g.MA(100)
def onTick():
if ma40[-1] - ma100[-1] > 0:
return 1 # 表示持仓
else:
return -1 # 表示空仓
show = (ma40, ma100), None # 展示两条移动平均线
以上onTick
定义为Python函数,每个K线周期都会被调用一次
返回值
onTick()
函数的返回值用于决定持仓状态,而不是直接用于标记买入或卖出点.
如下:
返回值 | 持仓状态 |
---|---|
> 0 | 持仓(持有头寸) |
< 0 | 空仓(不持有头寸) |
0 | 不动(保持当前状态) |
请注意,这里的返回值是持仓状态(持仓或空仓), 并非买入卖出的动作, 也没有持仓多少。
实际的交易逻辑需要根据这个状态来进一步实现。
dtree决策树
决策树(Decision Tree)
一个完善的决策并不能靠单一指标就能得出的,往往是多个指标和复杂相互交叉关系
把一个大决策分解成多个小决策, 用树的形式串起来形成综合的决策
调用形式如下:
决策1 = MA10 - MA30 # 双均线
决策2 = K < 30 # KDJ之K 小于30
决策3 = dtree(...) # 也可以是另外一棵决策树
onTick = dtree([ # 定义onTick为一棵决策树
决策1,
决策2,
决策3,
...
决策N,
])
- dtree执行顺序
执行顺序依次为: 决策1, 决策2, 决策3 ...
- dtree返回规则
当某一决策N
的值为None
, 则继续执行下一决策, 否则上层dtree返回决策N
的值
决策写法
指标组合
决策N = MA10 - MA30
dtree
决策N = dtree(...)
if-else组合
仿造python if else分支语法, 简写成如下格式:决策N = (决策X, 1, -1, 0, None)
表达的规则如下:
决策N = (X, A, B, C, D)
#相当于以下过程:
if X > 0:
执行A
elif X < 0:
执行B
elif X == 0:
执行C
elif X == None:
执行D
本质是if-else的组合简写
S
dtree中画出标记
如, 以下双均线策略
ma10 = g.MA(10)
ma20 = g.MA(20)
onTick = (ma10 - ma20, 1, -1)
show = (ma10, ma20),
如果希望当ma10 > ma20时, 在ma10上画红色小点. 可这样写
ma10 = g.MA(10)
ma20 = g.MA(20)
#onTick = (ma10 - ma20, 1, -1) # 变成下面一行
onTick = (ma10 - ma20, S(1, ma10, 'ro'), -1) # 1 变成 S(1, ma10, 'ro')
show = (ma10, ma20),
onLast函数
onLast
函数,顾名思义,是在所有数据计算完成后最后调用一次的函数。它返回一个元组,格式为('名称1', 结果1, '名称2', 结果2, ...)。
可以用于在策略面板
页面展示多个合约的计算结果。
这里是一个例子,其中onTick
是每次数据更新时都会执行的函数,用于计算当前收盘价与60日均线金叉入与死叉出。onLast
函数则在所有数据计算完成后被调用,返回一个包含多个交易指标的元组。
代码示例:
# onTick函数计算收盘价与60日均线, 金叉买入, 死叉卖出
onTick=g.CLOSE() - g.MA(60)
def onLast():
ret = g.profit()
return ('资产', ret.total_assets,
'天数', ret.days,
'赢利', ret.last_win,
'次数', ret.trade_cnt,
'回撤', ret.max_loss,
'赔率', ret.odds)
这样的格式不仅更加清晰,也便于后续对数据的处理和分析。
Profit
Profit单词:益利
g.profit()
建立一个模拟帐户, 初始资金1W, 从某个k线开始计算益利情况.
参数如下profit(self, start = 0, cross = True, reverse = False)
start
: 从第几个k线开始计算收益, 即跳过start以前的k线cross
: start时, 有可能已经持仓一段时间, 有可能已经到顶即将下跌. cross=True: 在这种情况下, 跳过这一段持仓,等待下一次空仓之后,再开始计算收益reverse
: 持仓与空仓反转, 可以看反向操作
的效果
返回值:
Profit
对象
示例请参考onLast函数
Profit属性
total_assets | 总资产 |
buy | 最后一次是不是buy或者sell |
idx | 最后一次操作的位置 |
days | 最后一次持仓时间 |
trade_cnt | 交易次数 |
loss_cnt | 亏损次数 |
win_cnt | 益利次数 |
max_loss | 最大回撤 |
max_loss_idx | 最大回撤对应的位置 |
last_win | 最后一次益利 |
odds | 赔率 |
last_buy_idx | 最后一次买入位置 |
last_sell_idx | 最后一次卖出位置 |
win_rate | 胜率 |
position_duration | 持仓时长 |
tax | 交税及手续费统计 |
Profit.into函数
可将Profit以上的属性转换成与onLast匹配的数组, 可显示表前台表格中, 返回如下:
['Total', 总资产,
'Days', 最后一次持仓时间,
'LastWin', 最后一次益利,
'TradeTimes', 总交易次数,
'PosiLong', 持仓时间长度,
'MaxLoss', 最大回撤,
'WinRate', 胜率,
'LossRate', 赔率,
]
Profit.next函数
计算并更新数据. 一般在CTX策略中使用
画图
show变量
show
变量用于指定在多窗口环境中, 各个窗口展示不同的图表。
设定的格式如下:
show = 第一窗口, 第二窗口, 第三窗口, ..., 第N窗口, None
- 最后一个None:
当定义了onTick
函数时,表示策略有买入和卖出的动作。所以会有资金的变化, 默认资金画在最后一个窗口.
如果不需要显示资金窗口,就在show
的最后面添加一个None
当没有onTick
函数, 没有买卖动作, 本来默认就不画资金窗口, 就可以不加最后的None
现在,我们想把不同的图表分别展示在不同的窗口中。 例如:
show = (g.MA(), g.EMA(), g.BOLL()), (g.K(), g.D()), (g.MACD(),)
# 第一窗口将展示:MA, EMA, BOLL
# 第二窗口将展示:K, D
# 第三窗口将展示:MACD
可以根据需求,将不同的指标分配到不同的窗口中。请尝试运行上述代码,以查看多窗口图表的展示效果。
mark函数
mark()
函数用于在图像上添加标记,以便于观察和分析。这些标记可以是图标、文字或事件。
函数格式如下:
mark(self, pat='', msg='', event=None, auto=0, pos=-1)
参数说明:
pat
参数:当
pat
为字符串时,表示在当前位置绘制一个图标。例如,在onTick
内部使用ma40.mark('gv')
会在ma40
指标上绘制一个绿色向下箭头。图标的颜色和形状对应关系如下:颜色 圆点 上箭头 下箭头 红色 ro r^ rv 绿色 go g^ gv 蓝色 bo b^ bv 当
pat
为指标时,表示将某个指标的图标绘制到另一个指标上。例如,ma100.mark(ma40)
表示将ma40
的图标同步到ma100
上。
msg
参数:- 当需要添加文本标记时,可以使用
msg
参数。例如,mark(msg='文字信息')
会在指定位置添加“文字信息”的文本标记。 - 也可以用
=>
把信息分隔为“简短概括“和“详细内容“。例如,ma40.mark(msg='简短概括=>详细内容')
- 当需要添加文本标记时,可以使用
event
参数:event
参数用于在图上标注特定事件。例如,mark(event='利率公告')
会在图上标注“利率公告”的一系列事件。- 支持以下
event
事件:牛熊
:牛熊转折点的重要事件大事件
: A股历史上的大事件利率公告
: 美联储的利率公告老胡炒股日记
: 根据老胡公布的持仓情况,整理的信息。示例 老胡日记
示例:
以下是一个双均线策略中添加mark
的示例:
ma40 = g.MA(40)
ma100 = g.MA(100)
def onTick():
if ma40[-1] - ma100[-1] > 0:
if ma40[-2] < ma100[-2]:
ma40.mark('r^', msg='金叉=>ma40上穿ma100') # 在ma40指标上绘制红色向上箭头
return 1 # 表示持仓
else:
if ma40[-2] > ma100[-2]:
ma40.mark('gv', msg='死叉=>ma40下穿ma100') # 在ma40指标上绘制绿色向下箭头
return -1 # 表示空仓
ma100.mark(ma40) # 将ma40的图标同步到ma100上
show = ma40, ma100, None # 第一窗口显示ma40,第二窗口显示ma100
在这个示例中,mark
函数被用于在图上添加图标和同步图标,以便于观察和分析均线策略的行为。