openfund-maker 1.0.16__py3-none-any.whl → 1.1.0__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 +221 -188
- {openfund_maker-1.0.16.dist-info → openfund_maker-1.1.0.dist-info}/METADATA +1 -1
- {openfund_maker-1.0.16.dist-info → openfund_maker-1.1.0.dist-info}/RECORD +5 -5
- {openfund_maker-1.0.16.dist-info → openfund_maker-1.1.0.dist-info}/WHEEL +0 -0
- {openfund_maker-1.0.16.dist-info → openfund_maker-1.1.0.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)
|
@@ -167,29 +153,29 @@ class ThreeLineOrdergBot:
|
|
167
153
|
atr = sum(trs[-period:]) / period
|
168
154
|
return atr
|
169
155
|
|
170
|
-
def calculate_sma_pandas(self,symbol,
|
156
|
+
def calculate_sma_pandas(self,symbol, klines, period) -> pd.Series:
|
171
157
|
"""
|
172
158
|
使用 pandas 计算 SMA
|
173
159
|
:param KLines K线
|
174
160
|
:param period: SMA 周期
|
175
161
|
:return: SMA 值
|
176
162
|
"""
|
177
|
-
|
178
|
-
df = pd.DataFrame(
|
179
|
-
sma = df['close'].rolling(window=period).mean()
|
163
|
+
|
164
|
+
df = pd.DataFrame(klines, columns=['timestamp', 'open', 'high', 'low', 'close', 'volume'])
|
165
|
+
sma = df['close'].rolling(window=period).mean()
|
180
166
|
return sma
|
181
167
|
|
182
|
-
def calculate_ema_pandas(self,symbol,
|
168
|
+
def calculate_ema_pandas(self,symbol, klines, period) -> pd.Series:
|
183
169
|
"""
|
184
170
|
使用 pandas 计算 EMA
|
185
171
|
:param KLines K线
|
186
172
|
:param period: EMA 周期
|
187
173
|
:return: EMA 值
|
188
174
|
"""
|
189
|
-
|
190
|
-
df = pd.DataFrame(
|
175
|
+
|
176
|
+
df = pd.DataFrame(klines, columns=['timestamp', 'open', 'high', 'low', 'close', 'volume'])
|
191
177
|
# 计算EMA
|
192
|
-
ema = df['close'].ewm(span=period, adjust=False).mean()
|
178
|
+
ema = df['close'].ewm(span=period, adjust=False).mean()
|
193
179
|
return ema
|
194
180
|
|
195
181
|
def calculate_average_amplitude(self,klines, period=60):
|
@@ -202,23 +188,187 @@ class ThreeLineOrdergBot:
|
|
202
188
|
amplitudes.append(amplitude)
|
203
189
|
average_amplitude = sum(amplitudes) / len(amplitudes)
|
204
190
|
return average_amplitude
|
191
|
+
|
192
|
+
def calculate_range_diff(self,prices:pd.Series) -> float:
|
193
|
+
"""
|
194
|
+
计算价格列表中最后一个价格与第一个价格的差值。
|
195
|
+
Args:
|
196
|
+
prices: 价格列表。
|
197
|
+
Returns:
|
198
|
+
diff: 计算最高价列的最大值与最小值的差值
|
199
|
+
。
|
200
|
+
"""
|
201
|
+
if prices.empty:
|
202
|
+
return None
|
203
|
+
# 将价格列表转换为pandas Series格式
|
204
|
+
|
205
|
+
diff = prices.max() - prices.min()
|
206
|
+
|
207
|
+
return diff
|
205
208
|
|
206
|
-
def
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
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
|
+
|
232
|
+
# 定义根据均线斜率判断 K 线方向的函数: 0 空 1 多 -1 平
|
233
|
+
def judge_k_line_direction(self, symbol, pair_config, ema: pd.Series, klines) -> int:
|
234
|
+
"""
|
235
|
+
判断K线方向
|
236
|
+
Args:
|
237
|
+
symbol: 交易对
|
238
|
+
pair_config: 配置参数
|
239
|
+
ema: EMA数据
|
240
|
+
Returns:
|
241
|
+
int: -1:平, 0:空, 1:多
|
242
|
+
"""
|
243
|
+
# 获取配置参数
|
244
|
+
period = int(pair_config.get('ema_range_period', 3))
|
245
|
+
|
246
|
+
# precision= self.get_precision_length(symbol)
|
247
|
+
|
248
|
+
ema_4_diff = ema.diff().tail(period)
|
249
|
+
|
250
|
+
direction = None
|
251
|
+
if all(ema_4_diff <= 0) :
|
252
|
+
# 下降趋势
|
253
|
+
direction = 0
|
254
|
+
elif all(ema_4_diff >= 0) :
|
255
|
+
# 上升趋势
|
256
|
+
direction = 1
|
257
|
+
else:
|
258
|
+
# 震荡趋势
|
259
|
+
direction = -1
|
260
|
+
self.logger.debug(f"{symbol}: K线极差={ema_4_diff.map('{:.9f}'.format).values} ,K线方向={direction}")
|
261
|
+
return direction
|
262
|
+
|
263
|
+
def judge_ema_direction(self, symbol, pair_config, ema: pd.Series) -> int:
|
264
|
+
"""
|
265
|
+
判断EMA方向
|
266
|
+
Args:
|
267
|
+
symbol: 交易对
|
268
|
+
pair_config: 配置参数
|
269
|
+
ema: EMA数据
|
270
|
+
Returns:
|
271
|
+
int: -1:平, 0:空, 1:多
|
272
|
+
"""
|
273
|
+
# 获取配置参数
|
274
|
+
period = int(pair_config.get('ema_range_period', 3))
|
275
|
+
|
276
|
+
precision= self.get_precision_length(symbol)
|
277
|
+
|
278
|
+
ema_4_diff = ema.round(precision).diff().tail(period)
|
279
|
+
|
280
|
+
direction = None
|
281
|
+
if all(ema_4_diff <= 0) and any(ema_4_diff < 0) :
|
282
|
+
# 下降趋势
|
283
|
+
direction = 0
|
284
|
+
elif all(ema_4_diff >= 0) and any(ema_4_diff > 0) :
|
285
|
+
# 上升趋势
|
286
|
+
direction = 1
|
287
|
+
# 都是 (0 0 0) 或 (+ 0 -) 这两种情况认为都是震荡
|
288
|
+
else:
|
289
|
+
# 震荡趋势
|
290
|
+
direction = -1
|
291
|
+
self.logger.debug(f"{symbol}: EMA极差={ema_4_diff.map('{:.4f}'.format).values} ,EMA方向={direction}")
|
292
|
+
return direction
|
293
|
+
|
294
|
+
def judge_cross_direction(self,fastklines,slowklines) :
|
295
|
+
# 创建DataFrame
|
296
|
+
df = pd.DataFrame({
|
297
|
+
'fast': fastklines,
|
298
|
+
'slow': slowklines
|
299
|
+
})
|
300
|
+
|
301
|
+
# 判断金叉和死叉
|
302
|
+
df['golden_cross'] = (df['fast'] > df['slow']) & (df['fast'].shift(1) < df['slow'].shift(1))
|
303
|
+
df['death_cross'] = (df['fast'] < df['slow']) & (df['fast'].shift(1) > df['slow'].shift(1))
|
304
|
+
|
305
|
+
# 从后往前找最近的交叉点
|
306
|
+
last_golden = df['golden_cross'].iloc[::-1].idxmax() if df['golden_cross'].any() else None
|
307
|
+
last_death = df['death_cross'].iloc[::-1].idxmax() if df['death_cross'].any() else None
|
308
|
+
|
309
|
+
# 判断最近的交叉类型
|
310
|
+
if last_golden is None and last_death is None:
|
311
|
+
return {
|
312
|
+
'cross': -1, # 无交叉
|
313
|
+
'index': None
|
211
314
|
}
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
315
|
+
|
316
|
+
# 如果金叉更近或只有金叉
|
317
|
+
if last_golden is not None and (last_death is None or last_golden > last_death):
|
318
|
+
return {
|
319
|
+
'cross': 1, # 金叉
|
320
|
+
'index': last_golden
|
321
|
+
}
|
322
|
+
# 如果死叉更近或只有死叉
|
323
|
+
else:
|
324
|
+
return {
|
325
|
+
'cross': 0, # 死叉
|
326
|
+
'index': last_death
|
327
|
+
}
|
328
|
+
|
329
|
+
def judge_ma_apex(self,symbol,pair_config, fastklines,slowklines) -> bool:
|
330
|
+
period = int(pair_config.get('ema_range_period', 3))
|
331
|
+
precision= self.get_precision_length(symbol)
|
332
|
+
|
333
|
+
df = pd.DataFrame({
|
334
|
+
'ema': fastklines,
|
335
|
+
'sma': slowklines
|
336
|
+
})
|
337
|
+
# 快线和慢线的差值
|
338
|
+
# 将ema和sma转换为tick_size精度
|
339
|
+
# 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)))
|
340
|
+
df['diff'] = df['ema'].round(precision)-df['sma'].round(precision)
|
341
|
+
df['ema_diff'] = df['ema'] - df['ema'].shift(1)
|
342
|
+
df['sma_diff'] = df['sma'] - df['sma'].shift(1)
|
343
|
+
# 计算斜率,【正】表示两线距离扩张,【负】表示两线距离收缩
|
344
|
+
df['slope'] = df['diff'].abs().diff().round(4)
|
345
|
+
|
346
|
+
self.logger.debug(f"{symbol}: slopes = \n{df[['ema','ema_diff','sma','sma_diff','diff','slope']].iloc[-6:-1]} ")
|
347
|
+
|
348
|
+
# 两条线的距离是扩张状态还是收缩状态 true 是收缩 flase 是扩张
|
349
|
+
is_expanding_or_contracting = all(df['slope'].tail(period) <= 0 ) and any(df['slope'].tail(period) < 0)
|
221
350
|
|
351
|
+
return is_expanding_or_contracting
|
352
|
+
|
353
|
+
def judge_range_diff(self,symbol,pair_config,prices:pd.Series) -> bool:
|
354
|
+
"""
|
355
|
+
计算价格列表中最后一个价格与第一个价格的差值。
|
356
|
+
Args:
|
357
|
+
prices: 价格列表。
|
358
|
+
Returns:
|
359
|
+
diff: 计算最高价列的最大值与最小值的差值
|
360
|
+
。
|
361
|
+
"""
|
362
|
+
limit = int(pair_config.get('ema_range_limit', 1))
|
363
|
+
period = int(pair_config.get('ema_range_period', 3))
|
364
|
+
tick_size = self.get_tick_size(symbol)
|
365
|
+
if prices.empty:
|
366
|
+
return None
|
367
|
+
|
368
|
+
diff = prices.tail(period).max() - prices.tail(period).min()
|
369
|
+
self.logger.debug(f"{symbol}: 最高价列的最大值与最小值的差值 = {diff:.9f}")
|
370
|
+
return abs(diff) <= tick_size * limit
|
371
|
+
|
222
372
|
def set_leverage(self,symbol, leverage, mgnMode='isolated',posSide=None):
|
223
373
|
try:
|
224
374
|
# 设置杠杆
|
@@ -255,7 +405,6 @@ class ThreeLineOrdergBot:
|
|
255
405
|
self.logger.error(f"{symbol} 检查持仓失败: {str(e)}")
|
256
406
|
return False
|
257
407
|
|
258
|
-
|
259
408
|
def place_order(self,symbol, price, amount_usdt, side):
|
260
409
|
|
261
410
|
|
@@ -312,147 +461,24 @@ class ThreeLineOrdergBot:
|
|
312
461
|
# self.logger.debug(f"{symbol} ++ Order placed rs : {order_result}")
|
313
462
|
except Exception as e:
|
314
463
|
self.logger.error(f"{symbol} Failed to place order: {e}")
|
315
|
-
self.logger.info(f"--------- ++ {symbol} Order placed done! --------")
|
316
|
-
|
317
|
-
# 定义根据均线斜率判断 K 线方向的函数: 0 空 1 多 -1 平
|
318
|
-
def judge_k_line_direction(self,symbol, pair_config, ema:pd.Series) -> int:
|
319
|
-
"""
|
320
|
-
判断K线方向
|
321
|
-
Args:
|
322
|
-
symbol: 交易对
|
323
|
-
pair_config: 配置参数
|
324
|
-
ema: EMA数据
|
325
|
-
Returns:
|
326
|
-
int: -1:平, 0:空, 1:多
|
327
|
-
"""
|
328
|
-
def check_ema_range(ema_data: pd.Series, period: int, limit: float, tick_size: float) -> bool:
|
329
|
-
"""检查EMA是否在指定范围内震荡"""
|
330
|
-
ema_window = ema_data[-period:]
|
331
|
-
price_range = ema_window.max() - ema_window.min()
|
332
|
-
return abs(price_range) <= limit * tick_size
|
333
|
-
|
334
|
-
def get_trend_direction(slope: float) -> int:
|
335
|
-
"""根据斜率判断趋势方向"""
|
336
|
-
if slope > 0:
|
337
|
-
return 1 # 上升趋势
|
338
|
-
elif slope < 0:
|
339
|
-
return 0 # 下降趋势
|
340
|
-
return -1 # 震荡趋势
|
341
|
-
|
342
|
-
# 获取配置参数
|
343
|
-
tick_size = self.get_tick_size(symbol)
|
344
|
-
ema_range_period = int(pair_config.get('ema_range_period', 3))
|
345
|
-
ema_range_limit = float(pair_config.get('ema_range_limit', 1))
|
346
|
-
|
347
|
-
# 判断是否在震荡区间
|
348
|
-
if check_ema_range(ema, ema_range_period, ema_range_limit, tick_size):
|
349
|
-
direction = -1
|
350
|
-
else:
|
351
|
-
# 计算最新斜率并判断方向
|
352
|
-
latest_slope = ema.diff().iloc[-1]
|
353
|
-
direction = get_trend_direction(latest_slope)
|
354
|
-
|
355
|
-
self.logger.debug(f"{symbol}: 极差={abs(ema[-ema_range_period:].max() - ema[-ema_range_period:].min()):.9f} "
|
356
|
-
f"斜率={ema.diff().iloc[-1]:.9f}, K线方向 {direction}")
|
357
|
-
|
358
|
-
return direction
|
464
|
+
self.logger.info(f"--------- ++ {symbol} Order placed done! --------")
|
359
465
|
|
360
|
-
def
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
})
|
366
|
-
|
367
|
-
# 判断金叉和死叉
|
368
|
-
df['golden_cross'] = (df['fast'] > df['slow']) & (df['fast'].shift(1) < df['slow'].shift(1))
|
369
|
-
df['death_cross'] = (df['fast'] < df['slow']) & (df['fast'].shift(1) > df['slow'].shift(1))
|
370
|
-
|
371
|
-
# 从后往前找最近的交叉点
|
372
|
-
last_golden = df['golden_cross'].iloc[::-1].idxmax() if df['golden_cross'].any() else None
|
373
|
-
last_death = df['death_cross'].iloc[::-1].idxmax() if df['death_cross'].any() else None
|
374
|
-
|
375
|
-
# 判断最近的交叉类型
|
376
|
-
if last_golden is None and last_death is None:
|
377
|
-
return {
|
378
|
-
'cross': -1, # 无交叉
|
379
|
-
'index': None
|
380
|
-
}
|
381
|
-
|
382
|
-
# 如果金叉更近或只有金叉
|
383
|
-
if last_golden is not None and (last_death is None or last_golden > last_death):
|
384
|
-
return {
|
385
|
-
'cross': 1, # 金叉
|
386
|
-
'index': last_golden
|
387
|
-
}
|
388
|
-
# 如果死叉更近或只有死叉
|
389
|
-
else:
|
390
|
-
return {
|
391
|
-
'cross': 0, # 死叉
|
392
|
-
'index': last_death
|
466
|
+
def cancel_all_orders(self,symbol):
|
467
|
+
try:
|
468
|
+
# 获取所有未完成订单
|
469
|
+
params = {
|
470
|
+
# 'instId': instId
|
393
471
|
}
|
472
|
+
open_orders = self.exchange.fetch_open_orders(symbol=symbol,params=params)
|
473
|
+
|
474
|
+
# 取消每个订单
|
475
|
+
for order in open_orders:
|
476
|
+
self.exchange.cancel_order(order['id'], symbol,params=params)
|
477
|
+
|
478
|
+
self.logger.info(f"{symbol} 挂单取消成功.")
|
479
|
+
except Exception as e:
|
480
|
+
self.logger.error(f"{symbol} 取消订单失败: {str(e)}")
|
394
481
|
|
395
|
-
def judge_ma_apex(self,symbol, fastklines,slowklines) -> bool:
|
396
|
-
|
397
|
-
df = pd.DataFrame({
|
398
|
-
'ema': fastklines,
|
399
|
-
'sma': slowklines
|
400
|
-
})
|
401
|
-
# 快线和慢线的差值
|
402
|
-
# 将ema和sma转换为tick_size精度
|
403
|
-
# 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)))
|
404
|
-
df['diff'] = df['ema']-df['sma']
|
405
|
-
# 计算斜率,【正】表示两线距离扩张,【负】表示两线距离收缩
|
406
|
-
df['slope'] = df['diff'].abs().diff().round(4)
|
407
|
-
df['flag'] = df['slope'] <= 0.0
|
408
|
-
|
409
|
-
self.logger.debug(f"{symbol}: slopes = \n{df[['ema','sma','diff','slope','flag']].iloc[-6:-1]} ")
|
410
|
-
# 检查最后两个斜率是否都为负
|
411
|
-
# 取slopes最新的第2个和第3个值进行判断
|
412
|
-
|
413
|
-
return all(slope <= 0.0 for slope in df['slope'].iloc[-3:-1])
|
414
|
-
|
415
|
-
|
416
|
-
def calculate_range_diff(self,prices:pd.Series) -> float:
|
417
|
-
"""
|
418
|
-
计算价格列表中最后一个价格与第一个价格的差值。
|
419
|
-
Args:
|
420
|
-
prices: 价格列表。
|
421
|
-
Returns:
|
422
|
-
diff: 计算最高价列的最大值与最小值的差值
|
423
|
-
。
|
424
|
-
"""
|
425
|
-
if prices.empty:
|
426
|
-
return None
|
427
|
-
# 将价格列表转换为pandas Series格式
|
428
|
-
|
429
|
-
diff = prices.max() - prices.min()
|
430
|
-
|
431
|
-
return diff
|
432
|
-
|
433
|
-
def calculate_place_order_price(self, symbol,side,base_price, amplitude_limit, offset=1) -> float:
|
434
|
-
"""
|
435
|
-
计算开仓价格
|
436
|
-
Args:
|
437
|
-
symbol: 交易对
|
438
|
-
side: 开仓方向
|
439
|
-
base_price: 开盘价格
|
440
|
-
amplitude_limit: 振幅限制
|
441
|
-
offset: 偏移量
|
442
|
-
Returns:
|
443
|
-
place_order_price: 开仓价格
|
444
|
-
"""
|
445
|
-
tick_size = float(self.exchange.market(symbol)['precision']['price'])
|
446
|
-
place_order_price = None
|
447
|
-
# 计算止盈价格,用市场价格(取持仓期间历史最高)减去开仓价格的利润,再乘以不同阶段的止盈百分比。
|
448
|
-
|
449
|
-
if side == 'buy':
|
450
|
-
place_order_price = base_price * (1- amplitude_limit/100) - offset * tick_size
|
451
|
-
else:
|
452
|
-
place_order_price = base_price * (1 + amplitude_limit/100) + offset * tick_size
|
453
|
-
self.logger.debug(f"++++ {symbol} 下单价格: {place_order_price:.9f} 方向 {side} 基准价格{base_price} 振幅限制 {amplitude_limit} ")
|
454
|
-
return float(self.round_price_to_tick(place_order_price,tick_size))
|
455
|
-
|
456
482
|
def process_pair(self,symbol,pair_config):
|
457
483
|
# 检查是否有持仓,有持仓不进行下单
|
458
484
|
if self.check_position(symbol=symbol) :
|
@@ -474,8 +500,8 @@ class ThreeLineOrdergBot:
|
|
474
500
|
sma_length = pair_config.get('sma', 50)
|
475
501
|
|
476
502
|
# 增加 金叉死叉 方向确认的 20250209
|
477
|
-
fastk = self.calculate_ema_pandas(symbol, klines, period=ema_length)
|
478
|
-
slowk = self.calculate_sma_pandas(symbol, klines, period=sma_length)
|
503
|
+
fastk = self.calculate_ema_pandas(symbol=symbol, klines=klines, period=ema_length)
|
504
|
+
slowk = self.calculate_sma_pandas(symbol=symbol, klines=klines, period=sma_length)
|
479
505
|
|
480
506
|
cross_direction = self.judge_cross_direction(fastklines=fastk,slowklines=slowk)
|
481
507
|
# 更新交叉状态
|
@@ -487,27 +513,37 @@ class ThreeLineOrdergBot:
|
|
487
513
|
|
488
514
|
|
489
515
|
# 判断趋势:多头趋势或空头趋势
|
490
|
-
direction = self.judge_k_line_direction(symbol=symbol, pair_config=pair_config,ema=fastk)
|
516
|
+
direction = self.judge_k_line_direction(symbol=symbol, pair_config=pair_config,ema=fastk,klines=klines)
|
491
517
|
if direction == 1:
|
492
518
|
is_bullish_trend = True
|
493
519
|
elif direction == 0:
|
494
520
|
is_bearish_trend = True
|
495
521
|
|
496
522
|
# 结合金叉死叉判断是否是周期顶部和底部
|
497
|
-
is_apex = self.judge_ma_apex(symbol=symbol,fastklines=fastk,slowklines=slowk)
|
523
|
+
is_apex = self.judge_ma_apex(symbol=symbol,pair_config=pair_config, fastklines=fastk,slowklines=slowk)
|
524
|
+
ema_direction = self.judge_ema_direction(symbol=symbol, pair_config=pair_config,ema=fastk)
|
525
|
+
if_inner_range = self.judge_range_diff(symbol=symbol, pair_config=pair_config, prices=fastk)
|
498
526
|
# 金叉死叉逻辑
|
499
527
|
if last_cross_direction and last_cross_direction['cross'] == 1 : # 金叉
|
500
528
|
self.logger.debug(f"{symbol} 金叉:{last_cross_direction},清理空单,挂多单!!")
|
501
529
|
is_bearish_trend = False
|
502
|
-
|
503
|
-
|
530
|
+
# 强校验下单条件
|
531
|
+
if is_apex or ema_direction == -1 or if_inner_range:
|
532
|
+
self.logger.debug(f"{symbol} 强校验 - 死叉:{last_cross_direction},两线收缩={is_apex} ,ema_平={ema_direction},均线振幅={if_inner_range} ,不开单!!")
|
533
|
+
# 弱校验下单条件
|
534
|
+
# if is_apex or ema_direction == -1:
|
535
|
+
# self.logger.debug(f"{symbol} 金叉:{last_cross_direction},两线收缩={is_apex} ,ema_平={ema_direction},不开单!!")
|
504
536
|
is_bullish_trend = False
|
505
537
|
|
506
538
|
elif last_cross_direction and last_cross_direction['cross'] == 0 : # 死叉
|
507
539
|
self.logger.debug(f"{symbol} 死叉:{last_cross_direction},清理多单,挂空单!!")
|
508
540
|
is_bullish_trend = False
|
509
|
-
|
510
|
-
|
541
|
+
# 强校验下单条件
|
542
|
+
if is_apex or ema_direction == -1 or if_inner_range :
|
543
|
+
self.logger.debug(f"{symbol} 强校验 - 死叉:{last_cross_direction},两线收缩={is_apex} ,ema_平={ema_direction},均线振幅={if_inner_range} ,不开单!!")
|
544
|
+
# 弱校验下单条件
|
545
|
+
# if is_apex or ema_direction == -1:
|
546
|
+
# self.logger.debug(f"{symbol} 死叉:{last_cross_direction},两线收缩={is_apex} ,ema_平={ema_direction},不开单!!")
|
511
547
|
is_bearish_trend = False
|
512
548
|
|
513
549
|
else:
|
@@ -535,9 +571,7 @@ class ThreeLineOrdergBot:
|
|
535
571
|
|
536
572
|
amplitude_limit = pair_config.get('amplitude_limit', 0.32)
|
537
573
|
|
538
|
-
self.logger.debug(f"{symbol} 当前K线的前三根K线 最高价: {max_high}, 最低价: {min_low}")
|
539
|
-
|
540
|
-
|
574
|
+
self.logger.debug(f"{symbol} 当前K线的前三根K线 最高价: {max_high}, 最低价: {min_low}")
|
541
575
|
|
542
576
|
long_amount_usdt = pair_config.get('long_amount_usdt', 5)
|
543
577
|
short_amount_usdt = pair_config.get('short_amount_usdt', 5)
|
@@ -550,6 +584,7 @@ class ThreeLineOrdergBot:
|
|
550
584
|
close_price = klines[-1][4]
|
551
585
|
self.logger.debug(f"-- {symbol} 最新K线 {klines[-1]}")
|
552
586
|
|
587
|
+
# FIXME calculate_range_diff 去掉
|
553
588
|
if is_bullish_trend:
|
554
589
|
diff = self.calculate_range_diff(prices=low_prices)
|
555
590
|
cur_amplitude_limit = diff / close_price * 100
|
@@ -579,8 +614,6 @@ class ThreeLineOrdergBot:
|
|
579
614
|
self.logger.error(error_message,exc_info=True)
|
580
615
|
traceback.print_exc()
|
581
616
|
self.send_feishu_notification(error_message)
|
582
|
-
|
583
|
-
|
584
617
|
|
585
618
|
def monitor_klines(self):
|
586
619
|
symbols = list(self.trading_pairs_config.keys()) # 获取所有币对的ID
|
@@ -1,4 +1,4 @@
|
|
1
|
-
maker/ThreeLineOrderBot.py,sha256=
|
1
|
+
maker/ThreeLineOrderBot.py,sha256=UBWtLMJtL6mAS4CLYThja5Z_XE7UCD4bBhik0T0Xp0s,27521
|
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.0.
|
11
|
-
openfund_maker-1.0.
|
12
|
-
openfund_maker-1.0.
|
13
|
-
openfund_maker-1.0.
|
10
|
+
openfund_maker-1.1.0.dist-info/METADATA,sha256=y6UyUbgh-IJwrJiklJxR4mBCK-SQg56J2EpDI8cIIVc,1965
|
11
|
+
openfund_maker-1.1.0.dist-info/WHEEL,sha256=IYZQI976HJqqOpQU6PHkJ8fb3tMNBFjg-Cn-pwAbaFM,88
|
12
|
+
openfund_maker-1.1.0.dist-info/entry_points.txt,sha256=gKMytICEKcMRFQDFkHZLnIpID7UQFoTIM_xcpiiV6Ns,50
|
13
|
+
openfund_maker-1.1.0.dist-info/RECORD,,
|
File without changes
|
File without changes
|