以文本方式查看主题 - 金字塔客服中心 - 专业程序化交易软件提供商 (http://weistock.com/bbs/index.asp) -- 高级功能研发区 (http://weistock.com/bbs/list.asp?boardid=5) ---- 发布一个Python网格交易策略 (http://weistock.com/bbs/dispbbs.asp?boardid=5&id=167260) |
-- 作者:guotx2010 -- 发布时间:2018/12/21 8:33:46 -- 发布一个Python网格交易策略 老听说金字塔支持Python了,而且很牛X,一直想了解一下,就边学边玩,写了一个网格交易的策略,经过验证,还不错,金字塔的Python版用于算法交易还是可以,从交易下单,到成交过程订单状态的回报,都很准确。 相对于VBA使用对象的方式来调用,Python更直观,简洁。 需要增强的地方(可能我还没学会): 1、希望增加对INI文件读写的功能,我使用 import ConfigParser不支持 2、希望增加对界面方面的支持,Python有支持图形的库 -------------------------------------------------------------- # 本Python代码主要用于策略交易 # 可以自己import我们平台支持的第三方python模块,比如pandas、numpy等。 from PythonApi import * import time from decimal import Decimal # 参数定义区,这里定义的参数可以直接在context对象中获取。--(选择实现) #def parameter(): # input_par("myvalues1",5,1,20,1) # input_par("myvalues2",10,1,20,1) # 在这个方法中编写任何的初始化逻辑。context对象将会在你的算法策略的任何方法之间做传递。--(必须实现) def init(context): # 在context中保存全局变量 context.s1 = "ZQZC05" #动力煤 context.lastbuy=0 #末次买入开仓单号 context.lastsell=0 #末次卖出开仓单号 context.lastbuyping=0 #末次平多单单号 context.lastsellping=0 #末次平空单单号 context.jiange=1 #间隔 context.vol=1 #每档手数 context.firstvol=5 #初始手数 context.fx=1 #交易方向 1-多 2-空 context.price=561.2 #初始参考价 context.maxvol=8*context.vol #最大手数 settimer(GridTrade,2000) #2秒执行一次 print(context.s1+"策略启动") #调试打印输出 def setorderid(context): #检查未成交订单,将单号赋值给全局变量,避免启动策略时变量的值为0 #print("获取未成交订单编号") Orders=get_orders(context.s1,0) #取未成交单 context.lastbuy=0 context.lastbuyping=0 context.lastsell=0 context.lastsellping=0 if not(Orders == None): for order in Orders: orderID=order.order_id #委托单号 sBuySell=order.side #买卖 sKp=order.position_effect #开平 sStatus=order.status #状态 #print(str(orderID)+\',\'+sBuySell+\',\'+sKp+\',\'+sStatus) if context.lastbuy==0 and sBuySell=="buy" and sKp=="open" and sStatus=="submitted": context.lastbuy=order.order_id #单号 if context.lastsell==0 and sBuySell=="sell" and sKp=="open" and sStatus=="submitted": context.lastsell=order.order_id #单号 if context.lastbuyping==0 and sBuySell=="sell" and sKp=="close" and sStatus=="submitted": context.lastbuyping=order.order_id #单号 if context.lastsellping==0 and sBuySell=="buy" and sKp=="close" and sStatus=="submitted": context.lastsellping=order.order_id #单号 #print(\'开多:\'+str(context.lastbuy)+\',平多:\'+str(context.lastbuyping)+\',开空:\'+str(context.lastsell)+\',平空:\'+str(context.lastsellping)) #网格交易主程序 def GridTrade(context): if istradertime(context.s1)==False: #不在交易时间,不进入交易段 return setorderid(context) #获取未成交订单号,保存到全局变量 nAmount=get_account(19) #可用资金 if nAmount<=10000: print(\'账户可用资金低于10000了,退出交易。\') return portfolio=get_portfolio(context.s1,0) #获取持仓量 if context.fx==1: iDuoTotal=portfolio.buy_quantity nCurOrdPrice = round(context.price - ((iDuoTotal -context.firstvol) * context.jiange) / context.vol, 1) else: iKongTotal=portfolio.sell_quantity nCurOrdPrice = round(context.price - ((context.firstvol - iKongTotal) * context.jiange) / context.vol, 1) #print(\'档位价:\'+str(nCurOrdPrice)+\',开多:\'+str(context.lastbuy)+\',平多:\'+str(context.lastbuyping)+\',开空:\'+str(context.lastsell)+\',平空:\'+str(context.lastsellping)) nPrice=get_dynainf (context.s1,7) #获取最新价 if context.fx==1: #做多 if (context.lastbuy==0 and iDuoTotal<context.maxvol): nOrdPrice=nCurOrdPrice-context.jiange context.lastbuy=buy_open(context.s1,"Limit",nOrdPrice,context.vol) print(\'档位价:\'+str(nCurOrdPrice)+\',委托价:\'+str(nOrdPrice)+\',开多\') if (context.lastbuyping==0 and iDuoTotal>0): nOrdPrice=nCurOrdPrice+context.jiange context.lastbuyping=sell_close(context.s1,"Limit",nOrdPrice,context.vol) print(\'档位价:\'+str(nCurOrdPrice)+\',委托价:\'+str(nOrdPrice)+\',平多\') if context.fx==2 and iKongTotal<context.maxvol: #做空 if (context.lastsell==0): nOrdPrice=nCurOrdPrice+context.jiange context.lastsell=sell_open(context.s1,"Limit",nOrdPrice,context.vol) print(\'档位价:\'+str(nCurOrdPrice)+\',委托价:\'+str(nOrdPrice)+\',开空\') if (context.lastsellping==0 and iKongTotal>0): nOrdPrice=nCurOrdPrice-context.jiange context.lastsellping=buy_close(context.s1,"Limit",nOrdPrice,context.vol) print(\'档位价:\'+str(nCurOrdPrice)+\',委托价:\'+str(nOrdPrice)+\',平空\') # before_trading此函数会在每天基准合约的策略交易开始前被调用,当天只会被调用一次。--(选择实现) def before_trading(context): pass # 你选择的品种的数据更新将会触发此段逻辑,例如日或分钟历史数据切片或者是实时数据切片更新。--(必须实现) def handle_bar(context): # 开始编写你的主要的算法逻辑。 pass # after_trading函数会在每天交易结束后被调用,当天只会被调用一次。 --(选择实现) def after_trading(context): pass # order_status当委托下单,成交,撤单等与下单有关的动作时,该方法就会被调用。---(选择实现) def order_status(context,order): #print(\'订单成交\') #print(order.order_book_id) #print(str(order.order_id)+\',\'+order.status+\',\'+order.order_book_id) #print(\'开多:\'+str(context.lastbuy)+\',平多:\'+str(context.lastbuyping)+\',开空:\'+str(context.lastsell)+\',平空:\'+str(context.lastsellping)) #如果是成交,将对应的委托单撤销 if (order.status=="tradeing" and order.order_book_id==context.s1): print(str(order.order_id)+\'全部成交\') if order.order_id==context.lastbuy: #买入成交 if context.lastbuyping!=0: cancel_order (context.lastbuyping) print("买入成交之后撤平仓单,"+str(context.lastbuyping)) context.lastbuyping=0 if order.order_id==context.lastbuyping: #平多成交 if context.lastbuy!=0: cancel_order (context.lastbuy) print("平多成交之后撤开仓单,"+str(context.lastbuy)) context.lastbuy=0 if order.order_id==context.lastsell: #卖出成交 if context.lastsellping!=0: cancel_order (context.lastsellping) print("卖出成交之后撤平仓单,"+str(context.lastsellping)) context.lastsellping=0 if order.order_id==context.lastsellping: #平空成交 if context.lastsell!=0: cancel_order (context.lastsell) print("平空成交之后撤开仓单,"+str(context.lastsell)) context.lastsell=0 #如果是撤单,将对应的变量设置为0 if (order.status=="cancelled" and order.order_book_id==context.s1): if order.order_id==context.lastbuy: #买入撤单 print("买入开仓撤单,"+str(context.lastbuy)) context.lastbuy=0 if order.order_id==context.lastbuyping: #平多撤单 print("平多单撤单,"+str(context.lastbuyping)) context.lastbuyping=0 if order.order_id==context.lastsell: #卖出撤单 print("卖出开仓撤单,"+str(context.lastsell)) context.lastsell=0 if order.order_id==context.lastsellping: #平空撤单 print("平空单撤单,"+str(context.lastsellping)) context.lastsellping=0 # order_action当查询交易接口信息时返回的通知---(选择实现) #def order_action(context,type, account, datas) # pass # exit函数会在测评结束或者停止策略运行时会被调用。---(选择实现) def exit(context): killtimer(GridTrade) #终止计时器 |
-- 作者:yukizzc -- 发布时间:2018/12/21 8:49:16 -- 1、你不使用金字塔的绿色版,自己本地装python的环境,然后安装这些库是可以使用的。 2、GUI界面这块目前可能的确不行 |
-- 作者:guotx2010 -- 发布时间:2018/12/21 8:56:43 -- 那我得安装一个python试试了,至于gui,可以结合vba做窗体来弥补。 |
-- 作者:马良 -- 发布时间:2018/12/21 10:03:18 -- 1,后面会增加ini文件的直接操作函数 2,python对ui的操作肯定不如vba的,python的优点在于策略研发而不是二次开发 |
-- 作者:guotx2010 -- 发布时间:2018/12/23 16:31:49 -- 周末用vba做界面,将需要交互的ini文件读写,做成窗体,提供盘中修改的功能,python实时读取ini文件进行交易,形成vba和python的互补,挺不错。 |
-- 作者:F10 -- 发布时间:2019/2/19 10:26:50 -- context.s1 = "ZQZC05" #动力煤 这样可以吗? context.s1 = "ZC05" #动力煤
|
-- 作者:投资老友-WAN -- 发布时间:2019/2/20 14:43:47 -- 楼主,谢谢你的分享,看你的代码很有意思,你没有用handle Bar的方式来触发运行策略,而是建立时钟settimer(GridTrade,2000) 来跑你的网格交易子程序Grid Trade |
-- 作者:F10 -- 发布时间:2019/2/21 14:01:03 -- 执行Python脚本时遇到错误。 类型: SystemError 描述: PyEval_EvalFrameEx returned a result with an error set 不知道是哪里错了?
|
-- 作者:无为剑 -- 发布时间:2019/2/21 15:47:08 -- 这个策略不能进行程序化回测,只能用在盘中实时交易 |
-- 作者:投资老友-WAN -- 发布时间:2019/2/22 9:31:38 -- 不能回测的原因可能就是这个策略不是用handle bar触发运算循环,是用类似VB的定时器触发。Python模块的回测是以Handle Bar为循环的。 |