择时策略

下面以Python语言, 介绍择时策略的写法

双均线策略

实现策略:10日均线上穿30日均线时买入,下穿时卖出。

onTick = g.MA(10) - g.MA(30)  # 利用金叉和死叉信号进行交易
show = (g.MA(10), g.MA(30)),  # 同时显示10日和30日均线

g

gstrategy 的缩写,代表当前策略。

g 绑定了一个strategy的信息:合约名称、周期(分钟、日、周、月等),但不包含任何交易账户信息。

onTick() 的执行结果会被保存在 g
每次onTick后, 系统会自动:g.append(onTick())

所以gonTick的所有返回值组成:

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指标上绘制一个绿色向下箭头。图标的颜色和形状对应关系如下:

      颜色圆点上箭头下箭头
      红色ror^rv
      绿色gog^gv
      蓝色bob^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函数被用于在图上添加图标和同步图标,以便于观察和分析均线策略的行为。