返回列表 发布新帖

调仓示例(报撤直到达到指定仓位)

2256 2
发表于 2023-12-25 17:04:25 | 显示全部楼层 阅读模式
  1. #encoding:gbk

  2. '''
  3. 调仓到指定篮子
  4. '''

  5. import pandas as pd
  6. import numpy as np
  7. import time
  8. from datetime import timedelta,datetime

  9. #自定义类 用来保存状态
  10. class a():pass
  11. A=a()
  12. A.waiting_dict =  {}
  13. A.all_order_ref_dict = {}
  14. #撤单间隔 单位秒 超过间隔未成交的委托撤回重报
  15. A.withdraw_secs = 30
  16. #定义策略开始结束时间 在两者间时进行下单判断 其他时间跳过
  17. A.start_time = '093000'
  18. A.end_time = '150000'

  19. def init(C):
  20.         '''读取目标仓位 字典格式 品种代码:持仓股数, 可以读本地文件/数据库,当前在代码里写死'''
  21.         A.final_dict = {"600000.SH" :10000, '000001.SZ' : 20000}
  22.         '''设置交易账号 acount accountType是界面上选的账号 账号类型'''
  23.         A.acct = account
  24.         A.acct_type = accountType
  25.         #定时器 定时触发指定函数
  26.         C.run_time("f","1nSecond","2019-10-14 13:20:00","SH")


  27. def f(C):
  28.         '''定义定时触发的函数 入参是ContextInfo对象'''
  29.         #记录本次调用时间戳
  30.         t0 = time.time()
  31.         final_dict=A.final_dict
  32.         #本次运行时间字符串
  33.         now = datetime.now()
  34.         now_timestr = now.strftime("%H%M%S")
  35.         #跳过非交易时间
  36.         if now_timestr < A.start_time or now_timestr > A.end_time:
  37.                 return
  38.         #获取账号信息
  39.         acct = get_trade_detail_data(A.acct, A.acct_type, 'account')
  40.         if len(acct) == 0:
  41.                 print(A.acct, '账号未登录 停止委托')
  42.                 return
  43.         acct = acct[0]
  44.         #获取可用资金
  45.         available_cash = acct.m_dAvailable
  46.         print(now, '可用资金', available_cash)
  47.         #获取持仓信息
  48.         position_list = get_trade_detail_data(A.acct, A.acct_type, 'position')
  49.         #持仓数据 组合为字典
  50.         position_dict = {i.m_strInstrumentID + '.' + i.m_strExchangeID : int(i.m_nVolume) for i in position_list}
  51.         position_dict_available = {i.m_strInstrumentID + '.' + i.m_strExchangeID : int(i.m_nCanUseVolume) for i in position_list}
  52.         #未持有的品种填充持股数0
  53.         not_in_position_stock_dict = {i : 0 for i in final_dict if i not in position_dict}
  54.         position_dict.update(not_in_position_stock_dict)
  55.         #print(position_dict)
  56.         stock_list = list(position_dict.keys())
  57.         # print(stock_list)
  58.         #获取全推行情
  59.         full_tick = C.get_full_tick(stock_list)
  60.         #print('fulltick', full_tick)
  61.         #更新持仓状态记录
  62.         refresh_waiting_dict(C)
  63.         #撤超时委托
  64.         order_list = get_trade_detail_data(A.acct, 'stock', 'order')
  65.         if '091500'<= now_timestr <= '093000':#指定的范围內不撤单
  66.                 pass
  67.         else:
  68.                 for order in order_list:
  69.                         #非本策略 本次运行记录的委托 不撤
  70.                         if order.m_strRemark not in A.all_order_ref_dict:
  71.                                 continue
  72.                         #委托后 时间不到撤单等待时间的 不撤
  73.                         if time.time() - A.all_order_ref_dict[order.m_strRemark] < A.withdraw_secs:
  74.                                 continue
  75.                         #对所有可撤状态的委托 撤单
  76.                         if order.m_nOrderStatus in [48,49,50,51,52,55,86,255]:
  77.                                 print(f"超时撤单 停止等待 {order.m_strRemark}")
  78.                                 cancel(order.m_strOrderSysID,A.acct,'stock',C)
  79.         #下单判断
  80.         for stock in position_dict:
  81.                 #有未查到的委托的品种 跳过下单 防止超单
  82.                 if stock in A.waiting_dict:
  83.                         print(f"{stock} 未查到或存在未撤回委托 {A.waiting_dict[stock]} 暂停后续报单")
  84.                         continue
  85.                 if stock in position_dict.keys():
  86.                         #print(position_dict[stock],target_vol,'1111')
  87.                         #到达目标数量的品种 停止委托
  88.                         target_vol = final_dict[stock] if stock in final_dict else 0
  89.                         if int(abs(position_dict[stock] - target_vol)) == 0:
  90.                                 print(stock, C.get_stock_name(stock), '与目标一致')
  91.                                 continue
  92.                         #与目标数量差值小于100股的品种 停止委托
  93.                         if abs(position_dict[stock] - target_vol) < 100:
  94.                                 print(f"{stock} {C.get_stock_name(stock)} 目标持仓{target_vol} 当前持仓{position_dict[stock]} 差额小于100 停止委托")
  95.                                 continue
  96.                         #持仓大于目标持仓 卖出
  97.                         if position_dict[stock]>target_vol:
  98.                                 vol = int((position_dict[stock] - target_vol)/100)*100
  99.                                 if stock not in position_dict_available:
  100.                                         continue
  101.                                 vol = min(vol, position_dict_available[stock])
  102.                                 #获取买一价
  103.                                 print(stock,'应该卖出')
  104.                                 buy_one_price = full_tick[stock]['bidPrice'][0]
  105.                                 #买一价无效时 跳过委托
  106.                                 if not buy_one_price > 0:
  107.                                         print(f"{stock} {C.get_stock_name(stock)} 取到的价格{buy_one_price}无效,跳过此次推送")
  108.                                         continue
  109.                                 print(f"{stock} {C.get_stock_name(stock)} 目标股数{target_vol} 当前股数{position_dict[stock]}")
  110.                                 msg = f"{now.strftime('%Y%m%d%H%M%S')}_{stock}_sell_{vol}股"
  111.                                 print(msg)
  112.                                 #对手价卖出
  113.                                 passorder(24,1101,A.acct,stock,14,-1,vol,'调仓策略',2,msg,C)
  114.                                 A.waiting_dict[stock] = msg
  115.                                 A.all_order_ref_dict[msg] = time.time()
  116.                         #持仓小于目标持仓 买入
  117.                         if position_dict[stock]<target_vol:
  118.                                 vol = int((target_vol-position_dict[stock])/100)*100
  119.                                 #获取卖一价
  120.                                 sell_one_price = full_tick[stock]['askPrice'][0]
  121.                                 #卖一价无效时 跳过委托
  122.                                 if not sell_one_price > 0:
  123.                                         print(f"{stock} {C.get_stock_name(stock)} 取到的价格{sell_one_price}无效,跳过此次推送")
  124.                                         continue
  125.                                 target_value = sell_one_price * vol
  126.                                 if target_value > available_cash:
  127.                                         print(f"{stock} 目标市值{target_value} 大于 可用资金{available_cash} 跳过委托")
  128.                                         continue
  129.                                 print(f"{stock} {C.get_stock_name(stock)} 目标股数{target_vol} 当前股数{position_dict[stock]}")
  130.                                 msg = f"{now.strftime('%Y%m%d%H%M%S')}_{stock}_buy_{vol}股"
  131.                                 print(msg)
  132.                                 #对手价买入
  133.                                 passorder(23,1101,A.acct,stock,14,-1,vol,'调仓策略',2,msg,C)
  134.                                 A.waiting_dict[stock] = msg
  135.                                 A.all_order_ref_dict[msg] = time.time()
  136.                                 available_cash -= target_value
  137.         #打印函数运行耗时 定时器间隔应大于该值
  138.         print(f"下单判断函数运行完成 耗时{time.time() - t0}秒")


  139. def refresh_waiting_dict(C):
  140.         """更新委托状态 入参为ContextInfo对象"""
  141.         #获取委托信息
  142.         order_list = get_trade_detail_data(A.acct,A.acct_type,'order')
  143.         #取出委托对象的 投资备注 : 委托状态
  144.         ref_dict = {i.m_strRemark : int(i.m_nOrderStatus) for i in order_list}
  145.         del_list = []
  146.         for stock in A.waiting_dict:
  147.                 if A.waiting_dict[stock] in ref_dict and ref_dict[A.waiting_dict[stock]] in [56, 53, 54]:
  148.                         #查到对应投资备注 且状态为成交 / 已撤 / 部撤, 从等待字典中删除
  149.                         print(f'查到投资备注 {A.waiting_dict[stock]},的委托 状态{ref_dict[A.waiting_dict[stock]]} (56已成 53部撤 54已撤)从等待等待字典中删除')
  150.                         del_list.append(stock)
  151.                 if A.waiting_dict[stock] in ref_dict and ref_dict[A.waiting_dict[stock]] == 57:
  152.                         #委托状态是废单的 也停止等待 从等待字典中删除
  153.                         print(f"投资备注为{A.waiting_dict[stock]}的委托状态为废单 停止等待")
  154.                         del_list.append(stock)
  155.         for stock in del_list:
  156.                 del A.waiting_dict[stock]
复制代码


评论2

Liwu楼主
发表于 2023-12-25 17:06:32 | 显示全部楼层
实盘策略要注意委托状态的确认, 委托后加入等待列表, 暂停该品种后续报单, 委托查到后再从等待列表删除.
可以参考 http://dict.thinktrader.net/inne ... 5%E7%9B%B8%E5%85%B3
*******1021
发表于 2024-2-4 15:16:09 | 显示全部楼层
赞!!

回复

您需要登录后才可以回帖 登录 | 立即注册

客服专线

400-080-8112

用思考的速度交易,用真诚的态度合作,我们是认真的!
  • 关注公众号
  • 添加微信客服
Copyright © 2001-2025 迅投QMT社区 版权所有 All Rights Reserved. 京ICP备2025122616号-3
关灯 快速发帖
扫一扫添加微信客服
QQ客服返回顶部
快速回复 返回顶部 返回列表