一、引言
" J* v, x* Q( G/ z4 l- [/ x" C) o; m) F0 L7 H3 a4 L0 B- Q7 Y( y
(1)、希望对其他同学有帮助,顺便希望能有个小葫芦,集齐7个娃/ q& `- t7 Z2 P' `: U" O
(2)、担心自己程序有考虑不周到的地方。比如爆仓风险啥的,毕竟个人的经验认知有限。也希望同学有好的想法能交流者发帖共享出来一起改进 (这是主要的,嘻嘻,有同学优化,改进,或者马力强的能分析历史找出比较优的方案)。一起致富,此贴抛砖引玉。
( z& d% a( D1 {4 ]7 m" Z' z q0 U(3)、下图是我大概半个月的收益( 做空usdt,做多busd,利用杠杠,赚两个品种的费率差 ),因为我资金没全开满,也是每天观察,一点点加的,中间也调仓开开平平,持了好几个币,所以平均持仓大概用了一万二,三左右金额。策略比较粗糙,只是一个大概的开单跟查询框架。
6 u3 M1 _4 e; U; V& Q! y效果图+ ] S3 b8 T" W" v" c. L9 I
/ Q9 Q) ~, ]% Y
! W7 k' g. [8 t二、程序设置5 N; y8 y: Z0 v8 b* [! N- \6 ]" A/ {
; s8 P0 s, Y' V
账户先设置成单边模式,和联合保证金模式 ( 联合保证金可以参考上一篇帖子设置 )( V% H' V" O# _6 h, z% m8 @
(1)、在【utils】文件夹下的【Config.py】里设置账号和钉钉账号,这里钉钉账号我程序里是有两个,大家也可以都填一样的,因为我有专门个钉钉监控所有策略的异常
; t9 J$ Q) \+ z$ t: R5 P0 Y( ?7 q+ i3 W2 M+ K; m. c
3 [" @- j: d a" q7 U# e8 f
(2)、在【实盘下单】文件夹里的【config.py】配置策略相关参数,【实盘下单】里的所有py程序参数都在这一个文件里配置,参数 "set_lever"是要自己查询两个本位的允许最大杠杠,比如BTCUSDT最大刚刚是50倍,BTCBUSD杠杆是20倍,那就填20,后面程序运行会自动设置/ D Y2 w2 c- ]" |' r: U
2 M7 m4 N: v9 }% h. k( u" l
3 z" Y& s' f; m( a( c W
(3) 、【1_实盘下单.py】这里一开始会显示相关的数据,觉得ok了,在最下方输入yes,才会开始开单,程序有一个地方要注意,右上角有显示这个品种最大的持仓价值,我这里没做处理,目前是假设跑BTCUSDT,BTCBUSD,假设BTCUSDT开单了,接着开BTCUSD超过了允许值开不出来,然后程序会结束,这时候需要手动在把BTCUSDT多开的部分平掉。+ X0 ]+ Q b# ]( C& n
1 ^$ W1 }# E9 }; W2 {% r( H

2 m! i) l- S, W. Z(4)、【3_实盘监控.py】开单后主要就是开着这个程序,循环监控,这里功能,每到 00:00、8:00、16:00 会显示相关信息,并且如果ADL到达你设置的报警级别,或者仓位不平衡会隔10秒提示,并且仓位不平衡的时候,也会把多出来的一边多出来的部分给平了,目前是这样处理的。okex船队的方法是平掉百分20再开,我担心行情极端的时候会出现平开,又ADL又平开的情况,干脆直接平掉多出来的部分,这里我是一次性平掉的,等到行情稳定了再手动执行程序补。而且具我观察币安的这些合约ALD满级了也很少触发平仓,如果主动平仓再开,多几次成本就高了,个人想法。* t+ I. z9 g. `5 R' Q
( `6 Q" I; t7 [4 j
' M0 K6 I. C Z. d& l' B
# ~; u5 n5 x, ?) \- @5 n
' U: D Q" w1 L# K$ I) [2 }& u- ]' o% {' I7 H2 q& x
; N+ ~% q0 A7 ^" t/ X
(5)还有两个小程序【5_保证金查询.py】,【6_收益查询.py】查看账户情况,用于策略的参考
* B% }9 a$ U* Z. y9 K三、主要代码
M5 [7 n& r' w7 P4 a L0 f! X
4 i3 i7 j+ N8 T+ m6 S* U下单代码
3 m% S" D5 S; h3 K6 |# S0 Y+ Fimport utils.Config as Cf
1 w% y+ K& j+ N7 n$ simport utils.gateway.binance_http as ins7 o( o3 o6 G4 ~9 f
import time" D% u/ C0 X# [* w$ S1 A; j
import program.usd_busd永续套利.实盘下单.config as cf- _6 `$ x+ u' K1 @! O$ n
import math
; O9 a7 e4 Q$ R, m1 H4 ~5 k" h# ===== 初始化. x0 R7 U, }- O" r" Z
# 创建币安api
0 a+ j: N, V; e9 y% q, R# [account = Cf.account[cf.username]
4 p8 K( q; k7 c4 ?% `ins = ins.BinanceHttp(key = account['key_0'] ,secret=account['secret_0'] )
, k$ H6 a6 s6 y9 u- N4 p1 h7 ]* T' ~" A- r6 o; `; S& Y$ U
# 参数设置. T% E6 n+ Y+ F" U6 {
coin = cf.coin' J' ] Z% b* b! P p7 e; l% W1 | a) W
money = cf.money # usdt" T3 g2 R' M4 i' F1 P8 |
set_lever = cf.set_lever # 设置杠杆- e& C% a% p6 i# V5 ?: j
symbol_1 = cf.symbol_1 # 做空
+ h" I9 b# D# F H) ^! {* \symbol_2 = cf.symbol_2 # 做多
7 Z( u! s, M/ }6 P/ x4 e1 [, H* Jexecute_amount = cf.execute_amount # 每次建仓usdt的数量。如果是btc的话,得是100的整数倍。其他币种得是10的整数倍。每次数量不要太多,太多会造成价格波动。建议数量在1000-3000之5 Y/ u/ j4 J% n( Q9 {4 Y+ x
max_execute_num = math.floor(money*set_lever/execute_amount/2) # 最大建仓次数,需要向下取整这里要改。建仓这些次数之后程序就会停止。, K, C: e1 b* l6 o+ c: P6 s8 E
7 ~: j- O; V! h" Aprint("开仓次数 : {}".format(max_execute_num))
x) r1 B, ]5 w: z: B( vprint("设置最大杠杆 : ")
, C7 `/ k$ S# P! t" ?print(ins.u_set_leverage(symbol_1,set_lever))
; H$ B# R) _7 D; h7 w" ]print(ins.u_set_leverage(symbol_2,set_lever))
: m$ w H1 u$ C# v0 xprint()
1 c& z( s( d4 B# T9 r. ^9 K% z) p( X/ }6 }6 K, \; T6 V+ H( ?) D
print("最新资金费率 : ")
( C, z( ~1 b( O. J v+ c2 Tprint(symbol_1 + ": "+ins.u_premiumIndex(symbol_1)["lastFundingRate"])
3 B$ @3 w# Q1 N3 Sprint(symbol_2 + ": "+ins.u_premiumIndex(symbol_2)["lastFundingRate"])
3 |9 Z; o7 m- h& eprint()
$ P4 @& t& f/ P' f0 g# T- e7 R v" W t* C0 r# x9 G6 Y# P
print("合约信息 : 品种 ,价格精度,下单量精度,最小下单u")" n! _5 s; E n3 ^: X9 @3 L
symbol_exchange_info = [[i['symbol'],. Q% j0 A0 N$ R, f, k
int(i['filters'][0]['tickSize'][::-1].split("1")[1].find('.')) + 1,9 H, T7 f0 L1 E4 g6 W$ [6 O
int(i["filters"][2]["minQty"][::-1].split("1")[1].find('.')) + 1,# h7 B, b( H1 e9 y9 H. a
i["filters"][5]["notional"]]
' J8 F: O9 Z' ?0 { for i in ins.u_exchange_info()["symbols"] if i['symbol'] in [symbol_1,symbol_2]]
: ]) U- }9 L8 ~print(symbol_exchange_info,'\n')# 价格下单精度,价格最小下单量精度,最小下单金额
" e) C- ?! d+ q/ j5 Y- Qprint()
2 B7 h T, q- i2 h* f3 q' I
4 F* a) n" Y, O- Q) _$ |swap_buy_price_1 = float(ins.u_depth(symbol_1, limit=5)['bids'][0][0]) # 做空5 m z3 b) [) }
swap_sell_price_1 = float(ins.u_depth(symbol_2, limit=5)['asks'][0][0]) # 做多
: c3 m8 W/ P3 e6 G5 M+ ?+ y7 Pprint("{} bids {} , {} asks {} , 价差 {}".format(symbol_1,swap_buy_price_1,symbol_2,swap_sell_price_1,round(swap_buy_price_1/swap_sell_price_1-1,5)))
6 W/ Y1 ^/ V! H# l, L9 e. ^
. B& X/ I# X8 {print()
$ F9 l0 G* o v- G, i8 Erun = input("注意控制风险,是否继续 y/x :")* |& U1 @% C) }8 ]/ s
* y) z. l. x& x* A; B( j6 Dif run.lower() == "x":
3 g* Q1 f2 { d) O) G& m2 G print('*' * 20, '程序退出', '*' * 20, '\n')+ d) {, e. q9 V4 p. e$ A% ^% t0 O* h
exit()1 g. K* |/ p! g* P
% A% d- q* c5 ^9 m: F5 U7 Velif run.lower() == "y":
' `2 D: s( M- [' `. p print('*' * 20, '【开始运行】', '*' * 20, '\n')
7 B: ^+ m; z- M8 O1 [, m3 V* ^: S4 @$ I7 F5 ~
execute_num = 0
6 i4 d5 b! R, F* y5 {1 L! W! _ while True:4 Y$ H; J! y/ J2 v; R$ N
' Q4 [3 F9 v. l
+ b7 I" z: {4 M* H) H! f
execute_num+=1
. G& Y7 z: @! V! a print("*"*50,"【执行{}次】".format(execute_num),"*"*50)
) E; A; t. ]5 r+ a; i1 `
+ X2 \ a5 M" E5 y. ~7 E+ q swap_buy_price_1 = float(ins.u_depth(symbol_1, limit=5)['bids'][0][0])) R+ [! i V; a3 Z, L
swap_sell_price_1 = float(ins.u_depth(symbol_2, limit=5)['asks'][0][0])/ p4 }" Q% i5 f4 b0 r9 z
buy_price_1 = round(swap_buy_price_1*0.98,symbol_exchange_info[0][1]). p# t- A( x c: z' O, G! {
sell_price_1 = round(swap_sell_price_1*1.02,symbol_exchange_info[1][1])
2 U" P0 s6 A0 J- x6 x$ [; T' d- Z* Z. }. k' t
if buy_price_1 > sell_price_1:) y: @6 r# n& E# \, x( W
lot = round(execute_amount/buy_price_1,symbol_exchange_info[0][2]), |1 j4 t: [( L
else:9 k& v1 v5 ]0 P. Q6 o8 X5 ~- Q; T3 H
lot = round(execute_amount/sell_price_1,symbol_exchange_info[1][2])' l! w2 w) j, \" P( B9 F; Q" t
4 W5 a+ K; ~: s7 `) B
r = swap_buy_price_1 / swap_sell_price_1 - 1
^/ o# [7 E% X) F print( "{} 买一价 {} ,做空 {} , 下单量 {}".format(symbol_1,swap_buy_price_1,buy_price_1,lot))# v) w. N+ j: ]
print( "{} 卖一价 {} ,做多 {} , 下单量 {}".format(symbol_2,swap_sell_price_1,sell_price_1,lot)); m6 k$ U8 y2 C# L3 f" D9 ` C0 D- Q
x# b3 t& C/ r/ _& |! ]- f9 s
print("开始下单 : "), R" J; j! J Y- ?; |* |. z. q
symbol_1_order_info = ins.u_order_send(symbol_1,"SELL","LIMIT",quantity = lot ,price = buy_price_1,timeIn_force="GTC")
$ C, O5 x9 e# S }% f8 ^& W symbol_2_order_info = ins.u_order_send(symbol_2, "BUY", "LIMIT", quantity=lot, price=sell_price_1,timeIn_force="GTC"); Q/ s8 R3 _0 I( ]9 u2 a0 F
print(symbol_1_order_info)3 l1 W6 s+ K5 Q7 H4 ^5 @4 ^ \
print(symbol_2_order_info); P3 F c c7 G& X: b! L m
* f/ p2 I0 C `" m% q& J; \/ p if ("code" in symbol_1_order_info) | ("code" in symbol_2_order_info):
$ l7 O+ y- p: D1 M9 Y5 n print("下单出错停止")
$ ]( v) ^+ ^# { break/ e5 i7 o8 N* Q4 Z0 P. b6 |6 A# o
. V# Q% A, t$ W
time.sleep(5)
; M2 u: m( ` F4 J( l. a print()
+ K- u/ a. ^; f; U. C+ Y0 @
}# @: r4 G# B$ b if execute_num >= max_execute_num:$ s! h; [/ i/ L- l
print('达到最大下单次数,完成建仓计划,退出程序')
$ ?& a: M5 K1 H5 k* n9 I Break监控代码 g j# t4 `0 E+ P
print("\n"+text)
1 h a/ [3 B% U6 c5 `8 [ text = " 警报! adl风险 : " + "\n" + str(adl) + "\n"
8 V- @' S5 n5 X! X3 x dingtalk_alert.send_dingding_msg(alert_text + text)
8 {9 z) F( ^/ g: X/ n6 v) e& C2 o4 ^* t, [# X/ N5 F5 H- {
# 2.检测手数是否平衡,异常报警,平掉多余手数
# H3 n$ `6 y! h3 ?) ^ check_pos = check.pos()# x4 s# b" N f/ M
df_pos = check_pos[0] # 原始仓位
4 S1 r v7 e$ x, W* V! z. \ coin_pos = check_pos[1] # 多空抵消后的币的仓位: d1 r& u9 e4 E/ k# ?: R
$ U a( Q) x# L4 n* F% B1 s' a
coin_pos = coin_pos[coin_pos['open_pos'] != 0]4 p. ]3 i/ w: Q$ Q4 h
if len(coin_pos) > 0:
% j+ {8 W: G& A6 [9 y* U4 Y, m
( h5 C, A. T7 S4 g: a/ A5 U symbol_order_info = check.close_pos(coin_pos)
/ W+ W, A R6 B: h4 x1 c# v% @6 h% O- F
text = " 警报!仓位异常 : "+"\n"+str(coin_pos.to_markdown())+"\n"+"平仓信息 : " +"\n"+str(symbol_order_info)# \. P3 p+ T5 ~- @; i+ \3 _
print(text)9 f# @+ x9 N; l/ h
text = " 警报!仓位异常 : "+"\n"+str(coin_pos)+"\n"+"平仓信息 : " +"\n\n"+str(symbol_order_info)
5 K' S, z7 z! g* G5 M( b dingtalk_alert.send_dingding_msg(alert_text + text + str(symbol_order_info))* A, `) j. t# g: \6 M# a: t
, `7 N2 m0 G6 t0 l4 H5 N6 n* Y% [ # 3.账户风险,检测资金流水,本期到期资金费率
$ M& W/ e3 ~3 ]( g+ _9 @) N5 I now_time = pd.to_datetime(now_time)6 o2 [# Q" N8 A
account_risk = check.account_risk()
$ C" a& f7 j* F* o3 w maint_margin = account_risk[0]
6 L6 J, Y5 R; W3 M7 R" l margin_balance = account_risk[1]
: x# X8 \( `) z% q7 C+ | q1 x risk_rate = round(float(account_risk[2] * 100),2)
7 t% E; e1 A1 I" K0 W1 j6 D& l. ?, W
if risk_rate > set_risk_rate:
1 L2 k' F& h5 b7 P" b1 ] text = " 警报!账户风险率 : {}%".format(risk_rate)
! k, p* V- {0 ~ p print(text)
7 \: Y& @( Z( f4 Z C F1 O" d% M' V dingtalk_alert.send_dingding_msg(alert_text +text)
3 p( v9 D. f6 Y, X H: [6 ~, b5 l( y2 r) p7 K0 N9 O! j
# 资金费率发生后一分钟显示数据' c0 c o" }; ?# F
if now_time.hour % 8 == 0 and now_time.minute == 1:
% C/ T% f6 k. y
0 D4 n# A) O! D* a* r( L2 j text = "\n"+"【账户风险】 :"+"\n"+\ i; c4 g8 k9 a: i E' F
"维持保证金 : {}USD".format(round(maint_margin,2))+"\n"+\# F5 n$ I- r2 q* n3 Z# z) S
"账户权益 : {}USD".format(round(margin_balance,2))+"\n"+\
) C; T- L- y" J8 h9 n- G: N1 S "账户风险率 : {}%".format(risk_rate)+"\n"+" "+"\n"+\! y5 }+ U" e2 N7 l4 e, N" X
"【资金费率差】 :" +"\n"+str(check.last_funding_rate())+"\n"+" "+"\n"+\
! k0 f3 l2 _; D9 ?6 M! ]) @# r "【币种收益】 : "+"\n"+str(check.income()) + '\n'+" "
! S0 ~3 a; Z7 D7 Z; t2 @! m8 Z, |$ N0 }& Q# v
dingtalk.send_dingding_msg(text)# @7 L4 ^) _5 h: m3 {
print(text)
. ^ A: h+ k& T0 Z. C& w* `, D7 J2 v5 R+ L# T
# 休眠60秒这样就只会报警一次了
& P! L: P. e5 ?/ T3 j time.sleep(60); S. _7 \2 G& \ P
; K5 k9 e% _0 P4 J print()' z" W9 R! ] n" r" ^4 @, f2 A
time.sleep(sleeptime)( s8 J3 z( {9 u+ V" v
* q& Y5 J6 P w3 o
+ M" S/ W$ J/ w0 e7 @! T3 ~% t) Dif __name__ == '__main__':# A0 `9 [+ {" x" d% F l& b1 c
) }" a! z7 j( i! p/ A
9 ]" {1 y) D7 W. a6 D% {+ u while True:
4 y; a7 g/ {5 a$ `+ n& J
0 u6 a& k' M% F( V try:" h- @% C6 o4 o/ X' c
main(ins,dingtalk_alert,dingtalk,alert_text)
/ j9 ]* i% g4 R( j% ]1 _ except Exception as e:6 ?% I" e+ p6 o4 V/ p
print("程序报错")) q. f5 h/ {0 S3 h R3 i
dingtalk_alert.send_dingding_msg(alert_text + "程序报错 :" + str(e))
% M, t5 C- w6 ` time.sleep(10)
9 @; S5 v% ?6 Z6 J" \8 m2 t+ T三、其他
7 d+ N: P9 U! b# O: m7 F; [ X
- }+ p3 q, r& b' H! l我这里没写平仓,大家开单反过来写下就行了,另外跑的时间很短,这几天大部分币资金费率差开始变成负的了( 策略是否要加入自动平仓功能,比如平均多少天的资金费率转负了平仓,转正了再开?),亏了两天,具体策略的情况还需要长期观察。另外usdt之前暴雷过,如果再次发生暴雷,或者busd/usdt价格偏离很大,会发生爆仓。! k* m& j. Y8 q
先这样吧,觉得有帮助的话多多点赞2 G3 a! l1 L4 Y$ f/ ` S/ [
代码附件:
5 V2 d1 c; A( \' U
* f; S7 Q+ q7 p. B8 g- M
# A& Z! T6 S8 O: k! Z: ^
|