代码格式化自动行调整_全自动程序化交易——有手就行(44代码篇)

0945870ef64e2ba0be368ca19a5f7313.gif

小黎导读

关注小黎的朋友们大家好!本期是“基于tqsdk(天勤)编译的程序化交易策略”系列第N+10086期。本篇内容为系列内容,共四篇,分为安装、配置、效果、代码篇,阅读用时约20分钟,别忘了点击关注查看更多历史推送哦。

“基于均线交叉与通道突破相结合的交易系统”/“市场情绪日内交易策略”/“做市商与逆向选择”/“短线突破交易系统”/“逆势交易“/“AMA自适应均线”/“CCI通道+自适应系统”/“Cuatro策略开发全流程”(上篇)(下篇)/“震荡行情利器(网格+马丁)”/“商品期货多因子模型”/“TQSDK实战技巧分享录播”/“K线形态量化”/“参数输入框+异步下单demo”/“高频交易模型”/“止损的几种方法及示例程序”/“全品种自动交易”/“期权Delta对冲”

(※本文为“小黎说财经”原创,转载需获得同意,并在显要位置标明文章来源。)

e7d2ff312fc9ad65df7d0dc5b02b9530.png

全自动程序化交易策略代码展示

AMA百万账户简单风控模拟版

仅供小黎展示使用,如果他人用作其他用途后果自负

#!/usr/bin/python
# -*- coding:utf-8 -*-

__author__ = "Xiaoli"

"""
继承了精准版的特性
优化了代码结构只占用一份网络资源
优化了CPU和内存占用
日交易时间(长夜盘短夜盘无夜盘)作为一个参数可以设置了
跟踪止损冷静期可以作为一个参数设置了
距离涨跌停板1%不开仓
盈利一定程度后设置了保本止损
加入了定时报告账户情况
"""

from tqsdk import TqApi, TqKq, TargetPosTask, ta, TqAuth
import pandas as pd
import numpy as np
from json import dumps
from datetime import datetime, time
import time as tm
import os
import requests
import pickle
import asyncio
from contextlib import closing
from talib import KAMA, ATR
from prettytable import PrettyTable, PLAIN_COLUMNS

def write_pickle(data: list, symbol: str):
    """写入缓存变量到plk文件中"""
    with open(os.getcwd() + "\\" + "{}{}{}".format("AMA", symbol, ".plk"), "wb") as f:
        pickle.dump(data, f)

def sent_ding_msg(content: str):
    """钉钉消息提醒模块"""
    robot_id = ""  # 这里填你的钉钉机器人id
    msg = {
        "msgtype": "text",
        "text": {
            "content": "{}\n{}\n{}".format(content, datetime.now().strftime("%Y-%m-%d %H:%M:%S"), "")  # 这里填你的顶顶机器人关键字
        },
    }
    headers = {"content-type": "application/json;charset=utf-8"}
    url = "https://oapi.dingtalk.com/robot/send?access_token=" + robot_id
    body = dumps(msg)
    requests.post(url, data=body, headers=headers)

async def report_account(
    api: TqApi,
    account: TqApi.get_account,
    position: TqApi.get_position,
    klines: TqApi.get_kline_serial,
    klines2: TqApi.get_kline_serial,
):

    async with api.register_update_notify([account, position, klines, klines2]) as update_chan:

        while not api.is_serial_ready(klines) or not api.is_serial_ready(klines2):

            await update_chan.recv()

        async for _ in update_chan:

            if api.is_changing(klines.iloc[-1], "datetime") or api.is_changing(klines2.iloc[-1], "datetime"):

                tb = PrettyTable()
                tb.set_style(PLAIN_COLUMNS)
                tb.field_names = ["合约", "持仓", "多仓成本", "空仓成本", "浮动盈亏"]
                for i in position.keys():
                    if position[i].pos != 0:
                        tb.add_row(
                            [
                                i,
                                position[i].pos,
                                round(position[i]["open_price_long"], 2),
                                round(position[i]["open_price_short"], 2),
                                round(position[i]["float_profit"], 2),
                            ]
                        )
                sent_ding_msg(
                    "{}\n{}{}\n{}{}\n{}{}\n{}{}\n{}{}\n{}{}\n{}\n{}".format(
                        "账户:快期模拟",
                        "今日权益:",
                        round(account["balance"], 2),
                        "昨日权益:",
                        round(account["pre_balance"], 2),
                        "平仓盈亏:",
                        round(account["close_profit"], 2),
                        "浮动盈亏:",
                        round(account["float_profit"], 2),
                        "手续费:",
                        round(account["commission"], 2),
                        "风险度:",
                        "%.2f%%" % (float(account["risk_ratio"]) * 100),
                        "账户持仓:",
                        tb,
                    )
                )

async def AMAStrategy(
    api: TqApi,
    symbol: str,  # 合约代码
    trade_hour: int,  # 日交易时长
    period: int,  # 运行在哪个K线周期
    margin: float,  # 该合约保证金率
    money: int,  # 开仓金额
    risk_ratio: float,  # 单次开仓风险度
    n_atr_stop: float,  # N倍ATR止损系数
    atr_len: int,  # ATR选取的参数
    n_k_len: int,  # 止损后多少根K线不开仓
    n_k_len2: int,  # 跟踪止损后多少根K线不开仓
    eff_ratio_len: int,  # 效率系数也就是自适应均线的参数
    fliter_set: float,  # 过滤器系数超过均值的多少倍才算突破
    filter_len: int,  # 过滤器均值选取的参数
    highest_high_len: int,  # 多少周期的高点
    lowest_low_len: int,  # 多少周期的低点
):
    symbol = str(symbol)
    period = int(period)
    margin = float(margin)
    money = int(money)
    n_atr_stop = float(n_atr_stop)
    atr_len = int(atr_len)
    n_k_len = int(n_k_len)
    n_k_len2 = int(n_k_len2)
    eff_ratio_len = int(eff_ratio_len)
    fliter_set = float(fliter_set)
    filter_len = int(trade_hour * 60 * 60 / period) * filter_len
    highest_high_len = int(highest_high_len)
    lowest_low_len = int(lowest_low_len)
    stop_id = float("nan")  # 硬止损那根K线的位置
    stop_id2 = float("nan")  # 跟踪止损那根K线的位置
    is_gap_bar = False  # 周期K线跳空标记
    kama = pd.Series(dtype=float)  # AMA序列
    atr = float("nan")  # atr
    Filter = float("nan")  # 过滤器
    highest_high = float("nan")  # 周期高点
    lowest_low = float("nan")  # 周期低点
    myhigh = float("nan")  # 开仓后的最高价跟踪止损用
    mylow = float("nan")  # 开仓后的最低价跟踪止损用
    klines2_min_len = max(eff_ratio_len, highest_high_len, lowest_low_len) + 2  # 数据长度要求
    klines3_min_len = max(5, 10, atr_len) + 2  # 数据长度要求

    try:

        with open(os.getcwd() + "\\" + "{}{}{}".format("AMA", symbol, ".plk"), "rb") as f:
            plk_data = pickle.load(f)

    except FileNotFoundError:

        pass

    else:

        stop_id = plk_data[2]
        stop_id2 = plk_data[3]
        is_gap_bar = plk_data[4]
        myhigh = plk_data[5]
        mylow = plk_data[6]

    ticks = api.get_tick_serial(symbol, 2)
    quote = api.get_quote(symbol)
    klines1 = api.get_kline_serial(symbol, 60, 2)
    klines2 = api.get_kline_serial(symbol, period, klines2_min_len)
    klines3 = api.get_kline_serial(symbol, 86400, klines3_min_len)
    position = api.get_position(symbol)
    target_pos = TargetPosTask(api, symbol)

    async with api.register_update_notify([ticks, quote, klines1, klines2, klines3]) as update_chan:

        while not api.is_serial_ready(klines1) or not api.is_serial_ready(klines2) or not api.is_serial_ready(klines3):

            await update_chan.recv()

        while len(klines2.dropna()) or len(klines3.dropna()) 
            await update_chan.recv()

        lots = int(
            (money / (margin * klines3.iloc[-1]["open"] * quote["volume_multiple"]))
            / (
                ATR(klines3["high"], klines3["low"], klines3["close"], 5).iloc[-1]
                / ATR(klines3["high"], klines3["low"], klines3["close"], 10).iloc[-1]
            )
        )

        kama = KAMA(klines2["close"], eff_ratio_len)
        atr = ATR(klines3["high"], klines3["low"], klines3["close"], atr_len).iloc[-1]
        Filter = kama.iloc[-filter_len:].std() * fliter_set
        highest_high = max(klines2.iloc[-highest_high_len:]["high"])
        lowest_low = min(klines2.iloc[-lowest_low_len:]["low"])

        if abs(klines2.iloc[-1]["open"] - klines2.iloc[-2]["close"]) > atr:

            is_gap_bar = True

        else:

            is_gap_bar = False

        try:

            async for _ in update_chan:

                if api.is_changing(klines3.iloc[-1], "datetime"):

                    lots = int(
                        (money / (margin * klines3.iloc[-1]["open"] * quote["volume_multiple"]))
                        / (
                            ATR(klines3["high"], klines3["low"], klines3["close"], 5).iloc[-1]
                            / ATR(klines3["high"], klines3["low"], klines3["close"], 10).iloc[-1]
                        )
                    )
                    atr = ATR(klines3["high"], klines3["low"], klines3["close"], atr_len).iloc[-1]

                if api.is_changing(klines2.iloc[-1], "datetime"):

                    if abs(klines2.iloc[-1]["open"] - klines2.iloc[-2]["close"]) > atr:

                        is_gap_bar = True

                    else:

                        is_gap_bar = False

                if api.is_changing(klines1.iloc[-1], "datetime"):

                    write_pickle([datetime.now(), symbol, stop_id, stop_id2, is_gap_bar, myhigh, mylow], symbol)

                if api.is_changing(ticks.iloc[-1], "datetime"):

                    kama = KAMA(klines2["close"], eff_ratio_len)
                    Filter = kama.iloc[-filter_len:].std() * fliter_set
                    highest_high = max(klines2.iloc[-highest_high_len:]["high"])
                    lowest_low = min(klines2.iloc[-lowest_low_len:]["low"])
                    myhigh = max(myhigh, ticks.iloc[-1]["last_price"])
                    mylow = min(mylow, ticks.iloc[-1]["last_price"])

                    if position.pos == 0 and account["risk_ratio"] 0.8 and is_gap_bar == False:

                        if (klines2.iloc[-1]["id"] > stop_id2 + n_k_len2 or np.isnan(stop_id2)) and (
                            klines2.iloc[-1]["id"] > stop_id + n_k_len or np.isnan(stop_id)
                        ):

                            if (
                                ticks.iloc[-1]["last_price"] >= highest_high
                                and kama.iloc[-1] - kama.iloc[-2] > Filter
                                and ticks.iloc[-1]["last_price"] <= int(quote["upper_limit"] * 0.99)
                            ):

                                open_lots = lots
                                max_loss = (
                                    open_lots
                                    * max(n_atr_stop * atr, ticks.iloc[-1]["last_price"] - klines2.iloc[-2]["low"])
                                    * quote["volume_multiple"]
                                )

                                if max_loss > risk_ratio * account["balance"]:

                                    open_lots = int(
                                        risk_ratio
                                        * account["balance"]
                                        / max(n_atr_stop * atr, ticks.iloc[-1]["last_price"] - klines2.iloc[-2]["low"])
                                        * quote["volume_multiple"]
                                    )

                                if (
                                    account["available"]
                                    > open_lots * margin * ticks.iloc[-1]["last_price"] * quote["volume_multiple"]
                                ):

                                    target_pos.set_target_volume(open_lots)
                                    myhigh = ticks.iloc[-1]["last_price"]
                                    sent_ding_msg(
                                        "{}\n{}\n{}{}\n{}{}".format(
                                            symbol, "多头突破开仓", "开仓触发价:", ticks.iloc[-1]["last_price"], "开仓手数:", open_lots
                                        )
                                    )

                            elif (
                                ticks.iloc[-1]["last_price"] <= lowest_low
                                and kama.iloc[-2] - kama.iloc[-1] > Filter
                                and ticks.iloc[-1]["last_price"] >= int(quote["lower_limit"] * 1.01)
                            ):

                                open_lots = lots
                                max_loss = (
                                    open_lots
                                    * max(n_atr_stop * atr, klines2.iloc[-2]["high"] - ticks.iloc[-1]["last_price"])
                                    * quote["volume_multiple"]
                                )

                                if max_loss > risk_ratio * account["balance"]:

                                    open_lots = int(
                                        risk_ratio
                                        * account["balance"]
                                        / max(n_atr_stop * atr, klines2.iloc[-2]["high"] - ticks.iloc[-1]["last_price"])
                                        * quote["volume_multiple"]
                                    )

                                if (
                                    account["available"]
                                    > open_lots * margin * ticks.iloc[-1]["last_price"] * quote["volume_multiple"]
                                ):

                                    target_pos.set_target_volume(-open_lots)
                                    mylow = ticks.iloc[-1]["last_price"]
                                    sent_ding_msg(
                                        "{}\n{}\n{}{}\n{}{}".format(
                                            symbol, "空头突破开仓", "开仓触发价:", ticks.iloc[-1]["last_price"], "开仓手数:", open_lots
                                        )
                                    )

                    elif position.pos_long > 0 and position["open_price_long"] > 0:

                        if (
                            ticks.iloc[-1]["last_price"] -2]["low"]
                            and ticks.iloc[-1]["last_price"] "open_price_long"] - n_atr_stop * atr
                            and is_gap_bar == False
                        ):

                            target_pos.set_target_volume(0)
                            stop_id = klines2.iloc[-1]["id"]
                            sent_ding_msg(
                                "{}\n{}\n{}{}".format(symbol, "多头硬止损", "止损触发价:", ticks.iloc[-1]["last_price"])
                            )

                        elif myhigh - position["open_price_long"] > n_atr_stop * atr:

                            if ticks.iloc[-1]["last_price"]                                 position["open_price_long"], myhigh - n_atr_stop * atr
                            ) and ticks.iloc[-1]["last_price"] <= min(klines2.iloc[-5:]["low"]):

                                target_pos.set_target_volume(0)
                                stop_id2 = klines2.iloc[-1]["id"]
                                sent_ding_msg(
                                    "{}\n{}\n{}{}".format(symbol, "多头跟踪止损", "止损触发价:", ticks.iloc[-1]["last_price"])
                                )

                        elif kama.iloc[-2] - kama.iloc[-1] > Filter and ticks.iloc[-1]["last_price"] <= lowest_low:

                            target_pos.set_target_volume(-lots)
                            mylow = ticks.iloc[-1]["last_price"]
                            sent_ding_msg(
                                "{}\n{}\n{}{}\n{}{}".format(
                                    symbol, "多头反转开空", "反转触发价:", ticks.iloc[-1]["last_price"], "开仓手数:", lots
                                )
                            )

                    elif position.pos_short > 0 and position["open_price_short"] > 0:

                        if (
                            ticks.iloc[-1]["last_price"] > klines2.iloc[-2]["high"]
                            and ticks.iloc[-1]["last_price"] > position["open_price_short"] + n_atr_stop * atr
                            and is_gap_bar == False
                        ):

                            target_pos.set_target_volume(0)
                            stop_id = klines2.iloc[-1]["id"]
                            sent_ding_msg(
                                "{}\n{}\n{}{}".format(symbol, "空头硬止损", "止损触发价:", ticks.iloc[-1]["last_price"])
                            )

                        elif position["open_price_short"] - mylow > n_atr_stop * atr:

                            if ticks.iloc[-1]["last_price"] > min(
                                position["open_price_short"], mylow - n_atr_stop * atr
                            ) and ticks.iloc[-1]["last_price"] >= max(klines2.iloc[-5:]["high"]):

                                target_pos.set_target_volume(0)
                                stop_id2 = klines2.iloc[-1]["id"]
                                sent_ding_msg(
                                    "{}\n{}\n{}{}".format(symbol, "空头跟踪止损", "止损触发价:", ticks.iloc[-1]["last_price"])
                                )

                        elif kama.iloc[-1] - kama.iloc[-2] > Filter and ticks.iloc[-1]["last_price"] >= highest_high:

                            target_pos.set_target_volume(lots)
                            myhigh = ticks.iloc[-1]["last_price"]
                            sent_ding_msg(
                                "{}\n{}\n{}{}\n{}{}".format(
                                    symbol, "空头反转开多", "反转触发价:", ticks.iloc[-1]["last_price"], "开仓手数:", lots
                                )
                            )

        except Exception as e:

            write_pickle([datetime.now(), symbol, stop_id, stop_id2, is_gap_bar, myhigh, mylow], symbol)
            sent_ding_msg("{}{}\n{}\n{}".format(symbol, "发生了", e, "挂了"))

api = TqApi(account=TqKq(), auth=TqAuth("", ""))  # 这里填入你的信易账号和密码
account = api.get_account()
position = api.get_position()
klines = api.get_kline_serial("KQ.m@SHFE.au", 15 * 60, 2)
klines2 = api.get_kline_serial("KQ.m@CFFEX.TF", 15 * 60, 2)

# 策略品种列表
strategy_list = [
    AMAStrategy(api, "SHFE.rb2101", 6, 15 * 60, 0.08, 30000, 0.015, 1.0, 3, 24, 6, 120, 0.15, 5, 120, 120),
    AMAStrategy(api, "SHFE.ru2101", 6, 15 * 60, 0.08, 50000, 0.025, 1.0, 3, 24, 6, 120, 0.15, 5, 120, 120),
    AMAStrategy(api, "SHFE.ss2012", 6, 30 * 60, 0.08, 50000, 0.025, 0.8, 3, 16, 4, 80, 0.15, 5, 80, 80),
    AMAStrategy(api, "SHFE.cu2012", 8, 30 * 60, 0.10, 50000, 0.025, 1.0, 3, 16, 4, 80, 0.15, 5, 80, 80),
    AMAStrategy(api, "INE.sc2012", 8, 30 * 60, 0.10, 80000, 0.04, 1.0, 3, 19, 5, 95, 0.15, 5, 95, 95),
    AMAStrategy(api, "SHFE.au2012", 8, 30 * 60, 0.08, 80000, 0.04, 1.5, 3, 19, 5, 95, 0.15, 5, 95, 95),
    AMAStrategy(api, "SHFE.ag2012", 8, 30 * 60, 0.12, 80000, 0.04, 0.8, 3, 19, 5, 95, 0.15, 5, 95, 95),
    AMAStrategy(api, "SHFE.bu2012", 6, 15 * 60, 0.10, 30000, 0.015, 1.0, 3, 24, 6, 120, 0.15, 5, 120, 120),
    AMAStrategy(api, "SHFE.sp2012", 6, 15 * 60, 0.07, 30000, 0.015, 0.8, 3, 24, 6, 120, 0.15, 5, 120, 120),
    AMAStrategy(api, "INE.lu2101", 6, 15 * 60, 0.10, 30000, 0.015, 1.0, 3, 24, 6, 120, 0.15, 5, 120, 120),
    AMAStrategy(api, "DCE.p2101", 6, 15 * 60, 0.09, 30000, 0.015, 1.0, 3, 24, 6, 120, 0.15, 5, 120, 120),
    AMAStrategy(api, "DCE.j2101", 6, 15 * 60, 0.09, 30000, 0.015, 1.0, 3, 24, 6, 120, 0.15, 5, 120, 120),
    AMAStrategy(api, "DCE.l2101", 6, 15 * 60, 0.11, 30000, 0.015, 1.0, 3, 24, 6, 120, 0.15, 5, 120, 120),
    AMAStrategy(api, "DCE.m2101", 6, 15 * 60, 0.08, 30000, 0.015, 1.0, 3, 24, 6, 120, 0.15, 5, 120, 120),
    AMAStrategy(api, "DCE.i2101", 6, 15 * 60, 0.11, 30000, 0.015, 1.0, 3, 24, 6, 120, 0.15, 5, 120, 120),
    AMAStrategy(api, "CZCE.SR101", 6, 15 * 60, 0.07, 30000, 0.015, 1.0, 3, 24, 6, 120, 0.15, 5, 120, 120),
    AMAStrategy(api, "CZCE.CF101", 6, 15 * 60, 0.07, 30000, 0.015, 1.0, 3, 24, 6, 120, 0.15, 5, 120, 120),
    AMAStrategy(api, "CZCE.SA101", 6, 15 * 60, 0.05, 30000, 0.015, 1.0, 3, 24, 6, 120, 0.15, 5, 120, 120),
    AMAStrategy(api, "CZCE.FG101", 6, 15 * 60, 0.06, 30000, 0.015, 1.0, 3, 24, 6, 120, 0.15, 5, 120, 120),
    AMAStrategy(api, "CZCE.MA101", 6, 15 * 60, 0.07, 30000, 0.015, 1.0, 3, 24, 6, 120, 0.15, 5, 120, 120),
    AMAStrategy(api, "CFFEX.IF2012", 4, 15 * 60, 0.11, 150000, 0.075, 1.0, 20, 16, 4, 80, 0.05, 5, 80, 80),
    AMAStrategy(api, "CFFEX.TF2012", 4, 3 * 60, 0.03, 50000, 0.025, 1.0, 20, 85, 9, 85, 0.05, 1, 85, 85),
    report_account(api, account, position, klines, klines2),
]

for i in strategy_list:

    api.create_task(i)

with closing(api):

    while True:

        api.wait_update()

期货开户请移步?

一个更懂你的客户经理

2ea8540fef6d1e0d4b88a7c4a60dda4d.png

dbe8cc6baa5da4c45703ef25eb510099.png

本文为“小黎说财经”原创,转载需获得同意,并在显要位置标明文章来源。

作者:小黎说财经

公众号设计/排版:宁晴

0b7a7118026df686a56aa34a0c3b8979.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值