#encoding:gbk
'''
调仓到指定篮子
'''
import pandas as pd
import numpy as np
import time
from datetime import timedelta,datetime
#自定义类 用来保存状态
class a(object):
def __init__(self):
#初始化委托状态记录容器
self.waiting_dict = {}
self.all_order_ref_dict = {}
#撤单间隔 单位秒 超过间隔未成交的委托撤回重报
self.withdraw_secs = 30
#定义策略开始结束时间 在两者间时进行下单判断 其他时间跳过
self.start_time = '093000'
self.end_time = '150000'
A=a()
def init(C):
'''读取目标仓位 字典格式 品种代码:持仓股数, 可以读本地文件/数据库,当前在代码里写死,600000.SH浦发银行,000001.SZ平安银行'''
A.final_dict = {"600000.SH" :300, '000001.SZ' : 200}
'''设置交易账号 acount accountType是界面上选的账号 账号类型'''
A.acct = account
A.acct_type = accountType
#定时器 定时触发指定函数
C.run_time("f","1nSecond","2019-10-14 13:20:00","SH") #pengxuan_note:官方文档中只有4个参数,这里有5个,最后一个是没用的,也没有报错不知道什么原因
def f(C):
'''定义定时触发的函数 入参是ContextInfo对象'''
#记录本次调用时间戳
t0 = time.time()
final_dict=A.final_dict
#本次运行时间字符串
now = datetime.now()
now_timestr = now.strftime("%H%M%S")
#跳过非交易时间 pengxuan_note:未判断中午11:30:00——13:00:00之间的休市时间
if now_timestr < A.start_time or now_timestr > A.end_time:
return
#获取账号信息
acct = get_trade_detail_data(A.acct, A.acct_type, 'account')
if len(acct) == 0:
print(A.acct, '账号未登录 停止委托')
return
acct = acct[0]
#获取可用资金
available_cash = acct.m_dAvailable
print(now, '可用资金', available_cash)
#获取持仓信息
position_list = get_trade_detail_data(A.acct, A.acct_type, 'position')
#持仓数据 组合为字典
position_dict = {i.m_strInstrumentID + '.' + i.m_strExchangeID : int(i.m_nVolume) for i in position_list}
position_dict_available = {i.m_strInstrumentID + '.' + i.m_strExchangeID : int(i.m_nCanUseVolume) for i in position_list}
#未持有的品种填充持股数0
not_in_position_stock_dict = {i : 0 for i in final_dict if i not in position_dict}
position_dict.update(not_in_position_stock_dict)
#print(position_dict)
stock_list = list(position_dict.keys())
# print(stock_list)
#获取全推行情
full_tick = C.get_full_tick(stock_list)
#print('fulltick', full_tick)
#更新持仓状态记录
refresh_waiting_dict(C)
#撤超时委托
order_list = get_trade_detail_data(A.acct, 'stock', 'order')
if '091500'<= now_timestr <= '093000':#指定的范围內不撤单
pass
else:
for order in order_list:
#非本策略 本次运行记录的委托 不撤
if order.m_strRemark not in A.all_order_ref_dict:
continue
#委托后 时间不到撤单等待时间的 不撤
if time.time() - A.all_order_ref_dict[order.m_strRemark] < A.withdraw_secs:
continue
#对所有可撤状态的委托 撤单
if order.m_nOrderStatus in [48,49,50,51,52,55,86,255]:
print(f"超时撤单 停止等待 {order.m_strRemark}")
#cancel(order.m_strOrderSysID,A.acct,'stock',C)
#下单判断
for stock in position_dict:
#有未查到的委托的品种 跳过下单 防止超单
if stock in A.waiting_dict:
print(f"{stock} 未查到或存在未撤回委托 {A.waiting_dict[stock]} 暂停后续报单")
continue
if stock in position_dict.keys(): #pengxuan_note:此处用判断条件没用,stock 是从上面for循环中position_dict取出来的,一定是存在于position_dict.keys中的
#print(position_dict[stock],target_vol,'1111')
#到达目标数量的品种 停止委托
target_vol = final_dict[stock] if stock in final_dict else 0
if int(abs(position_dict[stock] - target_vol)) == 0: #pengxuan_note:此处用int其实没用
print(stock, C.get_stock_name(stock), '与目标一致')
continue
#与目标数量差值小于100股的品种 停止委托
if abs(position_dict[stock] - target_vol) < 100:
print(f"{stock} {C.get_stock_name(stock)} 目标持仓{target_vol} 当前持仓{position_dict[stock]} 差额小于100 停止委托")
continue
#持仓大于目标持仓 卖出
if position_dict[stock]>target_vol:
vol = int((position_dict[stock] - target_vol)/100)*100
if stock not in position_dict_available: #pengxuan_note:在59,60,62,63行中position_dict与position_dict_available都是从持仓中取出,并且position_dict数据更多,怎么可能stock不在position_dict_available呢
continue
vol = min(vol, position_dict_available[stock])
#获取买一价
print(stock,C.get_stock_name(stock),'应该卖出')
buy_one_price = full_tick[stock]['bidPrice'][0]
#买一价无效时 跳过委托
if not buy_one_price > 0:
print(f"{stock} {C.get_stock_name(stock)} 取到的价格{buy_one_price}无效,跳过此次推送")
continue
print(f"{stock} {C.get_stock_name(stock)} 目标股数{target_vol} 当前股数{position_dict[stock]}")
msg = f"{now.strftime('%Y%m%d%H%M%S')}_{stock}_sell_{vol}股"
print(msg)
#挂单价卖出
#passorder(24,1101,A.acct,stock,13,-1,vol,'对冲',2,msg,C)
A.waiting_dict[stock] = msg
A.all_order_ref_dict[msg] = time.time()
#持仓小于目标持仓 买入
if position_dict[stock] 0:
print(f"{stock} {C.get_stock_name(stock)} 取到的价格{sell_one_price}无效,跳过此次推送")
continue
target_value = sell_one_price * vol
if target_value > available_cash:
print(f"{stock} 目标市值{target_value} 大于 可用资金{available_cash} 跳过委托")
continue
print(f"{stock} {C.get_stock_name(stock)} 目标股数{target_vol} 当前股数{position_dict[stock]}")
msg = f"{now.strftime('%Y%m%d%H%M%S')}_{stock}_buy_{vol}股"
print(msg)
#挂单价买入
#passorder(23,1101,A.acct,stock,13,-1,vol,'对冲',2,msg,C)
A.waiting_dict[stock] = msg
A.all_order_ref_dict[msg] = time.time()
available_cash -= target_value
#打印函数运行耗时 定时器间隔应大于该值
print(f"下单判断函数运行完成 耗时{time.time() - t0}秒")
def refresh_waiting_dict(C):
"""更新委托状态 入参为ContextInfo对象"""
#获取委托信息
order_list = get_trade_detail_data(A.acct,A.acct_type,'order')
#取出委托对象的 投资备注 : 委托状态
ref_dict = {i.m_strRemark : int(i.m_nOrderStatus) for i in order_list}
del_list = []
for stock in A.waiting_dict:
if A.waiting_dict[stock] in ref_dict and ref_dict[A.waiting_dict[stock]] in [56, 53, 54]:
#查到对应投资备注 且状态为成交 / 已撤 / 部撤, 从等待字典中删除
print(f'查到投资备注 {A.waiting_dict[stock]},的委托 状态{ref_dict[A.waiting_dict[stock]]} (56已成 53部撤 54已撤)从等待等待字典中删除')
del_list.append(stock)
if A.waiting_dict[stock] in ref_dict and ref_dict[A.waiting_dict[stock]] == 57:
#委托状态是废单的 也停止等待 从等待字典中删除
print(f"投资备注为{A.waiting_dict[stock]}的委托状态为废单 停止等待")
del_list.append(stock)
for stock in del_list:
del A.waiting_dict[stock]
bug代码在上面代码中用注释进行标注。官方文档都写成这样,不能用点心吗?