币安合约网格策略实盘框架v1【python数字货币量化_21精华帖_策略第29篇】

[复制链接]
查看7181 | 回复0 | 2023-8-5 23:49:19 | 显示全部楼层 |阅读模式
网格策略的逻辑很简洁,由于交易频繁,它可能是一个有利于刷返佣的策略,最近翻阅资料尝试将基于币安交易所的合约网格实盘代码敲了出来,供大家参考
6 ?4 j, U! k3 c- |网格策略的逻辑
& i3 K* o2 F( j
9 I0 @3 G& i1 d网格策略的逻辑很简单:低买高卖。# ~6 n7 z& M7 c; h& \
假设某个标的目前1000元,那么我在999元处挂个买单,1001元处挂个卖单,价格波动一下:从1000元-->999元-->1001元,那么我就赚到了2块钱。6 u$ O7 [1 {8 S
如果我挂单频率够高,价格也如我所愿地来回波动,那么我就不断地能赚到这2块钱。% z7 z5 @- s4 }  ?* W' N- ^$ I+ N; C
当然,任何策略都有风险,网格策略的风险也很明显:如果遇到单边大行情,比如价格一路下跌到900元,我999元挂的买单成交后,价格再也没有涨上来过,我就被套了。
* f1 o5 _2 B5 ?; e- J3 y/ J基于币安合约api实现的网格实盘代码$ R. T& @9 [! p

/ d' [4 T  S0 |每个人可能对网格策略的理解不一样,我描述一下我的实现逻辑:3 \  O5 i# G. b6 L9 d8 Z; n! V
1. 获取某个标的当前的价格,并在当前价格下方x%处,挂一个买单,在当前价格上方x%处,挂一个卖单(价差是2*x%);1 [: R) X. i: |; l0 h$ E
2. 等待某个挂单成交后,同上一步一样,在成交价上下方x%处挂卖单和买单;
: q7 t5 K; `9 k7 s* f+ s3. 价格不断波动,程序不断收割这个价差(2*x%)。
/ ~( I- D: D, P' P$ i# H* J! \2 H为实现以上逻辑,有几点需要注意:) R, M# M6 V$ f+ ]7 a; `
· 币安合约挂单成交的手续费为0.02%,所以理论上x应该>0.02%,否则没有利润空间;
" ^+ @% T: s* A& j% f+ L( q1 c· 价格不断波动,程序会不断挂单,很可能出现同一个价位,有多个挂单,我的做法是撤销同价位的挂单,保证每个价位只有一个挂单;# w+ I2 m  o  N0 h
· 为避免亏损,单个方向的挂单量不得超过max_orders(我个人设为3);
5 d5 O5 Z8 t; J* c4 ]7 R6 C) {, h- C· 即使设定了最大挂单量,还是有较大风险,因为虽然挂单量有限制,但是不断下跌就会不断买(只是买完后再挂买单的数量不会太多),所以我设了网格上下限,比如当前价格为20u,我设定网格范围为[18,22],一旦价格波动太大,不在这个[18,22]的范围内,程序就撤单不再交易了,等待价格回到网内再继续执行网格逻辑(注意,只是撤单,现有仓位不平,等待解套)。3 [  E2 Z% x8 H( A1 s$ R$ w
· 我是用上一次的成交价来计算新的挂单价格的:最新挂单价 = 上一次成交价 +- x%,如果网格执行周期比较长(程序默认为30s执行一次),价格波动又较大时,我的挂单可能会变成吃单,手续费会增加,所以在计算下单价格的时候,我会判断一下上一次的成交价与当前盘口的价格,避免maker变taker。3 X- d0 H4 W- ]7 {; {' q
程序的配置文件config.ini:) J4 N2 V  p, K2 U* f

! _" S% _. ~) O3 F) w( A/ y# p4 z5 h1 B% V# S4 c) ]7 ^
代码主要逻辑:
  w; c$ I+ ]4 Ndef grid(exchange, symbol, gap_percent, quantity, pricePrecision, max_orders, grid_up, grid_down, buy_orders, sell_orders):5 i% N: i3 @; L2 b8 X. q

. W% P" {/ J& s! _    # 用于存放已在交易所挂单的订单信息
# t  y; o; @$ I    buy_orders = buy_orders0 D8 t$ H# w: E& `# L. b
    sell_orders = sell_orders
$ ^5 m% c* c* T( S" P& q' n7 Y& S7 H% d7 {' c0 d
    # 获取当前买一卖一价
3 U% l; G# s) B0 d9 j; U! b, z# F    bid_price, ask_price = get_bid_ask_price(exchange, symbol)
# h6 Q4 W- ~2 g3 n    print(f'{datetime.now().strftime("%Y-%m-%d %H:%M:%S")} 当前ask_price: {ask_price} bid_price: {bid_price}')" r- {0 f& p, C! b

! G8 t9 M6 n  X8 }2 |$ [9 \* R    # 判断是否还在网内,如果破网则撤单,不执行网格逻辑,直到价格回到网内  j8 I# ^# I4 R/ `# ]0 Z6 v
    if bid_price > grid_up or ask_price < grid_down:
2 Z" F/ s$ Q! a; G. I+ w$ |  c        / O& a" }  t" C4 T, A) D( g
        # 撤掉目前所有挂单" ?0 O' y9 u2 \4 w3 L- R
        cancel_open_orders(exchange, symbol)( w" K$ O2 M3 i
        buy_orders = []& h& S! P* u  h$ H7 k- g( I
        sell_orders = []
6 P# U( T" \9 X        print(&#39;破网!已撤销所有挂单,等待价格回归至网内继续交易。&#39;)
- L+ {! l- D* s/ l* L% K& N4 Y" L/ u# d        print(f&#39;grid_up: {grid_up}      grid_down: {grid_down}&#39;)' k- y- B1 h* i
        print(f&#39;ask_price: {ask_price}  bid_price: {bid_price}&#39;)1 r' r" [: r/ F* m4 L& @, C% Q+ J
: |4 M) C, k1 O
        return buy_orders, sell_orders0 J( z7 p1 M  r
& b7 F9 J+ B1 T1 {* b4 K
    buy_orders.sort(key=lambda x: float(x[&#39;price&#39;]), reverse=True) # 按价格高到底排序(高价更容易成交)
0 |" l: D2 ]& [+ P2 J" X/ ?    sell_orders.sort(key=lambda x: float(x[&#39;price&#39;]), reverse=False) # 按价格低到高排序(低价更容易成交)
, R% U) ^& v5 L* a
! H1 V: P3 Y- J+ G2 N. @8 F    # 若buy_orders已记录有买单,逐个检查是否有最新成交: f) I% V* A/ J% p( X
    for buy_order_info in buy_orders:
: `6 ~0 X: M' M7 Y+ G! A        
$ z# l( ]/ w6 |/ A8 H5 J9 N& Z7 }        # 获取该订单当前最新状态  [+ d# `/ V7 `& _" e
        order_info = get_order_info(exchange, symbol, buy_order_info.get(&#39;orderId&#39;))1 B! y8 w9 R( A1 c. ?/ m
        
  @8 u' z. \4 S5 I1 }        # 若订单当下已成交
; f7 [' |) n6 U        if order_info.get(&#39;status&#39;) == &#39;FILLED&#39;:7 B( ?# J) d2 s  ?" |8 A9 G
            final_price = float(order_info.get(&#39;price&#39;))
; i* o6 D) |6 h2 S; k            print(f&#39;{datetime.now().strftime(&#34;%Y-%m-%d %H:%M:%S&#34;)} {symbol}买单成交了,买单价为{final_price}&#39;)
' ~, F4 G3 K; y9 E) k  T$ G% k% {
" D0 u$ ~6 |. d/ N* B4 G9 e# W& Y            # 成交后,从buy_orders中删除! O; n3 u" R9 L5 M
            # 注意remove的是buy_order_info而不是order_info
5 ?% v; J% [  M            # order_info是成交后的buy_order_info
- a, f$ s% p9 L            buy_orders.remove(buy_order_info)
! `' ]- R0 Q( n+ H  o2 {, E' Q0 g2 A- U. ~; e& j6 a
            # 买单成交,挂上一格的卖单& S3 {, Z9 d8 g9 y2 Q1 Z
            sell_price = final_price * (1 + gap_percent)
* B3 K& b  k6 E) t& y& F/ W            sell_price = round(sell_price, pricePrecision) # 处理价格精度
5 l% g& U- n, ?6 m; r8 [* L' d" a$ Q, R6 p0 E6 Z6 {
            # 防止新计算的sell_price比当前ask低
: s5 t! ~0 n) R/ @  k4 K  m            # (如果网格运行时间间隔较长会出现该情况,因为新挂单价是由上一个成交价决定的,从成交到现在价格可能已经大幅波动了)
% d: K" @9 S# _5 H: y            if sell_price < ask_price:
$ i1 w) t0 Q/ e  w+ G1 }                # 如果新计算的sell_price比当前ask低,以ask挂卖单,防止挂单变吃单
1 a) ]. _; Z1 ?9 K1 ~7 r                sell_price = round(ask_price, pricePrecision)
  q0 o  j5 y0 |. `2 ?; q9 Z( R
* _3 l( |. K. `6 Q+ }& j            # 挂新卖单& z  a; j4 }$ o% {+ I" |. R
            new_sell_order_info = place_order(exchange, symbol, &#39;SELL&#39;, quantity, sell_price)
3 S( K0 Q, v9 `# \            # 挂单成功后3 R7 X) |2 H  o, `
            if new_sell_order_info.get(&#39;orderId&#39;):
1 }% M5 s+ i* ^- p& V8 u6 l                # print(f&#39;{datetime.now().strftime(&#34;%Y-%m-%d %H:%M:%S&#34;)} 买单成交,根据成交价挂上一格卖单: {new_sell_order_info.get(&#34;symbol&#34;)} | price: {new_sell_order_info.get(&#34;price&#34;)} | qty: {new_sell_order_info.get(&#34;origQty&#34;)} | orderId: {new_sell_order_info.get(&#34;orderId&#34;)}&#39;)
) M+ ?% H$ E$ R# F7 L                print_order(new_sell_order_info, &#39;买单成交,根据成交价挂上一格卖单&#39;)2 H* u7 A# q( ^& _& C. F' `& T. l+ I
                # 新的卖单加入到sell_orders中, Y. r! y" X6 M% q% Q" N$ H
                sell_orders.append(new_sell_order_info)7 p/ Z. Z! H2 }! h, O

' @0 k# h; K# Q6 p$ R2 M$ _4 v. J9 |/ `8 P
            # 买单成交,挂下一格的买单(挂更便宜的买单)
4 t1 V1 P; y) |( d8 l6 f            buy_price = final_price * (1 - gap_percent)% e; n5 d; J& T; {5 y/ ^. d& h
            buy_price = round(buy_price, pricePrecision) # 处理价格精度1 e9 s  \4 k$ e- _, f  l# |
! `& Y9 {  g2 v7 n  V
            # 防止新计算的buy_price比当前bid高
" t* ~5 D) A! t# l  j            # (如果网格运行时间间隔较长会出现该情况,因为新挂单价是由上一个成交价决定的,从成交到现在价格可能已经大幅波动了)
& K6 d/ m! W1 U  T+ I            if buy_price < bid_price:4 R" X' X, ]" _  {
                # 如果新计算的buy_price比当前bid高,以bid挂买单,防止挂单变吃单
0 Z) b, e8 O. s& V                sell_price = round(ask_price, pricePrecision)
9 J' P/ b7 m. d) O: o" V0 k4 C$ {. K4 Y9 G3 G* {: j1 t7 x' D
            # 挂新买单2 h; c" {: Y: e/ u, J
            new_buy_order_info = place_order(exchange, symbol, &#39;BUY&#39;, quantity, buy_price)
$ a/ J6 B  u- w            # 挂单成功后
; c+ L1 |# x8 l4 H1 N            if new_buy_order_info.get(&#39;orderId&#39;):7 t9 m/ G5 h, A9 J1 F
                # print(f&#39;{datetime.now().strftime(&#34;%Y-%m-%d %H:%M:%S&#34;)} 买单成交,根据成交价挂下一格买单: {new_buy_order_info.get(&#34;symbol&#34;)} | price: {new_buy_order_info.get(&#34;price&#34;)} | qty: {new_buy_order_info.get(&#34;origQty&#34;)} | orderId: {new_buy_order_info.get(&#34;orderId&#34;)}&#39;)
4 a0 ~0 F! d5 s! k1 \' N                print_order(new_buy_order_info, &#39;买单成交,根据成交价挂下一格买单&#39;)/ x$ [0 `! Q* r/ d' Q* E
                # 新的卖单加入到sell_orders中
8 |4 G, t* @4 q5 u                buy_orders.append(new_buy_order_info)7 ~1 n8 H! |# u! g6 f
) N1 z0 ]& u7 A' [! ^
        elif order_info.get(&#39;status&#39;) == &#39;CANCELED&#39;:: j" f4 a4 T5 U9 f; v9 I, P
            # 订单被取消,从buy_orders中删除
+ M8 x  r, q! a3 d            buy_orders.remove(buy_order_info), o( H0 G1 ?: M6 T% x6 a; b; H
        
4 s5 l( {. J' d  z( A( m        elif order_info.get(&#39;status&#39;) == &#39;NEW&#39;:4 G1 @+ ~" S0 p" ~5 P9 o$ Z
            print(f&#39;{datetime.now().strftime(&#34;%Y-%m-%d %H:%M:%S&#34;)} 买单尚未成交,挂单价{order_info.get(&#34;price&#34;)}&#39;)
; A. Q  H. O! S, a3 e- T7 u( D" f
6 a2 S' u. k. E        else:
) Y# n1 `- P6 g1 l1 O% ]            print(f&#39;{datetime.now().strftime(&#34;%Y-%m-%d %H:%M:%S&#34;)} 买单当前状态为{order_info.get(&#34;status&#34;)}&#39;)1 P1 R& b; J9 T/ S9 M6 @
( j! y+ F0 _" l& O0 Q% g( l& ^

. O2 l4 y9 o2 E/ ?. r4 ~" l
  N- @5 R1 O; r. R; a& g% |, Z" \0 z( I# ]. |0 X
    # 若sell_orders已记录有卖单,逐个检查是否有最新成交' H& Q% E! q$ }/ D/ `7 k0 I$ ?
    for sell_order_info in sell_orders:
. O6 ?3 M# [+ ^- `7 A        - n& Y8 Y2 m/ Y2 b2 S9 G
        # 获取该订单当前最新状态
$ Y0 C4 l  `' g+ o& }* H        order_info = get_order_info(exchange, symbol, sell_order_info.get(&#39;orderId&#39;))
% `% a6 k+ Y7 o; a7 a6 q        ' X( ?, s# F; w6 W3 B3 M* n3 ]
        # 若订单当下已成交  a! c0 ~, X4 ~8 r, Y3 M) b
        if order_info.get(&#39;status&#39;) == &#39;FILLED&#39;:
% q) B1 F$ \, y: g) ]1 X            final_price = float(order_info.get(&#39;price&#39;))0 A) k" ]" {3 u1 k1 r
            print(f&#39;{datetime.now().strftime(&#34;%Y-%m-%d %H:%M:%S&#34;)} {symbol}卖单成交了,卖单价为{final_price}&#39;)4 _8 B+ I) G- v0 {) N
  E8 L" b4 i- `& ?- }' y
            # 成交后,从buy_orders中删除9 b# C; C7 R/ y9 \% O
            # 注意remove的是sell_order_info不是order_info9 |/ B1 ^$ d9 L. u; g
            # order_info是成交后的sell_order_info- O! ?: c% [( o# F
            sell_orders.remove(sell_order_info)
9 b: Q# o8 f5 k, I  K) a
* H! r' S; l6 G6 x* d  q            # 卖单成交,挂下一格的买单
. [* ?4 ~* `$ C8 V6 Y            buy_price = final_price * (1 - gap_percent)2 F1 w$ Q; t, ~0 }
            buy_price = round(buy_price, pricePrecision) # 处理价格精度0 D0 R5 S  i2 ?9 K' q" s3 b5 H" w
: x3 R( x: c5 H1 @
            # 防止新计算的buy_price比当前bid高
. `, t, C2 r' p6 V  k            #(如果网格运行时间间隔较长会出现该情况,因为新挂单价是由上一个成交价决定的,从成交到现在价格可能已经大幅波动了); e. L) Q  F7 s! a2 I0 ^/ m5 y) Z
            if buy_price < bid_price:
% {/ O; R9 {6 @. F                # 如果新计算的buy_price比当前bid高,以bid挂买单,防止挂单变吃单  t: `7 Q  _/ f  n9 f- o% Z
                sell_price = round(ask_price, pricePrecision)
' M' Y0 k- T( ~5 @2 m8 V1 c
0 [7 x# h( C, {5 i4 A  z3 R  o            # 挂新买单) f; m: I- L/ Z7 l0 E& |8 d$ b
            new_buy_order_info = place_order(exchange, symbol, &#39;BUY&#39;, quantity, buy_price)
. d* [; z8 f/ h6 A) a: r! Q  O: U            # 挂单成功后6 s. j2 [) [" U0 l* y5 l4 ?
            if new_buy_order_info.get(&#39;orderId&#39;):
) J8 Q, u* x1 S/ _; ?  G6 u& F  O                # print(f&#39;{datetime.now().strftime(&#34;%Y-%m-%d %H:%M:%S&#34;)} 卖单成交,根据成交价挂下一格买单: {new_buy_order_info.get(&#34;symbol&#34;)} | price: {new_buy_order_info.get(&#34;price&#34;)} | qty: {new_buy_order_info.get(&#34;origQty&#34;)} | orderId: {new_buy_order_info.get(&#34;orderId&#34;)}&#39;)
  f) k# y$ L+ D1 I0 ~                print_order(new_buy_order_info, &#39;卖单成交,根据成交价挂下一格买单&#39;)' [1 h+ I+ C% Q  {
                # 新的买单加入到buy_orders中7 {3 p9 n1 v0 q: B/ _/ l: K* f2 s: n
                buy_orders.append(new_buy_order_info)
% g8 [. {# V! E5 a7 X2 w$ c4 P: R
/ V% ^% W2 J4 J7 {+ N4 p! M. u) k: v# U" a" l' t8 p. p" U2 U
            # 卖单成交,挂上一格的卖单(挂更高价的卖单)& Y3 s7 [! M" J
            sell_price = final_price * (1 + gap_percent)
2 s6 J+ ]" v0 ^( y            sell_price = round(sell_price, pricePrecision) # 处理价格精度8 F. R% ^8 w9 @/ q. u. d
+ e1 b2 e. L& d7 {% i
            # 防止新计算的sell_price比当前ask低
7 c  }2 f% R5 E: Y            # (如果网格运行时间间隔较长会出现该情况,因为新挂单价是由上一个成交价决定的,从成交到现在价格可能已经大幅波动了)
; p: B" y' N# k7 ]( U( Z            if sell_price < ask_price:
2 }# f* g. \4 _" s/ V( t                # 如果新计算的sell_price比当前ask低,以ask挂卖单,防止挂单变吃单1 Z) s5 i3 x# O) f, a0 k
                sell_price = round(ask_price, pricePrecision), V: l1 |% A% Z2 t$ p! w
7 g- d5 c0 D+ d, z) G/ C8 L6 M& U
            # 挂新买单( c8 S: `+ l2 [- a. J
            new_sell_order_info = place_order(exchange, symbol, &#39;SELL&#39;, quantity, sell_price)+ r" m. A+ V3 f% C9 X2 C% ?
            # 挂单成功后) v. m$ j3 _+ W  r6 ^2 r, W% ^( N
            if new_sell_order_info.get(&#39;orderId&#39;):
) g  R' O& E3 D* p                # print(f&#39;{datetime.now().strftime(&#34;%Y-%m-%d %H:%M:%S&#34;)} 卖单成交,根据成交价挂上一格卖单: {new_sell_order_info.get(&#34;symbol&#34;)} | price: {new_sell_order_info.get(&#34;price&#34;)} | qty: {new_sell_order_info.get(&#34;origQty&#34;)} | orderId: {new_sell_order_info.get(&#34;orderId&#34;)}&#39;)
! c3 a! m1 ~2 s" W: ~. T- t8 C3 [, m                print_order(new_sell_order_info, &#39;卖单成交,根据成交价挂上一格卖单&#39;)+ ]" ^* ?9 Q. g: o9 L; l' r
                # 新的卖单加入到sell_orders中9 A% r$ s# }. ^# n9 z5 C
                sell_orders.append(new_sell_order_info)
3 F7 M: s0 j: f% K) a' m: x+ ]
. i/ n9 q& z; X        elif order_info.get(&#39;status&#39;) == &#39;CANCELED&#39;:
3 Z1 Q- v& p, w            # 订单被取消,从sell_orders中删除
6 ?. k, m6 W. O# W7 \& j( [2 A            sell_orders.remove(sell_order_info)
1 W" C; A# a( ^6 ^. W3 ]        + X1 s. \+ W9 `' j- g6 _0 Q
        elif order_info.get(&#39;status&#39;) == &#39;NEW&#39;:
) F; v2 h; p/ x/ f+ d0 q0 K+ v' i            print(f&#39;{datetime.now().strftime(&#34;%Y-%m-%d %H:%M:%S&#34;)} 卖单尚未成交,挂单价{order_info.get(&#34;price&#34;)}&#39;)( u7 M* x2 }% N
& C0 ^% _! x' X( D, N4 X
        else:
2 f: G# D% S6 a9 o9 |            print(f&#39;{datetime.now().strftime(&#34;%Y-%m-%d %H:%M:%S&#34;)} 卖单当前状态为{order_info.get(&#34;status&#34;)}&#39;)
2 Z" |9 J5 X6 s8 e. h9 P9 D( D3 _/ Q( |* z
    ################################################################! d% g- A7 v, I. K9 ~6 S, H

- S* s+ h) l# o% I5 O    # 若当下没有挂买单 - 挂个买单' U  {5 V% a0 H( U: I. B. y+ {
    if not buy_orders:3 G' u: X! V& b! p
        6 M0 T( n6 y8 m+ ~0 v  s' a0 _
        # 计算买单价格( Y% b9 H2 f; m7 {
        price = bid_price * (1 - gap_percent) # 按当前买一价的下一格,挂买单
. ]% `8 ^, Q7 G        price = round(price, pricePrecision) # 处理价格精度1 ?, [: t* N. V3 H* M* F1 x) D
! x2 H% ~# R) I& t7 ^; `
        # 下单
) \& V: n' d- C! I8 x# h6 m        buy_order_info = place_order(exchange, symbol, &#39;BUY&#39;, quantity, price)- g+ E! a# P8 g

& I  o+ C9 z; r4 i7 ~! C$ X' Y% F! }        # 下单成功后; i' E0 s* O2 s* j' @. S
        if buy_order_info.get(&#39;orderId&#39;):6 V7 C3 W& x1 p: E+ I
            # print(f&#39;{datetime.now().strftime(&#34;%Y-%m-%d %H:%M:%S&#34;)} 当下没有买单,根据买一价挂单: {buy_order_info}&#39;)
& g/ |% s6 o% g' T! y  ^% t            # print(f&#39;{datetime.now().strftime(&#34;%Y-%m-%d %H:%M:%S&#34;)} 当下没有买单,根据买一价挂单: {buy_order_info.get(&#34;symbol&#34;)} | price: {buy_order_info.get(&#34;price&#34;)} | qty: {buy_order_info.get(&#34;origQty&#34;)} | orderId: {buy_order_info.get(&#34;orderId&#34;)}&#39;)
3 ~( o8 _1 h0 a/ X6 e+ Y$ l2 I            print_order(buy_order_info, &#39;当下没有买单,根据买一价挂单&#39;)
6 N- E: s& j) ~1 h: G# M: o            buy_orders.append(buy_order_info)9 O! q0 D" `" E; S1 H
5 B& L' l' K- ?
1 A0 f0 S; X8 a' \: h# |. q
    # 若当下没有挂卖单 - 挂个卖单
# D3 a/ ~" q3 ~! K- T) T- f    if not sell_orders:7 c: |3 L4 ]  r( P+ i7 z, y5 D' Y
- b) s7 n4 O' e) m( F
        # 计算卖单价格
) _9 x' k* \+ I        price = ask_price * (1 + gap_percent) # 按当前卖一价的上一格,挂卖单1 P' C; B- G8 f( N
        price = round(price, pricePrecision) # 处理价格精度
( o6 p5 {  Z3 P+ ^/ G' u+ M$ p* \% w! c/ Z$ v7 A7 j( Z/ Q
        # 下单- ^% C; v. ]0 I, i" B7 _' K9 Q
        sell_order_info = place_order(exchange, symbol, &#39;SELL&#39;, quantity, price)9 S0 x4 Z0 ?. N. C1 q. ~3 e  L- ~
- V8 o4 ]* k* m# W9 Y7 u4 A5 y
        # 下单成功后
+ ^$ Y' s- C' m1 M8 n2 O7 N4 W        if sell_order_info.get(&#39;orderId&#39;):" o3 L. G2 }9 W5 _0 ?/ |4 E
            # print(f&#39;{datetime.now().strftime(&#34;%Y-%m-%d %H:%M:%S&#34;)} 当下没有卖单,根据卖一价挂单: {sell_order_info}&#39;)
$ N0 m, |3 C/ a            # print(f&#39;{datetime.now().strftime(&#34;%Y-%m-%d %H:%M:%S&#34;)} 当下没有卖单,根据卖一价挂单: {sell_order_info.get(&#34;symbol&#34;)} | price: {sell_order_info.get(&#34;price&#34;)} | qty: {sell_order_info.get(&#34;origQty&#34;)} | orderId: {sell_order_info.get(&#34;orderId&#34;)}&#39;)" D. x* K, {* T& X5 S. ~. c2 }) v
            print_order(sell_order_info, &#39;当下没有卖单,根据卖一价挂单&#39;)5 g* R4 f; x/ b% g! Y
            sell_orders.append(sell_order_info)6 R& Q3 R* r: V! ]

( a% v; G6 \- w8 R: x    ################################################################* j# Y+ v3 Q2 v8 l# `5 b+ W

) z$ M! x$ O; K- S    # 确保某个价位下,仅有一个买单! K& t! v5 V( ]3 G. E4 \
    if buy_orders:+ O2 r  }: {3 A
        buy_orders.sort(key=lambda x: float(x[&#39;price&#39;]), reverse=False) # 最低价到最高价# S7 q! M+ h) t. P% y+ z
        delete_orders = [], m/ C4 o0 T2 z& r$ S
        for i in range(len(buy_orders)-1):
+ R: x; ]9 w5 [+ F            order = buy_orders! {  u2 h0 B/ n5 {5 j- Q3 O7 C
            next_order = buy_orders[i+1]
" z% ^' j  K1 a7 _: C            # 价差过小,即为重复订单. @) J6 s- ^- ?7 U1 h1 _
            if abs(float(next_order[&#39;price&#39;])/float(order[&#39;price&#39;]) - 1) < 0.0001:
" F9 N! Z- ~' S  h# ?9 f) n                # print(f&#39;{datetime.now().strftime(&#34;%Y-%m-%d %H:%M:%S&#34;)} 有重复买单,撤销订单:{next_order.get(&#34;symbol&#34;)} | price: {next_order.get(&#34;price&#34;)} | qty: {next_order.get(&#34;origQty&#34;)} | orderId: {next_order.get(&#34;orderId&#34;)}&#39;)
4 v' r& q. a1 ^                print_order(next_order, &#39;有重复买单,撤销订单&#39;)
, |1 l( P" I; t' k( h; J  d                # 撤单8 ~3 C( Z; c6 o  z- |
                cancel_order(exchange, symbol, next_order.get(&#39;orderId&#39;))5 p: s9 k4 u2 F. o' G# X
                # 将next_order放入delete_orders,循环结束后再remove,否则会影响buy_orders的下标i
7 @; F. E# X$ ^- E                delete_orders.append(next_order)
5 J! L$ [# @, I( [
4 M. L. Z# Z8 M) L" d        # 将buy_orders中,价格重复的订单remove, X9 Q$ j4 e2 B0 \; ^+ ?, D
        for order in delete_orders:
" c# t& h8 X3 r            buy_orders.remove(order), k, Y6 O& |& g: ]8 D
2 E3 `) p, }+ P, g- C2 g# q

  |( {7 ^. F6 h5 M    # 确保某个价位下,仅有一个卖单
+ S" N  [1 |6 U. r    if sell_orders:
; N) y2 h, }% \        sell_orders.sort(key=lambda x: float(x[&#39;price&#39;]), reverse=True) # 最低价到最高价$ \+ ^+ h- O9 `3 p1 v2 z- {$ f
        delete_orders = []
: ?4 N3 C: E& \. N) Q! Z        for i in range(len(sell_orders)-1):
2 P: V0 P. @+ u' i# @            order = sell_orders. R2 y+ Q- \4 \( H) ]
            next_order = sell_orders[i+1]
, K' `* L# v% {  Z# B3 k            # 价差过小,即为重复订单# H0 e+ `3 `, o( y+ Z
            if abs(float(next_order[&#39;price&#39;])/float(order[&#39;price&#39;]) - 1) < 0.0001:! ]) @' s  X9 H2 f1 N
                # print(f&#39;{datetime.now().strftime(&#34;%Y-%m-%d %H:%M:%S&#34;)} 有重复卖单,撤销订单:{next_order.get(&#34;symbol&#34;)} | price: {next_order.get(&#34;price&#34;)} | qty: {next_order.get(&#34;origQty&#34;)} | orderId: {next_order.get(&#34;orderId&#34;)}&#39;)
9 f- \4 |, G' N. }, p% L0 }                print_order(next_order, &#39;有重复卖单,撤销订单&#39;)- w3 |% v# O" i9 s+ ^! Q
                # 撤单- m! Z7 C: }/ _- e1 P
                cancel_order(exchange, symbol, next_order.get(&#39;orderId&#39;))5 C) \& G1 P) ]0 F* |% v% F
                # 将next_order放入delete_orders,循环结束后再remove,否则会影响buy_orders的下标i) C5 h, @& E  H/ }. P7 i# s% F
                delete_orders.append(next_order)
! f$ u( l( N: R0 ?, j& H8 [; w: _9 W1 q" H
        # 将buy_orders中,价格重复的订单remove
  b0 {  [. g8 A, t. v        for order in delete_orders:
1 ^! \4 ^0 Y8 z6 M) S            sell_orders.remove(order)
; S& O& w9 }* l2 C5 ~0 p9 r3 h: G5 _0 {6 E( l1 `( B
    ################################################################9 b6 L, K% m1 a9 f, @0 U8 l% Y( L% D, ^

( L4 [1 ?' k2 P5 n+ Q* j8 ]6 q& G$ Q3 f: x, ]6 ?4 }6 b' e5 P
    # 如果当前买单挂单数大于设置量,则撤掉部分买单: H; b# E: B+ l5 e# {" A
    if len(buy_orders) > max_orders:
; ?3 \5 j2 E# E! Y
) E/ ^! e; a1 b: A2 r& ^5 D        # 最低价到最高价
$ R+ r/ @! N9 M        buy_orders.sort(key=lambda x: float(x[&#39;price&#39;]), reverse=False)
6 |' n! b2 O+ M9 t. u( Q        # 取出最低价的买单1 [+ k, X5 C7 V8 {
        delete_order = buy_orders[0]
) M1 Q! W% S* m        # print(f&#39;{datetime.now().strftime(&#34;%Y-%m-%d %H:%M:%S&#34;)} 买单超过设置量{max_orders},撤销最低价的买单:{delete_order}&#39;)* J; E5 \2 U$ W/ w4 z
        print_order(delete_order, f&#39;买单超过设置量{max_orders},撤销最低价的买单&#39;)6 K' r$ ^4 L) b+ k2 x
        # 撤单
+ h# M& \0 U% g) V% g/ Z        cancel_order(exchange, symbol, delete_order.get(&#39;orderId&#39;))# z; v, ]0 [9 q1 H3 M
        # 从buy_orders移除
) O4 V+ P3 ~; D        buy_orders.remove(delete_order)# ?) F* S) H" u" r! I3 Z
) C5 m. [$ ^" q" A$ F2 ?
    # 如果当前买单挂单数大于设置量,则撤掉部分买单& T3 H- V' e( E& P+ y$ x8 q
    if len(sell_orders) > max_orders:9 Y: r% T5 w. d8 S6 N

2 y, e6 X5 U4 g8 d! Y& m4 T' _        # 最高价到最低价6 [, G. i: B) U- R2 m  w/ O5 ^
        sell_orders.sort(key=lambda x: float(x[&#39;price&#39;]), reverse=True)4 R) z& n: V3 w# @3 y
        # 取出最高价的卖单1 Q/ B$ {' n0 ^- B
        delete_order = sell_orders[0]
/ b' I: T) F. X* _# p; \        # print(f&#39;{datetime.now().strftime(&#34;%Y-%m-%d %H:%M:%S&#34;)} 卖单超过设置量{max_orders},撤销最高价的卖单:{delete_order}&#39;)1 Q9 Y; u/ ~" U5 }) q
        print_order(delete_order, f&#39;卖单超过设置量{max_orders},撤销最高价的卖单&#39;)
" m  H7 l) _1 D9 m) ?        # 撤单" @3 X/ s. b* T
        cancel_order(exchange, symbol, delete_order.get(&#39;orderId&#39;))
% x- J7 h% C# y* m4 l: o5 G" p$ F        # 从sell_orders移除) \2 w" _- o+ r. }2 }$ }1 v$ |
        sell_orders.remove(delete_order)0 k" y: E5 u6 x3 @& u' h3 h6 ^
: m' q" N0 t  Q  `. s* `+ |6 d
    # return最新的buy_orders, sell_orders! L( D; r3 C* b/ {' L# _
    sell_orders.sort(key=lambda x: float(x[&#39;price&#39;]), reverse=True)
$ @) _3 f% |( S) F    buy_orders.sort(key=lambda x: float(x[&#39;price&#39;]), reverse=True)- R8 d' L/ z# L7 ~& F; d
    print_orders(sell_orders)" r* r( k0 _' _: F8 [
    print_orders(buy_orders)8 b5 f3 Z% `$ E' V2 K& H4 O
0 g* X2 {9 J: A
/ E: B+ w+ i$ g3 G4 P

9 [* w+ _+ F7 H2 r; P0 g    return buy_orders, sell_orders所有代码可参考附件,往config.ini填入api后即可使用。
4 Q+ J; c  ]% f7 b7 u程序我100u小资金在LINKUSDT上测试了两天,没碰到什么大的单边行情,赚了1u…程序逻辑上貌似没有什么大问题~- m) m( D6 f1 l3 j! a5 C

8 g+ F, P; D0 `+ _' l) T+ r# m4 q5 u  l" ~. p. b  t
注意事项+ j$ C, y. q4 z. H1 H

. g; S3 w, d" Z% X· 码力微薄,可能有我没发现的bug,建议阅读代码理清逻辑后谨慎使用,我尽量每句代码都有注释;$ k/ T8 u; c& a7 p! v, L
· 程序有钉钉和微信两种报错方式,我暂时都注释掉了,大家可自行打开;
3 P$ |% B8 R/ n  |7 S! y! ?/ y5 x2 f· 网格可能是一个赚小钱亏大钱的策略,大家注意风险,网格范围设小一些。
! U" C2 p4 Q3 W% V7 I代码附件:, r% w* [% S+ }8 R2 Y( e
% q  W. C2 `8 d! C
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

250

金钱

0

收听

0

听众
性别

新手上路

金钱
250 元