openfund-maker 1.0.17__py3-none-any.whl → 1.1.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- maker/ThreeLineOrderBot.py +203 -178
- {openfund_maker-1.0.17.dist-info → openfund_maker-1.1.1.dist-info}/METADATA +1 -1
- {openfund_maker-1.0.17.dist-info → openfund_maker-1.1.1.dist-info}/RECORD +5 -5
- {openfund_maker-1.0.17.dist-info → openfund_maker-1.1.1.dist-info}/WHEEL +0 -0
- {openfund_maker-1.0.17.dist-info → openfund_maker-1.1.1.dist-info}/entry_points.txt +0 -0
maker/ThreeLineOrderBot.py
CHANGED
@@ -49,18 +49,6 @@ class ThreeLineOrdergBot:
|
|
49
49
|
def get_precision_length(self,symbol) -> int:
|
50
50
|
tick_size = self.get_tick_size(symbol)
|
51
51
|
return len(f"{tick_size:.10f}".rstrip('0').split('.')[1]) if '.' in f"{tick_size:.10f}" else 0
|
52
|
-
|
53
|
-
# def decimal_to_precision(self,symbol,price) -> float:
|
54
|
-
# from ccxt.base.decimal_to_precision import DECIMAL_PLACES, TICK_SIZE, NO_PADDING, TRUNCATE, ROUND, ROUND_UP, ROUND_DOWN, SIGNIFICANT_DIGITS
|
55
|
-
# tick_size = self.get_tick_size(symbol)
|
56
|
-
# new_px = self.exchange.decimal_to_precision(
|
57
|
-
# n=float(price),
|
58
|
-
# precision=tick_size,
|
59
|
-
# rounding_mode=ROUND,
|
60
|
-
# counting_mode=TICK_SIZE
|
61
|
-
# )
|
62
|
-
|
63
|
-
# return new_px
|
64
52
|
|
65
53
|
def get_position_mode(self):
|
66
54
|
try:
|
@@ -78,7 +66,6 @@ class ThreeLineOrdergBot:
|
|
78
66
|
except Exception as e:
|
79
67
|
self.logger.error(f"无法检测持仓模式: {e}")
|
80
68
|
return None
|
81
|
-
|
82
69
|
|
83
70
|
def fetch_and_store_all_instruments(self,instType='SWAP'):
|
84
71
|
try:
|
@@ -123,7 +110,6 @@ class ThreeLineOrdergBot:
|
|
123
110
|
else:
|
124
111
|
raise ValueError("Unexpected response structure or missing 'c' value")
|
125
112
|
|
126
|
-
|
127
113
|
def get_mark_price(self,symbol):
|
128
114
|
# response = market_api.get_ticker(instId)
|
129
115
|
ticker = self.exchange.fetch_ticker(symbol)
|
@@ -202,118 +188,47 @@ class ThreeLineOrdergBot:
|
|
202
188
|
amplitudes.append(amplitude)
|
203
189
|
average_amplitude = sum(amplitudes) / len(amplitudes)
|
204
190
|
return average_amplitude
|
205
|
-
|
206
|
-
def cancel_all_orders(self,symbol):
|
207
|
-
try:
|
208
|
-
# 获取所有未完成订单
|
209
|
-
params = {
|
210
|
-
# 'instId': instId
|
211
|
-
}
|
212
|
-
open_orders = self.exchange.fetch_open_orders(symbol=symbol,params=params)
|
213
|
-
|
214
|
-
# 取消每个订单
|
215
|
-
for order in open_orders:
|
216
|
-
self.exchange.cancel_order(order['id'], symbol,params=params)
|
217
|
-
|
218
|
-
self.logger.info(f"{symbol} 挂单取消成功.")
|
219
|
-
except Exception as e:
|
220
|
-
self.logger.error(f"{symbol} 取消订单失败: {str(e)}")
|
221
191
|
|
222
|
-
def
|
223
|
-
try:
|
224
|
-
# 设置杠杆
|
225
|
-
params = {
|
226
|
-
# 'instId': instId,
|
227
|
-
'leverage': leverage,
|
228
|
-
'marginMode': mgnMode
|
229
|
-
}
|
230
|
-
if posSide:
|
231
|
-
params['side'] = posSide
|
232
|
-
|
233
|
-
self.exchange.set_leverage(leverage, symbol=symbol, params=params)
|
234
|
-
self.logger.debug(f"{symbol} Successfully set leverage to {leverage}x")
|
235
|
-
except Exception as e:
|
236
|
-
self.logger.error(f"{symbol} Error setting leverage: {e}")
|
237
|
-
#
|
238
|
-
def check_position(self,symbol) -> bool:
|
192
|
+
def calculate_range_diff(self,prices:pd.Series) -> float:
|
239
193
|
"""
|
240
|
-
|
241
|
-
|
194
|
+
计算价格列表中最后一个价格与第一个价格的差值。
|
242
195
|
Args:
|
243
|
-
|
244
|
-
|
196
|
+
prices: 价格列表。
|
245
197
|
Returns:
|
246
|
-
|
198
|
+
diff: 计算最高价列的最大值与最小值的差值
|
199
|
+
。
|
247
200
|
"""
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
return False
|
254
|
-
except Exception as e:
|
255
|
-
self.logger.error(f"{symbol} 检查持仓失败: {str(e)}")
|
256
|
-
return False
|
257
|
-
|
258
|
-
|
259
|
-
def place_order(self,symbol, price, amount_usdt, side):
|
260
|
-
|
261
|
-
|
262
|
-
markets = self.exchange.load_markets()
|
263
|
-
if symbol not in markets:
|
264
|
-
self.logger.error(f"{symbol}: Instrument {symbol} not found in markets")
|
265
|
-
return
|
266
|
-
market = markets[symbol]
|
267
|
-
# 获取价格精度
|
268
|
-
price_precision = market['precision']['price']
|
269
|
-
adjusted_price = self.round_price_to_tick(price, price_precision)
|
270
|
-
|
271
|
-
if amount_usdt > 0:
|
272
|
-
if side == 'buy':
|
273
|
-
pos_side = 'long'
|
274
|
-
else:
|
275
|
-
pos_side = 'short'
|
276
|
-
# 设置杠杆
|
277
|
-
self.set_leverage(symbol=symbol, leverage=self.leverage_value, mgnMode='isolated',posSide=pos_side)
|
278
|
-
params = {
|
279
|
-
|
280
|
-
"tdMode": 'isolated',
|
281
|
-
"side": side,
|
282
|
-
"ordType": 'limit',
|
283
|
-
# "sz": amount_usdt,
|
284
|
-
"px": str(adjusted_price)
|
285
|
-
}
|
286
|
-
|
287
|
-
# 模拟盘(demo_trading)需要 posSide
|
288
|
-
if self.is_demo_trading == 1 :
|
289
|
-
params["posSide"] = pos_side
|
290
|
-
|
291
|
-
# self.logger.debug(f"---- Order placed params: {params}")
|
292
|
-
try:
|
293
|
-
order = {
|
294
|
-
'symbol': symbol,
|
295
|
-
'side': side,
|
296
|
-
'type': 'limit',
|
297
|
-
'amount': amount_usdt,
|
298
|
-
'price': float(adjusted_price),
|
299
|
-
'params': params
|
300
|
-
}
|
301
|
-
# 使用ccxt创建订单
|
302
|
-
self.logger.debug(f"Pre Order placed: {order} ")
|
303
|
-
order_result = self.exchange.create_order(
|
304
|
-
**order
|
305
|
-
# symbol=symbol,
|
306
|
-
# type='limit',
|
307
|
-
# side=side,
|
308
|
-
# amount=amount_usdt,
|
309
|
-
# price=float(adjusted_price),
|
310
|
-
# params=params
|
311
|
-
)
|
312
|
-
# self.logger.debug(f"{symbol} ++ Order placed rs : {order_result}")
|
313
|
-
except Exception as e:
|
314
|
-
self.logger.error(f"{symbol} Failed to place order: {e}")
|
315
|
-
self.logger.info(f"--------- ++ {symbol} Order placed done! --------")
|
201
|
+
if prices.empty:
|
202
|
+
return None
|
203
|
+
# 将价格列表转换为pandas Series格式
|
204
|
+
|
205
|
+
diff = prices.max() - prices.min()
|
316
206
|
|
207
|
+
return diff
|
208
|
+
|
209
|
+
def calculate_place_order_price(self, symbol,side,base_price, amplitude_limit, offset=1) -> float:
|
210
|
+
"""
|
211
|
+
计算开仓价格
|
212
|
+
Args:
|
213
|
+
symbol: 交易对
|
214
|
+
side: 开仓方向
|
215
|
+
base_price: 开盘价格
|
216
|
+
amplitude_limit: 振幅限制
|
217
|
+
offset: 偏移量
|
218
|
+
Returns:
|
219
|
+
place_order_price: 开仓价格
|
220
|
+
"""
|
221
|
+
tick_size = self.get_tick_size(symbol)
|
222
|
+
place_order_price = None
|
223
|
+
# 计算止盈价格,用市场价格(取持仓期间历史最高)减去开仓价格的利润,再乘以不同阶段的止盈百分比。
|
224
|
+
|
225
|
+
if side == 'buy':
|
226
|
+
place_order_price = base_price * (1- amplitude_limit/100) - offset * tick_size
|
227
|
+
else:
|
228
|
+
place_order_price = base_price * (1 + amplitude_limit/100) + offset * tick_size
|
229
|
+
self.logger.debug(f"++++ {symbol} 下单价格: {place_order_price:.9f} 方向 {side} 基准价格{base_price} 振幅限制 {amplitude_limit} ")
|
230
|
+
return float(self.round_price_to_tick(place_order_price,tick_size))
|
231
|
+
|
317
232
|
# 定义根据均线斜率判断 K 线方向的函数: 0 空 1 多 -1 平
|
318
233
|
def judge_k_line_direction(self, symbol, pair_config, ema: pd.Series, klines) -> int:
|
319
234
|
"""
|
@@ -330,19 +245,19 @@ class ThreeLineOrdergBot:
|
|
330
245
|
|
331
246
|
# precision= self.get_precision_length(symbol)
|
332
247
|
|
333
|
-
|
248
|
+
ema_diff = ema.diff().tail(period)
|
334
249
|
|
335
250
|
direction = None
|
336
|
-
if
|
251
|
+
if ema_diff.iloc[-1] < 0:
|
337
252
|
# 下降趋势
|
338
253
|
direction = 0
|
339
|
-
elif
|
254
|
+
elif ema_diff.iloc[-1] > 0 :
|
340
255
|
# 上升趋势
|
341
256
|
direction = 1
|
342
257
|
else:
|
343
258
|
# 震荡趋势
|
344
259
|
direction = -1
|
345
|
-
self.logger.debug(f"{symbol}: K线极差={
|
260
|
+
self.logger.debug(f"{symbol}: K线极差={ema_diff.map('{:.9f}'.format).values} ,K线方向={direction}")
|
346
261
|
return direction
|
347
262
|
|
348
263
|
def judge_ema_direction(self, symbol, pair_config, ema: pd.Series) -> int:
|
@@ -369,7 +284,8 @@ class ThreeLineOrdergBot:
|
|
369
284
|
elif all(ema_4_diff >= 0) and any(ema_4_diff > 0) :
|
370
285
|
# 上升趋势
|
371
286
|
direction = 1
|
372
|
-
|
287
|
+
# 都是 (0 0 0) 或 (+ 0 -) 这两种情况认为都是震荡
|
288
|
+
else:
|
373
289
|
# 震荡趋势
|
374
290
|
direction = -1
|
375
291
|
self.logger.debug(f"{symbol}: EMA极差={ema_4_diff.map('{:.4f}'.format).values} ,EMA方向={direction}")
|
@@ -410,10 +326,15 @@ class ThreeLineOrdergBot:
|
|
410
326
|
'index': last_death
|
411
327
|
}
|
412
328
|
|
413
|
-
def judge_ma_apex(self,symbol,pair_config, fastklines,slowklines) -> bool:
|
329
|
+
def judge_ma_apex(self,symbol,pair_config,cross_index, fastklines,slowklines) -> bool:
|
414
330
|
period = int(pair_config.get('ema_range_period', 3))
|
415
331
|
precision= self.get_precision_length(symbol)
|
416
332
|
|
333
|
+
# 获取交叉点的索引,从交叉点之后进行判断
|
334
|
+
index = 0
|
335
|
+
if cross_index is not None:
|
336
|
+
index = cross_index
|
337
|
+
|
417
338
|
df = pd.DataFrame({
|
418
339
|
'ema': fastklines,
|
419
340
|
'sma': slowklines
|
@@ -421,21 +342,24 @@ class ThreeLineOrdergBot:
|
|
421
342
|
# 快线和慢线的差值
|
422
343
|
# 将ema和sma转换为tick_size精度
|
423
344
|
# df['diff'] = df['ema'].apply(lambda x: float(self.round_price_to_tick(x, tick_size))) - df['sma'].apply(lambda x: float(self.round_price_to_tick(x, tick_size)))
|
424
|
-
df['diff'] = df['ema'].round(precision)-df['sma'].round(precision)
|
345
|
+
df['diff'] = df['ema'].tail(period*2).round(precision)-df['sma'].tail(period*2).round(precision)
|
425
346
|
df['ema_diff'] = df['ema'] - df['ema'].shift(1)
|
426
347
|
df['sma_diff'] = df['sma'] - df['sma'].shift(1)
|
427
348
|
# 计算斜率,【正】表示两线距离扩张,【负】表示两线距离收缩
|
428
349
|
df['slope'] = df['diff'].abs().diff().round(4)
|
429
350
|
|
430
|
-
self.logger.debug(f"{symbol}: slopes = \n
|
431
|
-
|
432
|
-
#
|
433
|
-
|
351
|
+
self.logger.debug(f"{symbol}: ma apex slopes = \n"
|
352
|
+
f"{df[['ema','ema_diff','sma','sma_diff','diff','slope']].iloc[-1-period:-1]} ")
|
353
|
+
# 筛选出索引大于等于特定索引值的 slope 列元素
|
354
|
+
filtered_slope = df['slope'][df.index >= index]
|
434
355
|
|
356
|
+
# 两条线的距离是扩张状态还是收缩状态 true 是收缩 flase 是扩张
|
357
|
+
is_expanding_or_contracting = all(filtered_slope.tail(period) <= 0 ) and \
|
358
|
+
any(filtered_slope.tail(period) < 0)
|
359
|
+
|
435
360
|
return is_expanding_or_contracting
|
436
|
-
|
437
|
-
|
438
|
-
def calculate_range_diff(self,prices:pd.Series) -> float:
|
361
|
+
|
362
|
+
def judge_range_diff(self,symbol,pair_config,prices:pd.Series) -> bool:
|
439
363
|
"""
|
440
364
|
计算价格列表中最后一个价格与第一个价格的差值。
|
441
365
|
Args:
|
@@ -444,38 +368,128 @@ class ThreeLineOrdergBot:
|
|
444
368
|
diff: 计算最高价列的最大值与最小值的差值
|
445
369
|
。
|
446
370
|
"""
|
371
|
+
limit = int(pair_config.get('ema_range_limit', 1))
|
372
|
+
period = int(pair_config.get('ema_range_period', 3))
|
373
|
+
tick_size = self.get_tick_size(symbol)
|
447
374
|
if prices.empty:
|
448
|
-
return None
|
449
|
-
# 将价格列表转换为pandas Series格式
|
375
|
+
return None
|
450
376
|
|
451
|
-
diff = prices.max() - prices.min()
|
452
|
-
|
453
|
-
return diff
|
454
|
-
|
455
|
-
def
|
377
|
+
diff = prices.tail(period).max() - prices.tail(period).min()
|
378
|
+
self.logger.debug(f"{symbol}: 最高价列的最大值与最小值的差值 = {diff:.9f}")
|
379
|
+
return abs(diff) <= tick_size * limit
|
380
|
+
|
381
|
+
def set_leverage(self,symbol, leverage, mgnMode='isolated',posSide=None):
|
382
|
+
try:
|
383
|
+
# 设置杠杆
|
384
|
+
params = {
|
385
|
+
# 'instId': instId,
|
386
|
+
'leverage': leverage,
|
387
|
+
'marginMode': mgnMode
|
388
|
+
}
|
389
|
+
if posSide:
|
390
|
+
params['side'] = posSide
|
391
|
+
|
392
|
+
self.exchange.set_leverage(leverage, symbol=symbol, params=params)
|
393
|
+
self.logger.debug(f"{symbol} Successfully set leverage to {leverage}x")
|
394
|
+
except Exception as e:
|
395
|
+
self.logger.error(f"{symbol} Error setting leverage: {e}")
|
396
|
+
#
|
397
|
+
def check_position(self,symbol) -> bool:
|
456
398
|
"""
|
457
|
-
|
399
|
+
检查指定交易对是否有持仓
|
400
|
+
|
458
401
|
Args:
|
459
|
-
symbol: 交易对
|
460
|
-
|
461
|
-
base_price: 开盘价格
|
462
|
-
amplitude_limit: 振幅限制
|
463
|
-
offset: 偏移量
|
402
|
+
symbol: 交易对ID
|
403
|
+
|
464
404
|
Returns:
|
465
|
-
|
405
|
+
bool: 是否有持仓
|
466
406
|
"""
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
407
|
+
try:
|
408
|
+
position = self.exchange.fetch_position(symbol=symbol)
|
409
|
+
if position and position['contracts']> 0:
|
410
|
+
self.logger.debug(f"{symbol} 有持仓合约数: {position['contracts']}")
|
411
|
+
return True
|
412
|
+
return False
|
413
|
+
except Exception as e:
|
414
|
+
self.logger.error(f"{symbol} 检查持仓失败: {str(e)}")
|
415
|
+
return False
|
416
|
+
|
417
|
+
def place_order(self,symbol, price, amount_usdt, side):
|
418
|
+
|
419
|
+
|
420
|
+
markets = self.exchange.load_markets()
|
421
|
+
if symbol not in markets:
|
422
|
+
self.logger.error(f"{symbol}: Instrument {symbol} not found in markets")
|
423
|
+
return
|
424
|
+
market = markets[symbol]
|
425
|
+
# 获取价格精度
|
426
|
+
price_precision = market['precision']['price']
|
427
|
+
adjusted_price = self.round_price_to_tick(price, price_precision)
|
428
|
+
|
429
|
+
if amount_usdt > 0:
|
430
|
+
if side == 'buy':
|
431
|
+
pos_side = 'long'
|
432
|
+
else:
|
433
|
+
pos_side = 'short'
|
434
|
+
# 设置杠杆
|
435
|
+
self.set_leverage(symbol=symbol, leverage=self.leverage_value, mgnMode='isolated',posSide=pos_side)
|
436
|
+
params = {
|
437
|
+
|
438
|
+
"tdMode": 'isolated',
|
439
|
+
"side": side,
|
440
|
+
"ordType": 'limit',
|
441
|
+
# "sz": amount_usdt,
|
442
|
+
"px": str(adjusted_price)
|
443
|
+
}
|
444
|
+
|
445
|
+
# 模拟盘(demo_trading)需要 posSide
|
446
|
+
if self.is_demo_trading == 1 :
|
447
|
+
params["posSide"] = pos_side
|
448
|
+
|
449
|
+
# self.logger.debug(f"---- Order placed params: {params}")
|
450
|
+
try:
|
451
|
+
order = {
|
452
|
+
'symbol': symbol,
|
453
|
+
'side': side,
|
454
|
+
'type': 'limit',
|
455
|
+
'amount': amount_usdt,
|
456
|
+
'price': float(adjusted_price),
|
457
|
+
'params': params
|
458
|
+
}
|
459
|
+
# 使用ccxt创建订单
|
460
|
+
self.logger.debug(f"Pre Order placed: {order} ")
|
461
|
+
order_result = self.exchange.create_order(
|
462
|
+
**order
|
463
|
+
# symbol=symbol,
|
464
|
+
# type='limit',
|
465
|
+
# side=side,
|
466
|
+
# amount=amount_usdt,
|
467
|
+
# price=float(adjusted_price),
|
468
|
+
# params=params
|
469
|
+
)
|
470
|
+
# self.logger.debug(f"{symbol} ++ Order placed rs : {order_result}")
|
471
|
+
except Exception as e:
|
472
|
+
self.logger.error(f"{symbol} Failed to place order: {e}")
|
473
|
+
self.logger.info(f"--------- ++ {symbol} Order placed done! --------")
|
474
|
+
|
475
|
+
def cancel_all_orders(self,symbol):
|
476
|
+
try:
|
477
|
+
# 获取所有未完成订单
|
478
|
+
params = {
|
479
|
+
# 'instId': instId
|
480
|
+
}
|
481
|
+
open_orders = self.exchange.fetch_open_orders(symbol=symbol,params=params)
|
482
|
+
|
483
|
+
# 取消每个订单
|
484
|
+
for order in open_orders:
|
485
|
+
self.exchange.cancel_order(order['id'], symbol,params=params)
|
486
|
+
|
487
|
+
self.logger.info(f"{symbol} 挂单取消成功.")
|
488
|
+
except Exception as e:
|
489
|
+
self.logger.error(f"{symbol} 取消订单失败: {str(e)}")
|
490
|
+
|
478
491
|
def process_pair(self,symbol,pair_config):
|
492
|
+
self.logger.info("=" * 60)
|
479
493
|
# 检查是否有持仓,有持仓不进行下单
|
480
494
|
if self.check_position(symbol=symbol) :
|
481
495
|
self.logger.info(f"{symbol} 有持仓合约,不进行下单。")
|
@@ -506,7 +520,7 @@ class ThreeLineOrdergBot:
|
|
506
520
|
|
507
521
|
# 最新交叉方向
|
508
522
|
last_cross_direction = self.exchange.safe_dict(self.cross_directions,symbol,None)
|
509
|
-
|
523
|
+
cross_index = self.exchange.safe_dict(last_cross_direction,'index',None)
|
510
524
|
|
511
525
|
# 判断趋势:多头趋势或空头趋势
|
512
526
|
direction = self.judge_k_line_direction(symbol=symbol, pair_config=pair_config,ema=fastk,klines=klines)
|
@@ -516,34 +530,48 @@ class ThreeLineOrdergBot:
|
|
516
530
|
is_bearish_trend = True
|
517
531
|
|
518
532
|
# 结合金叉死叉判断是否是周期顶部和底部
|
519
|
-
is_apex = self.judge_ma_apex(symbol=symbol,pair_config=pair_config, fastklines=fastk,slowklines=slowk)
|
520
533
|
ema_direction = self.judge_ema_direction(symbol=symbol, pair_config=pair_config,ema=fastk)
|
534
|
+
is_apex = self.judge_ma_apex(symbol=symbol,pair_config=pair_config,cross_index=cross_index, fastklines=fastk,slowklines=slowk)
|
535
|
+
# if_inner_range = self.judge_range_diff(symbol=symbol, pair_config=pair_config, prices=fastk)
|
521
536
|
# 金叉死叉逻辑
|
522
537
|
if last_cross_direction and last_cross_direction['cross'] == 1 : # 金叉
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
538
|
+
# 强校验下单条件
|
539
|
+
# if is_apex or ema_direction == -1 or if_inner_range:
|
540
|
+
# self.logger.debug(f"{symbol} 强校验 - 金叉:{last_cross_direction},两线收缩={is_apex} ,ema_平={ema_direction},均线振幅={if_inner_range} ,不开单!!")
|
541
|
+
# 弱校验下单条件
|
542
|
+
if is_apex or ema_direction == -1:
|
543
|
+
self.logger.debug(f"{symbol} :金叉={last_cross_direction['cross']},两线收缩={is_apex} ,快线方向(平:-1)={ema_direction},不挂单!!")
|
527
544
|
is_bullish_trend = False
|
545
|
+
is_bearish_trend = False
|
546
|
+
else :
|
547
|
+
self.logger.debug(f"{symbol} :金叉={last_cross_direction['cross']},两线收缩={is_apex} ,快线方向(平:-1)={ema_direction}, 清理空单,挂多单!!")
|
548
|
+
is_bearish_trend = False
|
528
549
|
|
529
550
|
elif last_cross_direction and last_cross_direction['cross'] == 0 : # 死叉
|
530
|
-
|
531
|
-
|
551
|
+
|
552
|
+
# 强校验下单条件
|
553
|
+
# if is_apex or ema_direction == -1 or if_inner_range :
|
554
|
+
# self.logger.debug(f"{symbol} 强校验 - 死叉:{last_cross_direction},两线收缩={is_apex} ,ema_平={ema_direction},均线振幅={if_inner_range} ,不开单!!")
|
555
|
+
# 弱校验下单条件
|
532
556
|
if is_apex or ema_direction == -1:
|
533
|
-
self.logger.debug(f"{symbol}
|
557
|
+
self.logger.debug(f"{symbol} :死叉={last_cross_direction['cross']},两线收缩={is_apex} ,快线方向(平:-1)={ema_direction},不挂单!!")
|
534
558
|
is_bearish_trend = False
|
559
|
+
is_bullish_trend = False
|
560
|
+
else :
|
561
|
+
self.logger.debug(f"{symbol} :死叉={last_cross_direction['cross']},两线收缩={is_apex} ,快线方向(平:-1)={ema_direction},清理多单,挂空单!!")
|
562
|
+
is_bullish_trend = False
|
535
563
|
|
536
564
|
else:
|
537
|
-
self.logger.
|
565
|
+
self.logger.warning(f"{symbol} :当前没有金叉死叉,以K线趋势为准。")
|
538
566
|
|
539
567
|
|
540
|
-
if (not is_bullish_trend and not is_bearish_trend)
|
541
|
-
self.logger.info(f"{symbol}
|
568
|
+
if (not is_bullish_trend and not is_bearish_trend) :
|
569
|
+
self.logger.info(f"{symbol} :当前是震荡趋势(平),不挂单!! 死叉={last_cross_direction['cross']},两线收缩={is_apex} ,快线方向(平:-1)={ema_direction}")
|
542
570
|
return
|
543
571
|
|
544
572
|
'''
|
545
573
|
取当前K线的前三根K线中最高/低的值作为止盈位。
|
546
|
-
20250210
|
574
|
+
20250210 增加开单价格约束,下单时,三线如果价格振幅小(如0.32%内),那去找到0.32%外的那根。 振幅 amplitude_limit
|
547
575
|
'''
|
548
576
|
|
549
577
|
# 取当前 K 线的前三根 K 线
|
@@ -558,9 +586,7 @@ class ThreeLineOrdergBot:
|
|
558
586
|
|
559
587
|
amplitude_limit = pair_config.get('amplitude_limit', 0.32)
|
560
588
|
|
561
|
-
self.logger.debug(f"{symbol} 当前K线的前三根K线 最高价: {max_high}, 最低价: {min_low}")
|
562
|
-
|
563
|
-
|
589
|
+
self.logger.debug(f"{symbol} 当前K线的前三根K线 最高价: {max_high}, 最低价: {min_low}")
|
564
590
|
|
565
591
|
long_amount_usdt = pair_config.get('long_amount_usdt', 5)
|
566
592
|
short_amount_usdt = pair_config.get('short_amount_usdt', 5)
|
@@ -573,6 +599,7 @@ class ThreeLineOrdergBot:
|
|
573
599
|
close_price = klines[-1][4]
|
574
600
|
self.logger.debug(f"-- {symbol} 最新K线 {klines[-1]}")
|
575
601
|
|
602
|
+
# FIXME calculate_range_diff 去掉
|
576
603
|
if is_bullish_trend:
|
577
604
|
diff = self.calculate_range_diff(prices=low_prices)
|
578
605
|
cur_amplitude_limit = diff / close_price * 100
|
@@ -602,9 +629,7 @@ class ThreeLineOrdergBot:
|
|
602
629
|
self.logger.error(error_message,exc_info=True)
|
603
630
|
traceback.print_exc()
|
604
631
|
self.send_feishu_notification(error_message)
|
605
|
-
|
606
|
-
|
607
|
-
|
632
|
+
self.logger.info("=" * 60)
|
608
633
|
def monitor_klines(self):
|
609
634
|
symbols = list(self.trading_pairs_config.keys()) # 获取所有币对的ID
|
610
635
|
batch_size = 5 # 每批处理的数量
|
@@ -1,4 +1,4 @@
|
|
1
|
-
maker/ThreeLineOrderBot.py,sha256=
|
1
|
+
maker/ThreeLineOrderBot.py,sha256=JUMGkrsqQ5JOZdzUyEwZx15R5nIFu3IoqlWbzMtPBpY,28456
|
2
2
|
maker/WickReversalOrderBot.py,sha256=Oc6wChdWu39lfWh3NRHM8BqvaRIYDNZiDR6PDnE9XUM,17374
|
3
3
|
maker/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
4
4
|
maker/config.py,sha256=YPxghO5i0vgRg9Cja8kGj9O7pgSbbtzOgf3RexqXXwY,1188
|
@@ -7,7 +7,7 @@ maker/main_m.py,sha256=0PzDTnuBrxfpy5WDfsIHKAzZ_7pkuvuqqeWik0vpWio,15522
|
|
7
7
|
maker/okxapi.py,sha256=_9G0U_o0ZC8NxaT6PqpiLgxBm9gPobC9PsFHZE1c5w0,553
|
8
8
|
maker/zhen.py.bak,sha256=HNkrQbJts8G9umE9chEFsc0cLQApcM9KOVNMYPpkBXM,10918
|
9
9
|
maker/zhen_2.py,sha256=4IaHVtTCMSlrLGSTZrWpW2q-f7HZsUNRkW_-5QgWv24,10509
|
10
|
-
openfund_maker-1.
|
11
|
-
openfund_maker-1.
|
12
|
-
openfund_maker-1.
|
13
|
-
openfund_maker-1.
|
10
|
+
openfund_maker-1.1.1.dist-info/METADATA,sha256=0EsCzS1fP9Hcd9Gvx-CudomuhM-Yk4EJtf5r7HP2wbc,1965
|
11
|
+
openfund_maker-1.1.1.dist-info/WHEEL,sha256=IYZQI976HJqqOpQU6PHkJ8fb3tMNBFjg-Cn-pwAbaFM,88
|
12
|
+
openfund_maker-1.1.1.dist-info/entry_points.txt,sha256=gKMytICEKcMRFQDFkHZLnIpID7UQFoTIM_xcpiiV6Ns,50
|
13
|
+
openfund_maker-1.1.1.dist-info/RECORD,,
|
File without changes
|
File without changes
|