Python đơn giản hóa nhiều loại MACD framework (định hướng)

Tác giả:Giấc mơ nhỏ, Tạo: 2017-06-23 19:14:58, Cập nhật: 2017-10-11 10:39:27

Python đơn giản hóa nhiều loại MACD framework (định hướng)

Python siêu mỏng đa dạng MACD Trend Strategy Framework, mã siêu mỏng, chú thích siêu chi tiết. Cần tham khảo Python version CTP Commodity Futures Trading Library (có hỗ trợ phiên bản thử nghiệm 2/3) Template, mã của Template có chú thích phiên bản ngôn ngữ JS (đối với logic).

  • Mã đính kèm:

'''
/*backtest
start: 2016-01-30        
end: 2016-12-30           
period: 1440
periodBase: 60
mode: 0                 
*/
'''
# 以上 为设置的回测默认参数
# ------------ 
# 作者: Zero
# ------------

class Trader:                                   # 声明一个 python 类 
    def __init__(self, q, symbol):              # Trader 类的构造函数, 参数 self(代表类实例化以后的对象) , q(引用 商品期货交易类库 模板 构造的 交易处理对象),   symbol (商品期货合约代码)
        self.q = q                              # 给 构造函数 构造的对象添加属性q  ,并用 参数 q 赋值。 
        self.symbol = symbol                    # 同上, 给构造的对象添加symbol 属性,并用 参数 symbol 赋值。
        self.position = 0                       # 添加 属性 position 赋值 0    ,   该属性是用于 记录仓位数量。
        self.isPending = False                  # 添加 属性 isPending 赋值 False     ,   该属性用于标记 对象状态,是否是挂起状态。

    def onOpen(self, task, ret):                # 类成员函数 , 执行开仓完成后的 回调函数(即 在模拟多线程处理交易的对象q 完成当前任务后 回调该 onOpen 函数处理一些开仓后的工作。)
        if ret:                                 # 交易处理对象 q ,会在处理交易任务完成后 回调onOpen ,传入2个参数 ,第一个 就是由形参task 接收,具体数据为执行的交易任务数据, 第二个参数就是 交易完成的情况
                                                # 如果ret 为有效数据(交易未成功 ret 为 None),则处理  if 块内代码
            self.position = ret['position']['Amount'] * (1 if (ret['position']['Type'] == PD_LONG or ret['position']['Type'] == PD_LONG_YD) else -1)
                                                # 对调用该函数的对象的属性position 赋值, ret['position']['Amount'] 为交易后的持仓数量,根据 ret['position']['Type'] 持仓类型 等于 PD_LONG (持多仓)
                                                # 还是 PD_LONG_YD(持空仓)去选择 ret['position']['Amount'] 乘 1 还是 -1 ,最后把持仓数量赋值 给 position ,(作用是通过 position 区分持多仓还是持空仓)
        Log(task["desc"], "Position:", self.position, ret)  # 打印多个项: q 执行的任务的数据 task 字典的 描述内容,赋值过的position , q 对象处理的交易的完成情况(当前持仓信息)
        self.isPending = False                  # 给 isPending 赋值 False 即代表 当前的 品种 交易逻辑 处于 非挂起状态,可以接受任务。

    def onCover(self, task, ret):               # 平仓任务完成后要执行的回调函数, 参数同  onOpen 一致
        self.isPending = False                  # 设置 isPending 为False 当前 品种的交易逻辑为 非挂起状态,可以接受任务。
        self.position = 0                       # 给记录持仓的变量  position 赋值 为0, 即没有持仓。
        Log(task["desc"], ret)                  # 打印 交易处理对象 q 本次处理的任务 描述(desc),  完成处理的结果(ret)

    def onTick(self):                           # 主要交易逻辑 , MACD 策略核心。
        if self.isPending:                      # 如果 Trader类构造的当前逻辑对象的 isPending 属性 为True 则代表 目前有 交易任务 正在 交易处理对象q 队列中执行。
            return                              # 交易逻辑处于挂起状态,不做任何处理。
        ct = exchange.SetContractType(self.symbol)   # 根据构造函数 传入的 symbol 赋值给 对象成员属性symbol 传入 API 函数 即:交易平台对象exchange 的 SetContractType 函数, 用来设置操作的合约类型
        if not ct:                              # SetContractType 函数切换 交易合约代码(symbol) 成功后会返回 该合约的详细信息, 如果返回 None , 即 not ct 为真, 则立即返回,等待下一轮。
            return

        r = exchange.GetRecords()               # 声明 变量 r (用来储存K线数据) , 调用 API 函数 GetRecords 获取 设置后的该合约的 K线数据,赋值给 r 。
        if not r or len(r) < 35:                # 如果 r 为 None 或者 r的长度小于35 (因为要计算 MACD 指标,必须有足够数量的K线bar,小于35 无法计算)
            return                              # 立即返回 ,下一轮处理。
        macd = TA.MACD(r)                       # 调用 API  指标函数  TA.MACD  ,传入实参 r ,计算MACD 指标数据 ,并赋值给 变量 macd 。(TA.MACD 成功返回的数据是一个 二维数组 [dif, dea, 量柱]) 
                                                # 不明白 dif 、dea 的可以百度  MACD 指标
        diff = macd[0][-2] - macd[1][-2]        # 计算dif和dea的差值 (注意,此处计算使用的是计算出的倒数第二bar的dif、dea,因为倒数第一bar 的K线是一直变动的,macd指标也是一直在变动,准确不变的是倒数第二bar)
        if abs(diff) > 0 and self.position == 0:     # 开仓,如果此刻 指标 (dif - dea)的绝对值 大于0 并且 没有持仓(即: position 等于 0)
            self.isPending = True                    # 改变状态 设置为 挂起状态,  isPending = True 
            self.q.pushTask(exchange, self.symbol, ("buy" if diff > 0 else "sell"), 1, self.onOpen)      # 调用交易处理对象q的成员函数pushTask发出开仓交易任务,参数:exchange交易平台对象(传入即可)
                                                     # self.symbol 合约代码(构造时传入), 根据diff 大于0 还是小于0 去设置 "buy" 或者 "sell", 1 这个参数指的是下单量1手, self.onOpen 传入回调函数的引用 
        if abs(diff) > 0 and ((diff > 0 and self.position < 0) or (diff < 0 and self.position > 0)):     # 平仓,如果此刻指标(dif - dea)的绝对值 大于0 并且 and后的 条件任意一个成立执行if 块内代码,
                              # diff 大于0 并且 持空仓          或者     diff小于0 并且 持多仓 ,均为 平仓条件。
            self.isPending = True               # 设置 为挂起状态。
            self.q.pushTask(exchange, self.symbol, ("closebuy" if self.position > 0 else "closesell"), 1, self.onCover)    # 发送平仓交易任务, 参数 同上发送开仓任务。

def main():                                     # 入口函数
    q = ext.NewTaskQueue()                      # 调用 python版商品期货交易类库 模板 的导出函数(即接口),  ext.NewTaskQueue  返回一个 构造的 交易处理对象。引用 给 变量 q 
    Log(_C(exchange.GetAccount))                # 启动 调用 _C 容错函数 ,传入要容错处理的  API : GetAccount 函数,  返回账户信息 由 Log 函数 输出到日志 , 显示。
    tasks = []                                  # 声明一个 空数组  tasks  。
    for symbol in ["MA701", "rb1701"]:          # 遍历 数组 ["MA701", "rb1701"] 中的元素 , 每次循环 把其中的元素symbol 和 交易处理对象q 作为 参数 传递给 Trader 类的构造函数 去构造交易逻辑对象。
        tasks.append(Trader(q, symbol))         # 构造好的  交易逻辑对象 压入 tasks 数组。用以 循环遍历执行处理。
    while True:                                 # 设置一个 while 死循环
        if exchange.IO("status"):               # 每次循环 调用  API 函数 IO ,传入参数  "status" 去检测 与 期货公司 前置服务器 的连接状态(CTP协议), 返回 True 即连接 交易服务器 和 行情服务器
            for t in tasks:                     # 遍历 tasks 数组, 调用 构造 的 Trader 类的 对象 t的成员函数 onTick ,不断检测行情, 择时开仓 、平仓。
                t.onTick()                      # 见 Trader 类 中的 onTick 函数
            q.poll()                            # 调用 交易处理对象 q 的成员函数 poll  去处理 q 对象内的队列中的 交易任务。
        Sleep(1000)                         # 程序每次 while 循环 暂停一段时间 Sleep(1000) 即: 暂停1秒 (1000毫秒),以免访问 API 过于 频繁。

Chào mừng bạn đến với BUG, đề xuất.


Có liên quan

Thêm nữa