小白量化《穿云箭集群量化》(10)用指标公式实现期货全自动交易
期货交易有多种方式,例如ctp接口等,利用这些接口可以获取实时行情并自动交易,但是比较麻烦的是需要自己建立数据库保存历史数据。
我们这里采用天勤免费接口,获取实时和历史数据,并自动交易。
我们的策略是选择几个品种,用3分钟的KDJ和MACD指标交叉,来实现全自动交易。
策略中只需要修改策略信息,就可以实现交易。

##########修改模拟帐户信息########################
信易账户=''
账户密码=''
api = tqsdk.TqApi(account=tqsdk.TqKq(),auth=tqsdk.TqAuth(user_name=信易账户,password=账户密码))  # 构造 api 实例
##########修改实盘帐户信息########################
#api = TqApi(TqAccount("H海通期货", "412432343", "123456"), auth=TqAuth(信易账户, 账户密码))  # 构造 api 实例
#############################################

下面给我给出穿云箭量化上的期货策略交易源代码。

策略名='高级_期货策略天勤数据'
'''
声明:本策略不保证能赚钱,使用要求如下。
1、本策略是为客户设计演示策略,供用户学习使用。
'''
修改日期='2023-03-21'
导入 pandas 命名为 pd
导入 time,os
导入 HP_tdx 命名为 htdx   #小白量化行情模块
导入 HP_global 命名为 hg   #建立高级全局数据域hg
从 HP_formula 导入 *  #小白量化公式模块
从 HP_factor 导入 *  #小白量化因子公式及Alpha公式模块
导入 HP_factor 命名为 hf #小白量化因子公式及Alpha公式模块
导入 HP_formula 命名为 gs  #小白量化公式模块
导入 HP_quant 命名为 hpq   #穿云箭量化模块
从 HP_quant 导入 *  #穿云箭量化模块
导入 HP_tdxgs 命名为 tgs  #公式运行模块
导入 aiohttp, random, time, logging, datetime, json, akshare
从 xtquant 导入 xtdata, xttrader, xtconstant
从 xtquant.xttrader 导入 XtQuantTrader, XtQuantTraderCallback
从 xtquant.xttype 导入 StockAccount
导入 HP_xbdata 命名为 hpx
导入 tqsdk
从 tqsdk 导入 TqApi, TqAuth, TqAccount, TqKq

##########修改模拟帐户信息########################
信易账户=''
账户密码=''
api = tqsdk.TqApi(account=tqsdk.TqKq(),auth=tqsdk.TqAuth(user_name=信易账户,password=账户密码))  # 构造 api 实例
##########修改实盘帐户信息########################
#api = TqApi(TqAccount("H海通期货", "412432343", "123456"), auth=TqAuth(信易账户, 账户密码))  # 构造 api 实例
#############################################

mygs=tgs.Tdxgs()
函数 初始化(context):
    context.zh='tianqin'      #账户
    context.zhlx='期货'   #账户类型,2个汉字
    context.firstcash=1000000.00  #初始现金
    context.cash=context.firstcash
    context.portfolio.available_cash=context.firstcash
    # 设置我们要操作的股票池
    g.stocks=[]

    hpq.set_universe(g.stocks)
    hpq.log.info('----策略环境信息-----')
    输出('量化模块版本: ',hpq.ver)
    输出('量化模块最后修改日期: ',hpq.mdate)
    输出('svrip: ',hpq.svrip)
    输出('svrport: ',hpq.svrport)
    输出('\n----开始运行策略-----\n')
    输出('策略名:'+策略名)
    qhcsj2=time.strftime('%Y%m%d %H:%M:%S',time.localtime(time.time()))
    输出('开始运行时间:'+qhcsj2)

    # 开启动态复权模式(真实价格)
    set_option('use_real_price',)
    hg.hqsl=0 #行情数量
    hg.seemsg=假
    g.stocks=["SHFE.au2309","SHFE.ag2309",'CZCE.SR309','DCE.y2309','INE.bc2309','CZCE.MA309']  #设置股票池

    account = api.get_account() #获得账户资金情况
    context.portfolio.total_value=account['static_balance']   #总资产
    context.portfolio.available_cash=account['available']      #'可用金额'
    context.portfolio.positions_value=0.0   #'股票市值'
    context.portfolio.locked_cash=0.0  #冻结金额

    position = api.get_position()  ##获取全部持仓
    g.holds=[]  #持仓证券代码
    序列循环 k 在其中 position.keys():
        输出(k)
        g.holds.append(k)
    context.ccs=g.holds
    hpq.context=context
    g.ztzd={}   #状态字典
    g.wt=[]
    g.MAX=50
    g.hd=0.003 #滑点
    g.zzs=-0.05  #止损
    g.amount=1  #买入数量()
    g.MAXamount=1 #最大持仓量
    g.xdzj=10000  #下单资金
    g.cs=0  #策略运行次数
    #中文Python学习交流群 811379766
    g.gs='''{自编指标公式,最好用专家系统公式}
MA5:=MA(C,5);
MA10:=MA(C,10);

N:=9;
M1:=3;
M2:=3;
RSV := (CLOSE - LLV(LOW, N)) / (HHV(HIGH, N) - LLV(LOW, N)) * 100;
K:= EMA(RSV, (M1 * 2 - 1));
D:= EMA(K, (M2 * 2 - 1));
J:= K * 3 - D * 2;
TJ1:=CROSS(K,D)*IF(D<35,1,0);
TJ1A:=CROSS(D,K)*IF(D>65,1,0);

SHORT:=12;
LONG:=26;
M:=9;
DIFF:= EMA(CLOSE, SHORT) - EMA(CLOSE, LONG)
DEA:= EMA(DIFF, M)
MACD:= (DIFF - DEA) * 2
TJ2:=CROSS(DIFF,DEA);
TJ2A:=CROSS(DEA,DIFF);
BUY:TJ2*IF(COUNT(TJ1,5)>0,1,0);
SELL:TJ2A*IF(COUNT(TJ1A,5)>0,1,0);
'''

# 每个单位时间(如果按天回测,则每天调用一次,如果按分钟,则每分钟调用一次)调用一次
函数 开盘中(context):
    starttime = datetime.datetime.now()
    g.cs=g.cs+1

    #获取订单
    g.wt={}
    g.wt=order=api.get_order()
    序列循环 k 在其中 order.keys():
        输出(k)
        #api.cancel_order(k)  ##撤销订单

    account = api.get_account() #获得账户资金情况
    context.portfolio.total_value=account['static_balance']   #总资产
    context.portfolio.available_cash=account['available']      #'可用金额'

    position = api.get_position()  ##获取全部持仓
    g.holds=[]  #持仓证券代码
    序列循环 k 在其中 position.keys():
        输出(k)
        g.holds.append(k)

    context.ccs=g.holds
    hpq.context=context

    #合约处理
    pos_long=0
    pos_short=0
    序列循环 security 在其中 g.stocks:
        pos_long=0
        pos_short=0
        jyzt=jyzt2=jyzt3=jyzt4=0  #交易状态
        如果 security 在其中 g.holds:
            k=security
            mk=a0=position[k]['exchange_id']  #交易所
            a1=position[k]['instrument_id'] #交易所内的合约代码     
            pos_long_his=a2=position[k]['pos_long_his']  #多头老仓手数
            pos_long_today=a3=position[k]['pos_long_today']  #多头今仓手数
            pos_short_his=a4=position[k]['pos_short_his']  #空头老仓手数
            pos_short_today=a5=position[k]['pos_short_today'] #空头今仓手数
            a6=position[k]['open_price_long'] #多头开仓均价,以开仓价来统计
            a7=position[k]['open_price_short']  #空头开仓均价,以开仓价来统计
            a8=position[k]['open_cost_long'] #多头开仓成本,为开仓价乘以手数
            a9=position[k]['open_cost_short'] #空头开仓成本,为开仓价乘以手数 
            a10=position[k]['position_price_long'] #多头持仓均价,为多头持仓成本除以多头数量
            a11=position[k]['position_price_short'] #空头持仓均价,为空头持仓成本除以空头数量
            a12=position[k]['position_cost_long'] #多头持仓成本,为今仓的开仓价乘以手数加上昨仓的昨结算价乘以手数的和  
            a13=position[k]['position_cost_short'] #空头持仓成本,为今仓的开仓价乘以手数加上昨仓的昨结算价乘以手数的和
            a14=position[k]['float_profit_long'] #多头浮动盈亏
            a15=position[k]['float_profit_short'] #空头浮动盈亏 
            a16=position[k]['float_profit'] #浮动盈亏 (浮动盈亏: 相对于开仓价的盈亏)
            a17=position[k]['position_profit_long'] #多头持仓盈亏
            a18=position[k]['position_profit_short'] #空头持仓盈亏
            a19=position[k]['position_profit'] #持仓盈亏 (持仓盈亏: 相对于上一交易日结算价的盈亏),期权持仓盈亏为 0
            pos_long=position[k]['pos_long'] #多头持仓手数, ==0表示无多头持仓. >0表示多头持仓手数
            pos_short=position[k]['pos_short'] #空头持仓手数, ==0表示无空头持仓. >0表示空头持仓手数             

        如果 security  不是 在其中 g.ztzd:
            jyzt=jyzt2=jyzt3=jyzt4=0  #交易状态
            g.ztzd[security]=[jyzt,jyzt2,jyzt3,jyzt4]
        否则:
            jyzt,jyzt2,jyzt3,jyzt4=g.ztzd[security]

        #try:
        如果 真:
            df = api.get_kline_serial(security,180)
            如果 len(df)<1:
                继续
            price = df.close.iloc[-1]
            high= df.high.iloc[-1]
            low= df.low.iloc[-1]

            cash=context.portfolio.available_cash #现金

            mydf=gs.initmydf(df)  ##初始化mydf表
            mydf['pre_close']=REF(mydf.close,1)
            pre_close=mydf['pre_close'].iloc[-1]   #前收盘
            mygs.loaddf(mydf)  #加载行情数据
            mydf=mygs.execgs(g.gs)  #运行指标公式
            mydf=gs.initmydf(mydf)  ##初始化mydf表
            C=CLOSE=mydf.close
            L=LOW=mydf.low
            H=HIGH=mydf.high
            O=OPEN=mydf.open
            输出(security,'多单:',pos_long,'空单:',pos_short,'BUY:',mydf.BUY.iloc[-1],'SELL:',mydf.SELL.iloc[-1])
            quote = api.get_quote(security)

            如果 pos_long>0: #有多头持仓
                如果 mydf.SELL.iloc[-1]>0: #10日上穿5日
                    输出('多单平仓',security)
                    如果 mk=='SHFE' 或者 mk=='INE' 或者 mk=='CFFEX':
                        如果 pos_long_today>0:
                            order = api.insert_order(symbol=security, direction="SELL", offset="CLOSETODAY", volume=pos_long_today, limit_price=quote.ask_price1)
                            pos_long=pos_long-pos_long_today
                        如果 pos_long_his>0:
                            order = api.insert_order(symbol=security, direction="SELL", offset="CLOSE", volume=pos_long_his, limit_price=quote.ask_price1)
                            pos_long=pos_long-pos_long_his
                    否则:
                        order = api.insert_order(symbol=security, direction="SELL", offset="CLOSE", volume=pos_long, limit_price=quote.ask_price1)
                        pos_long=pos_long-pos_long
                    jyzt=0

            如果 pos_short>0: #有空头持仓
                如果 mydf.BUY.iloc[-1]>0: #KD交叉
                    输出('空单平仓',security)
                    如果 mk=='SHFE' 或者 mk=='INE' 或者 mk=='CFFEX':
                        如果 pos_short_today>0:
                            order = api.insert_order(symbol=security, direction="BUY", offset="CLOSETODAY", volume=pos_short_today, limit_price=quote.bid_price1)
                            pos_short=pos_short-pos_short_today
                        如果 pos_short_his>0:
                            order = api.insert_order(symbol=security, direction="BUY", offset="CLOSE", volume=pos_short_his, limit_price=quote.bid_price1)
                            pos_short=pos_short-pos_short_his
                    否则:
                        order = api.insert_order(symbol=security, direction="BUY", offset="CLOSE", volume=pos_short, limit_price=quote.bid_price1)
                        pos_short=pos_short-pos_short
                    jyzt2=0

            如果 mydf.BUY.iloc[-1]>0  并且 pos_long<g.MAXamount 并且 jyzt==0: #KD交叉,D小于70
                jyzt=1
                price2=quote.bid_price1
                order = api.insert_order(symbol=security, direction="BUY", offset="OPEN", volume=g.amount, limit_price=price2)
                pos_long=pos_long+g.amount
                hpq.log.info(context.current_dt+" 买入: %s ,数量:%d,买入价格:%.2f,成交资金:%0.2f"%(security,g.amount,price2,g.amount*price2))

        g.ztzd[security]=[jyzt,jyzt2,jyzt3,jyzt4]

    api.wait_update()  #是一个阻塞函数, 程序在这行上等待, 直到收到数据包才返回.
    endtime = datetime.datetime.now()
    costtime=(endtime - starttime).seconds
    t1=costtime-int(costtime/60)*60
    t2=int(costtime/60)-int(int(costtime/60)/60)*60
    t3=int(int(costtime/60)/60)
    输出('花费时间:%d:%d:%d'%(t3,t2,t1))

上面策略可以在穿云箭量化平台上运行,实现全自动交易。
前面介绍了股票,期货量化策略,后面介绍其他品种及更多策略。

超越自己是我的每一步!我的进步就是你的进步!

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐