市场转熊,到了中性跑的不理想,趋势也被来回割的阶段,没有特别好的赚钱方法,于是决定还是做好定投,布局下一波吧,之前有老板做过OKEX的定投框架,现在币安返佣很香,所以搞了一发币安的定投框架,完成了我自己的币安三件套中的最后一样,测了2周(目前实盘3天一投),暂时比较稳定。
9 o* F- p3 ]( i" |4 k/ _7 m一、总体思路5 `4 |7 D& [; V8 |
) ]3 P* j# N- q F, \7 p7 n分8个大的步骤,如下:, u9 i# ^& k) ]/ [1 `7 m+ H
# ##################### 1、获取币安现货价格精度 #######################3 K K: ^( O b
usdt_future_exchange_info(exchange, symbol_config)
: g4 M. M" a" t: k k4 u# ##################### 2、获取目标现货历史数据 #######################
. i9 c* w0 R; x! P. Y4 e9 t6 ? # 遍历获取币种历史数据
, Y) @0 K% [" J* | print('获取交易币种的历史K线数据')8 C2 W; A+ c9 V" P
# 获取币种的历史数据,会删除最新一行的数据) p- ]( Y' a- D1 R. B6 v+ w
symbol_candle_data = get_binance_history_candle_data(exchange, symbol_config, time_interval, max_len)6 z* k8 ~: E2 \0 o
# ##################### 3、获取当前账户信息 #######################
3 |) i# y) ]# W/ _& u # 更新账户信息symbol_info
- m& v) ]$ T& A symbol_info = update_symbol_info(exchange, symbol_info, symbol_config); S1 K6 M0 n2 ~: d( x8 ^8 a
# ##################### 4、计算并等待到下一次交易时间 #######################
4 s* T) b% i+ F7 C. ^' y # =获取策略执行时间,并sleep至该时间4 H8 X( f' C8 t
run_time = sleep_until_run_time(execution_interval)
$ @; A5 _7 Y$ N! n# ##################### 5、获取目标币种最新数据 #######################+ t" M( x, R$ R8 W/ T. o* @
# 获取数据
- l m6 T \! ^. D; ~. f) T- o4 t recent_candle_data = single_threading_get_binance_candle_data(exchange, symbol_config, symbol_info, time_interval, run_time, candle_num)0 D6 Y! W$ g5 R. }+ V$ p
# ##################### 6、根据定投规则计算交易信号及目标持仓量 #######################
1 ~1 [) Z" b; H, i # =计算每个币种的交易信号' X, K' P& F; G/ p# P
symbol_info = calculate_trade_vol(symbol_info, symbol_config, symbol_candle_data)5 V* L3 O V2 y7 B2 i
print('\n现货持仓与本次定投计划:\n', symbol_info): l# E$ f* }* r: _ K
# ##################### 7、下单,并更新订单信息到文档中 ######################## Y+ q) H) ?6 b
# order_info = place_binance_batch_order(exchange, symbol_order_params)
0 A* T0 W1 j4 Q/ Z! p symbol_order = single_threading_place_order(exchange, symbol_info, symbol_config) # 单线程下单4 n) K) d+ ~& A( e
print('下单记录:\n', symbol_order) P, m1 h- T2 L/ \3 Y
: _) ^! n% k+ I! J0 G: H # 更新订单信息,查看是否完全成交4 t4 @% C8 Y4 b0 ?! K) o
time.sleep(short_sleep_time) # 休息一段时间再更新订单信息+ }2 C0 Y. D' c
symbol_order = update_order_info(exchange, symbol_config, symbol_order)2 a! Y; ?: B1 X% @. J8 `# {
print('更新下单记录:', '\n', symbol_order)6 K# N3 \6 N2 S1 ?1 m% _
to_csv_log(symbol_order, 'invest') # 记录订单信息到CSV文件中
y* J2 X0 {6 Q! Y# ##################### 8、更新交易后的账户信息 #######################
# G# `+ b2 q+ d) H( s # 重新更新账户信息symbol_info
2 Y9 M. ?- U$ A3 o8 B time.sleep(long_sleep_time) # 休息一段时间再更新 T( h; R/ D( M+ i
symbol_info = pd.DataFrame(index=symbol_config.keys(), columns=symbol_info_columns)9 E6 k1 T$ y: t7 @
symbol_info = update_symbol_info(exchange, symbol_info, symbol_config)
9 t3 O- M, ?. L* M; J print('\nsymbol_info:\n', symbol_info, '\n')8 G5 X" z/ [, Z2 k' `* W
二、细节描述
, b* \+ Y( B0 C+ v7 c
' U) z5 H* e: `! Z. _1 、获取币安价格精度时
% G' _" `" C- x! ]) I9 C& V! J I! ^: n+ ~0 Q* m% o
对public_get_exchangeinfo返回的信息做了分析,核心是filters的结构,典型的list中装dict: T8 a# u* x/ U9 I7 I
'filters': [% h$ z; @# R( o! b2 ]( q! P$ L( m
{'filterType': 'PRICE_FILTER', 'minPrice': '0.00000100', 'maxPrice': '922327.00000000', 'tickSize': '0.00000100'},
; f. l( t# L0 b7 x8 [1 d4 v$ ^{'filterType': 'PERCENT_PRICE', 'multiplierUp': '5', 'multiplierDown': '0.2', 'avgPriceMins': '5'},
# R3 x. g2 O+ @{'filterType': 'LOT_SIZE', 'minQty': '0.00100000', 'maxQty': '100000.00000000', 'stepSize': '0.00100000'},% }6 x% A# L, p0 ^4 V7 f
{'filterType': 'MIN_NOTIONAL', 'minNotional': '0.00010000', 'applyToMarket': True, 'avgPriceMins': '5'},
" e1 ~0 L; Y4 U{'filterType': 'ICEBERG_PARTS', 'limit': '10'},% c# b% @! B j) V/ @: }' J" h6 e$ A
{'filterType': 'MARKET_LOT_SIZE', 'minQty': '0.00000000', 'maxQty': '1525.57157489', 'stepSize': '0.00000000'},/ B- h2 d% k3 U7 t r8 ?; H9 N
{'filterType': 'MAX_NUM_ORDERS', 'maxNumOrders': '200'},, W+ Q8 m& i6 i, p! n( a7 ^& g
{'filterType': 'MAX_NUM_ALGO_ORDERS', 'maxNumAlgoOrders': '5'}
0 t3 s4 c& b- m/ {1 h],经过分析,获取价格精度和下单量精度就是:
6 O) N9 _4 g/ M# f- P# 获取u本为合约交易对的信息/ q. A5 E. p _' d# v
exchange_info = retry_wrapper(exchange.public_get_exchangeinfo, act_name='查看现货基本信息')
- m u# v. q5 x* q # 转化为dataframe8 t D, `% W5 ]3 h; I4 ^$ [6 `. i
df = pd.DataFrame(exchange_info['symbols'])2 ~# n4 U+ [8 j9 r1 }% i
df['tickSize'] = df['filters'].apply(lambda x: x[0]['tickSize']) # 最小下单价精度
0 d- q5 {- u4 N/ F3 t9 e4 N+ l; t4 ^df['stepSize'] = df['filters'].apply(lambda x: x[2]['stepSize']) # 最小下单量精度2 、录订单信息" ~8 S' {5 J9 R3 g! T( L- Z! v' w
7 ]* ^- Q0 @% P; D+ L' s币安接口中不包含某些信息,如只有委托价格,没有实际成交价格(也可能是我没找到合适的接口),因此需要我们自己根据成交量和成交总金额计算:. N! x1 L+ B4 ^; [. ^0 M# e8 }) ~
if order_info:& c2 H9 l0 {) S ^" X' T
symbol_order.at[order_id, "订单状态"] = binance_order_state[order_info["status"]]! H2 z: h; ~( ~& O4 L6 e
if binance_order_state[order_info["status"]] == '失败':
9 v2 J% ]1 M0 ^4 d z0 r print('下单失败')
2 g( W9 s. z) X. K, o) _& y symbol_order.at[order_id, "交易方向"] = order_info["side"]+ F' X8 T8 G/ a" n3 w
symbol_order.at[order_id, "委托数量"] = order_info["origQty"]
0 V5 v" r/ T- ~ @ symbol_order.at[order_id, "成交数量"] = order_info["executedQty"]/ s; @1 i& F' J- n4 b, b" _6 g
symbol_order.at[order_id, "委托价格"] = order_info["price"]1 g) Z: g' g5 w" u8 x
symbol_order.at[order_id, "成交总金额"] = order_info["cummulativeQuoteQty"]3 Y2 a/ D! p$ j' i" B# X
symbol_order.at[order_id, "成交均价"] = float(order_info["cummulativeQuoteQty"]) / float(
* F+ v3 r) L0 E8 x! P5 q3 I order_info["executedQty"]) # 接口里没有,所以需要自己计算
( \0 R! S2 i) ] ^/ F0 Z! |0 e symbol_order.at[order_id, "委托时间"] = pd.to_datetime(order_info["time"], unit='ms')& Z" X# W7 z; D% c
else:; l6 ?/ X6 z# S: V# {6 i
print('根据订单号获取订单信息失败次数超过max_try_amount,发送钉钉'), `$ o" [4 Z- H2 \
3 、定投策略) f& k! j q. ]/ J n1 }. G
0 H" V" M1 ~# m3 l. t! s+ w定投策略都包含在Signals文件中,里面策略具体含义可以参考大佬的帖子:目前我用的就是定投策略+ I# a8 Q8 u$ j$ f
++++++++++++++++++++++++++++++++++++! `- x1 f0 m6 @ L/ W6 P! \
定投是熊市囤币,牛市收割的利器,一起跑起来,0 J+ p: d7 N+ M( R
3 a- K. ^- W5 @4 N; Q
最后附上代码:& r! I% D# g" Z( o) E5 ~, x$ }, T2 @
% Z. ^ W _7 x5 A4 i
|