交易示例
# 交易示例
# 1.PASSORDER下单函数Demo
本示例用于演示K线走完下单及立即下单的参数写法差异,旨在帮助您了解如何快速实现下单操作。
#coding:gbk
c = 0
s = '000001.SZ'
def init(ContextInfo):
# 立即下单 用最新价买入股票s 100股,且指定投资备注
passorder(23,1101,account,s,5,0,100,'1',2,'tzbz',ContextInfo)
pass
def handlebar(ContextInfo):
if not ContextInfo.is_last_bar():
#历史k线不应该发出实盘信号 跳过
return
if ContextInfo.is_last_bar():
global c
c +=1
if c ==1:
# 用14.00元限价买入股票s 100股
passorder(23,1101,account,s,11,14.00,100,1,ContextInfo) # 当前k线为最新k线 则立即下单
# 用最新价限价买入股票s 100股
passorder(23,1101,account,s,5,-1,100,0,ContextInfo) # K线走完下单
# 用最新价限价买入股票s 1000元
passorder(23, 1102, account, s, 5, 0,1000, 2, ContextInfo) # 不管是不是最新K线,立即下单
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 2.集合竞价下单
本示例演示了利用定时器函数和passorder下单函数在集合竞价期间以指定价买入平安银行100股
#coding:gbk
import time
c = 0
s = '000001.SZ'
def init(ContextInfo):
# 设置定时器,历史时间表示会在一次间隔时间后开始调用回调函数 比如本例中 5秒后会后第一次触发myHandlebar调用 之后五秒触发一次
ContextInfo.run_time("myHandlebar","5nSecond","2019-10-14 13:20:00")
def myHandlebar(ContextInfo):
global c
now = time.strftime('%H%M%S')
if c ==0 and '092500' >= now >= '091500':
c += 1
passorder(23,1101,account,s,11,14.00,100,2,ContextInfo) # 立即下单
def handlebar(ContextInfo):
return
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 3.PASSORDER下算法单函数Demo
本示例由于演示如何下达算法单,具体算法参数请参考迅投投研平台客户端参数说明。
#coding:gbk
import time
def init(C):
userparam={
'OrderType':1, #表示要下算法
'PriceType':0, # 卖5价下单
'MaxOrderCount':12, # 最大委托次数
'SuperPriceType':0, # 超价类型,0表示按比例
'SuperPriceRate':0.02, # 超价2%下单
'VolumeRate':0.1, # 单笔下单比率 每次拆10%
'VolumeType': 10, # 单笔基准量类型
'SingleNumMax':1000000, # 单笔拆单最大值
'PriceRangeType':0, # 波动区间类型
'PriceRangeRate':1, # 波动区间值
'ValidTimeType':1, # 有效时间类型 1 表示按执行时间
'ValidTimeStart':int(time.time()), # 算法开始时间
'ValidTimeEnd':int(time.time()+60*60), # 算法结束时间
'PlaceOrderInterval':10, # 报撤间隔
'UndealtEntrustRule':0, # 未成委托处理数值 用卖5加挂单
}
target_vol = 2000000 # 股, 算法目标总量
algo_passorder(23, 1101, account, '600000.SH', -1, -1, target_vol, '', 2, '普通算法', userparam, C)
print('finish')
def handlebar(C):
pass
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# 4.如何使用投资备注
投资备注功能是模型下单时指定的任意字符串(长度小于24),即passorder的userOrderId参数,可以用于匹配委托或成交。有且只有passorder, algo_passorder, smart_algo_passorder下单函数支持投资备注功能。
# encoding:gbk
note = 0
def get_new_note():
global note
note += 1
return str(note)
def init(ContextInfo):
ContextInfo.set_account(account)
passorder(23, 1101, account, '000001.SZ', 5 ,0, 100, '', 2, get_new_note(), ContextInfo)
orders = get_trade_detail_data(account, accountType, 'order')
remark = [o.m_strRemark for o in orders]
sysid_list = [o.m_strOrderSysID for o in orders]
print(remark)
def handlebar(C):
pass
def order_callback(C, O):
print(O.m_strRemark, O.m_strOrderSysID)
def deal_callback(C, D):
print(D.m_strRemark, D.m_strOrderSysID)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# 5.如何获取委托持仓及资金数据
本示例用于演示如何通过函数获取指定账户的委托、持仓、资金数据
#coding:gbk
def to_dict(obj):
attr_dict = {}
for attr in dir(obj):
try:
if attr[:2] == 'm_':
attr_dict[attr] = getattr(obj, attr)
except:
pass
return attr_dict
def init(C):
pass
#orders, deals, positions, accounts = query_info(C)
def handlebar(C):
if not C.is_last_bar():
return
orders, deals, positions, accounts = query_info(C)
def query_info(C):
orders = get_trade_detail_data('8000000213', 'stock', 'order')
for o in orders:
print(f'股票代码: {o.m_strInstrumentID}, 市场类型: {o.m_strExchangeID}, 证券名称: {o.m_strInstrumentName}, 买卖方向: {o.m_nOffsetFlag}',
f'委托数量: {o.m_nVolumeTotalOriginal}, 成交均价: {o.m_dTradedPrice}, 成交数量: {o.m_nVolumeTraded}, 成交金额:{o.m_dTradeAmount}')
deals = get_trade_detail_data('8000000213', 'stock', 'deal')
for dt in deals:
print(f'股票代码: {dt.m_strInstrumentID}, 市场类型: {dt.m_strExchangeID}, 证券名称: {dt.m_strInstrumentName}, 买卖方向: {dt.m_nOffsetFlag}',
f'成交价格: {dt.m_dPrice}, 成交数量: {dt.m_nVolume}, 成交金额: {dt.m_dTradeAmount}')
positions = get_trade_detail_data('8000000213', 'stock', 'position')
for dt in positions:
print(f'股票代码: {dt.m_strInstrumentID}, 市场类型: {dt.m_strExchangeID}, 证券名称: {dt.m_strInstrumentName}, 持仓量: {dt.m_nVolume}, 可用数量: {dt.m_nCanUseVolume}',
f'成本价: {dt.m_dOpenPrice:.2f}, 市值: {dt.m_dInstrumentValue:.2f}, 持仓成本: {dt.m_dPositionCost:.2f}, 盈亏: {dt.m_dPositionProfit:.2f}')
accounts = get_trade_detail_data('8000000213', 'stock', 'account')
for dt in accounts:
print(f'总资产: {dt.m_dBalance:.2f}, 净资产: {dt.m_dAssureAsset:.2f}, 总市值: {dt.m_dInstrumentValue:.2f}',
f'总负债: {dt.m_dTotalDebit:.2f}, 可用金额: {dt.m_dAvailable:.2f}, 盈亏: {dt.m_dPositionProfit:.2f}')
return orders, deals, positions, accounts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# 6. 使用快速交易参数委托
本例展示如何使用快速交易参数(quickTrade)立刻进行委托.
#coding:gbk
def after_init(C):
#account变量是模型交易界面 添加策略时选择的资金账号 不需要手动填写
#快速交易参数(quickTrade )填2 passorder函数执行后立刻下单 不会等待k线走完再委托。 可以在after_init函数 run_time函数注册的回调函数里进行委托
msg = f"投资备注字符串 用来区分不同委托"
passorder(23, 1101, account, '600000.SH', 5, -1, 200, '测试下单', 2, msg, C)
1
2
3
4
5
6
7
2
3
4
5
6
7
# 7.调整至目标持仓Demo
本示例由于演示如何调仓
#encoding:gbk
'''
调仓到指定篮子
'''
import pandas as pd
import numpy as np
import time
from datetime import timedelta,datetime
#自定义类 用来保存状态
class a():pass
A=a()
A.waiting_dict = {}
A.all_order_ref_dict = {}
#撤单间隔 单位秒 超过间隔未成交的委托撤回重报
A.withdraw_secs = 30
#定义策略开始结束时间 在两者间时进行下单判断 其他时间跳过
A.start_time = '093000'
A.end_time = '150000'
def init(C):
'''读取目标仓位 字典格式 品种代码:持仓股数, 可以读本地文件/数据库,当前在代码里写死'''
A.final_dict = {"600000.SH" :10000, '000001.SZ' : 20000}
'''设置交易账号 acount accountType是界面上选的账号 账号类型'''
A.acct = account
A.acct_type = accountType
#定时器 定时触发指定函数
C.run_time("f","1nSecond","2019-10-14 13:20:00","SH")
def f(C):
'''定义定时触发的函数 入参是ContextInfo对象'''
#记录本次调用时间戳
t0 = time.time()
final_dict=A.final_dict
#本次运行时间字符串
now = datetime.now()
now_timestr = now.strftime("%H%M%S")
#跳过非交易时间
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():
#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:
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:
continue
vol = min(vol, position_dict_available[stock])
#获取买一价
print(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,14,-1,vol,'调仓策略',2,msg,C)
A.waiting_dict[stock] = msg
A.all_order_ref_dict[msg] = time.time()
#持仓小于目标持仓 买入
if position_dict[stock]<target_vol:
vol = int((target_vol-position_dict[stock])/100)*100
#获取卖一价
sell_one_price = full_tick[stock]['askPrice'][0]
#卖一价无效时 跳过委托
if not sell_one_price > 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,14,-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]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
# 8.获取融资融券账户可融资买入标的
#coding:gbk
def init(C):
r = get_assure_contract('123456789')
if len(r) == 0:
print('未取到担保明细')
else:
finable = [o.m_strInstrumentID+'.'+o.m_strExchangeID for o in r if o.m_eFinStatus==48]
print('可融资买入标的:', finable)
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
# 9.获取两融账号信息示例
#coding:gbk
def init(C):
account_str = '11800028'
credit_account = query_credit_account(account_str, 1234, C)
def credit_account_callback(C,seq,result):
print('可买担保品资金', result.m_dAssureEnbuyBalance)
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
# 10.直接还款示例
该示例演示使用python进行融资融券账户的还款操作
#coding:gbk
def init(ContextInfo):
# 用passorder函数进行融资融券账号的直接还款操作
money = 10000 #还款金额
#account='123456'
s = '000001.SZ' # 代码填任意股票,占位用
passorder(32, 1101, account, s, 5, 0, money, 2, ContextInfo)
# passorder(75, 1101, account, s, 5, 0, money, 2, ContextInfo) 专项直接还款
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
# 11.双均线实盘示例
与双均线回测示例对应的实盘版本。
#encoding:gbk
import pandas as pd
import numpy as np
import datetime
"""
示例说明:双均线实盘策略,通过计算快慢双均线,在金叉时买入,死叉时做卖出
"""
class a():
pass
A = a() #创建空的类的实例 用来保存委托状态
#ContextInfo对象在盘中每次handlebar调用前都会被深拷贝, 如果调用handlebar的分笔不是k线最后分笔 ContextInfo会被回退到深拷贝的内容 所以ContextInfo不能用来记录快速交易的信号
def init(C):
A.stock= C.stockcode + '.' + C.market #品种为模型交易界面选择品种
A.acct= account #账号为模型交易界面选择账号
A.acct_type= accountType #账号类型为模型交易界面选择账号
A.amount = 10000 #单笔买入金额 触发买入信号后买入指定金额
A.line1=17 #快线周期
A.line2=27 #慢线周期
A.waiting_list = [] #未查到委托列表 存在未查到委托情况暂停后续报单 防止超单
A.buy_code = 23 if A.acct_type == 'STOCK' else 33 #买卖代码 区分股票 与 两融账号
A.sell_code = 24 if A.acct_type == 'STOCK' else 34
#设置股票池 订阅品种行情
C.set_universe([A.stock])
print(f'双均线实盘示例{A.stock} {A.acct} {A.acct_type} 单笔买入金额{A.amount}')
def handlebar(C):
#跳过历史k线
if not C.is_last_bar():
return
now = datetime.datetime.now()
now_time = now.strftime('%H%M%S')
#跳过非交易时间
if now_time < '093000' or now_time > "150000":
return
account = get_trade_detail_data(A.acct, A.acct_type, 'account')
if len(account)==0:
print(f'账号{A.acct} 未登录 请检查')
return
account = account[0]
available_cash = int(account.m_dAvailable)
#如果有未查到委托 查询委托
if A.waiting_list:
found_list = []
orders = get_trade_detail_data(A.acct, A.acct_type, 'order')
for order in orders:
if order.m_strRemark in A.waiting_list:
found_list.append(order.m_strRemark)
A.waiting_list = [i for i in A.waiting_list if i not in found_list]
if A.waiting_list:
print(f"当前有未查到委托 {A.waiting_list} 暂停后续报单")
return
holdings = get_trade_detail_data(A.acct, A.acct_type, 'position')
holdings = {i.m_strInstrumentID + '.' + i.m_strExchangeID : i.m_nCanUseVolume for i in holdings}
#获取行情数据
data = C.get_history_data(max(A.line1, A.line2)+1, '1d', 'close',dividend_type='front_ratio')
close_list = data[A.stock]
if len(close_list) < max(A.line1, A.line2)+1:
print('行情长度不足(新上市或最近有停牌) 跳过运行')
return
pre_line1 = np.mean(close_list[-A.line1-1: -1])
pre_line2 = np.mean(close_list[-A.line2-1: -1])
current_line1 = np.mean(close_list[-A.line1:])
current_line2 = np.mean(close_list[-A.line2:])
#如果快线穿过慢线,则买入委托 当前无持仓 买入
vol = int(A.amount / close_list[-1] / 100) * 100 #买入数量 向下取整到100的整数倍
if A.amount < available_cash and vol >= 100 and A.stock not in holdings and pre_line1 < pre_line2 and current_line1 > current_line2:
#下单开仓 ,参数说明可搜索PY交易函数 passorder
msg = f"双均线实盘 {A.stock} 上穿均线 买入 {vol}股"
passorder(A.buy_code, 1101, A.acct, A.stock, 14, -1, vol, '双均线实盘', 2 , msg, C)
print(msg)
A.waiting_list.append(msg)
#如果快线下穿慢线,则卖出委托
if A.stock in holdings and holdings[A.stock] > 0 and pre_line1 > pre_line2 and current_line1 < current_line2:
msg = f"双均线实盘 {A.stock} 下穿均线 卖出 {holdings[A.stock]}股"
passorder(A.sell_code, 1101, A.acct, A.stock, 14, -1, holdings[A.stock], '双均线实盘', 2 , msg, C)
print(msg)
A.waiting_list.append(msg)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
上次更新: 2023/10/12, 10:46:32