openfund-taker 1.0.12__py3-none-any.whl → 1.0.14__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: openfund-taker
3
- Version: 1.0.12
3
+ Version: 1.0.14
4
4
  Summary: Openfund-taker
5
5
  Requires-Python: >=3.9,<4.0
6
6
  Classifier: Programming Language :: Python :: 3
@@ -1,4 +1,4 @@
1
- taker/MultiAssetNewTradingBot.py,sha256=tPalEDPge_lfXP7yOdoYpgT8Mo-GGkoOhRhWdSg6mPY,26459
1
+ taker/MultiAssetNewTradingBot.py,sha256=KLwSZmrrrMX78pFlbZz51j3C_i7wZtQF8kjbEAIWzEM,35044
2
2
  taker/MultiAssetOldTradingBot.py,sha256=uBh_BxglvcbaHIsWHM7GI9Qa_QjzsxXaXJAAWEOMO5c,15315
3
3
  taker/ThreeLineTradingBot.py,sha256=oXIoQ8z9AzKzk0z13d0ufj2KGBOk5iHJTJNZQRDKA5U,20625
4
4
  taker/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -8,8 +8,8 @@ taker/chua_ok.py,sha256=5pPAoEYbFuKxfZwqNvOO890s-2cy6n69QiI0ZA0GTCQ,12474
8
8
  taker/chua_ok_all.py,sha256=2XnZM6QdB3juSE1pqQIJyh2x1XuhlTlnBKNA3owlJ9E,15267
9
9
  taker/chua_ok_bot.py,sha256=9SW0ujhi6PfN4yR1JZ9NaA37HtnXJ2QAWUfW52NG68w,13109
10
10
  taker/config.py,sha256=YPxghO5i0vgRg9Cja8kGj9O7pgSbbtzOgf3RexqXXwY,1188
11
- taker/main.py,sha256=3Wr5YzL3BliXCqwXBVQET4lhVNusmUhheWXyQQkGN1o,1975
12
- openfund_taker-1.0.12.dist-info/METADATA,sha256=ht_-aBM6Kcf6Vmc4AesUVyG3Pjmcfo1wDy_Uc7l-Qv8,7503
13
- openfund_taker-1.0.12.dist-info/WHEEL,sha256=IYZQI976HJqqOpQU6PHkJ8fb3tMNBFjg-Cn-pwAbaFM,88
14
- openfund_taker-1.0.12.dist-info/entry_points.txt,sha256=a7mG8F7aOA5-Gk2vPWuAR4537faxaHUgM_jwIDBZoEc,50
15
- openfund_taker-1.0.12.dist-info/RECORD,,
11
+ taker/main.py,sha256=8cLWzEvQDeELbY5Av7JqkEyYbaNqSbAbVl1tQHXzU8s,1954
12
+ openfund_taker-1.0.14.dist-info/METADATA,sha256=-24dsmCAqfnFGh9mZVYMe4qzQRqWYpbYM6iFHsPUQKc,7503
13
+ openfund_taker-1.0.14.dist-info/WHEEL,sha256=IYZQI976HJqqOpQU6PHkJ8fb3tMNBFjg-Cn-pwAbaFM,88
14
+ openfund_taker-1.0.14.dist-info/entry_points.txt,sha256=a7mG8F7aOA5-Gk2vPWuAR4537faxaHUgM_jwIDBZoEc,50
15
+ openfund_taker-1.0.14.dist-info/RECORD,,
@@ -2,37 +2,42 @@
2
2
  import ccxt
3
3
  import time
4
4
  import requests
5
+ import traceback
6
+ import pandas as pd
5
7
 
6
8
  class MultiAssetNewTradingBot:
7
- def __init__(self, config, feishu_webhook=None, monitor_interval=4,logger=None):
8
- self.stop_loss_pct = config["all_stop_loss_pct"] # 全局止损百分比
9
+ def __init__(self,g_config, platform_config, feishu_webhook=None, monitor_interval=4,logger=None):
10
+ self.trading_pairs_config = g_config.get('tradingPairs', {})
9
11
 
12
+ self.stop_loss_pct = platform_config["all_stop_loss_pct"] # 全局止损百分比
10
13
  # 止盈比例
11
- self.low_trail_stop_loss_pct = config["all_low_trail_stop_loss_pct"] # 第一档
12
- self.trail_stop_loss_pct = config["all_trail_stop_loss_pct"]# 第二档
13
- self.higher_trail_stop_loss_pct = config["all_higher_trail_stop_loss_pct"]# 第三档
14
+ self.low_trail_stop_loss_pct = platform_config["all_low_trail_stop_loss_pct"] # 第一档
15
+ self.trail_stop_loss_pct = platform_config["all_trail_stop_loss_pct"]# 第二档
16
+ self.higher_trail_stop_loss_pct = platform_config["all_higher_trail_stop_loss_pct"]# 第三档
14
17
  # 止盈阈值
15
- self.low_trail_profit_threshold = config["all_low_trail_profit_threshold"]# 第一档
16
- self.first_trail_profit_threshold = config["all_first_trail_profit_threshold"]# 第二档
17
- self.second_trail_profit_threshold = config["all_second_trail_profit_threshold"]# 第三档
18
+ self.low_trail_profit_threshold = platform_config["all_low_trail_profit_threshold"]# 第一档
19
+ self.first_trail_profit_threshold = platform_config["all_first_trail_profit_threshold"]# 第二档
20
+ self.second_trail_profit_threshold = platform_config["all_second_trail_profit_threshold"]# 第三档
18
21
 
19
22
  self.feishu_webhook = feishu_webhook
20
23
  self.monitor_interval = monitor_interval # 监控循环时间是分仓监控的3倍
21
- self.highest_total_profit = 0 # 记录最高总盈利
22
- self.current_tier = "无"
23
-
24
24
 
25
+ self.highest_total_profit = 0 # 记录最高总盈利
26
+ self.current_tier = "无" # 记录当前的仓位模式
27
+
25
28
  self.global_symbol_stop_loss_flag = {} # 记录每个symbol是否设置全局止损
26
29
  self.global_symbol_take_profit_price = {} # 记录每个symbol的止盈价格
27
30
  # 保留在止盈挂单中最高最低两个价格,计算止盈价格。
28
31
  self.max_market_price = 0.0
29
32
  self.min_market_price = float('inf') # 初始化为浮点数最大值
33
+
34
+ self.cross_directions = {} # 持仓期间,存储每个交易对的交叉方向
30
35
 
31
36
  # 配置交易所
32
37
  self.exchange = ccxt.okx({
33
- 'apiKey': config["apiKey"],
34
- 'secret': config["secret"],
35
- 'password': config["password"],
38
+ 'apiKey': platform_config["apiKey"],
39
+ 'secret': platform_config["secret"],
40
+ 'password': platform_config["password"],
36
41
  'timeout': 3000,
37
42
  'rateLimit': 50,
38
43
  'options': {'defaultType': 'future'},
@@ -40,8 +45,18 @@ class MultiAssetNewTradingBot:
40
45
  })
41
46
  self.logger = logger
42
47
  self.position_mode = self.get_position_mode() # 获取持仓模式
43
-
44
-
48
+ # 获取市场信息
49
+ def getMarket(self,symbol):
50
+ self.exchange.load_markets()
51
+ return self.exchange.market(symbol)
52
+ # 获取tick_size
53
+ def get_tick_size(self,symbol):
54
+ return float(self.getMarket(symbol)['precision']['price'])
55
+ # 获取价格精度
56
+ def get_precision_length(self,symbol) -> int:
57
+ tick_size = self.get_tick_size(symbol)
58
+ return len(f"{tick_size:.10f}".rstrip('0').split('.')[1]) if '.' in f"{tick_size:.10f}" else 0
59
+ # 获取当前持仓模式
45
60
  def get_position_mode(self):
46
61
  try:
47
62
  # 假设获取账户持仓模式的 API
@@ -89,29 +104,186 @@ class MultiAssetNewTradingBot:
89
104
  self.logger.error(f"Error fetching open orders: {e}")
90
105
  return []
91
106
 
92
- # def cancel_all_orders(self,symbol):
93
- # params = {}
94
- # orders = self.fetch_open_orders(symbol=symbol,params=params)
95
- # # 如果没有委托订单则直接返回
96
- # if not orders:
97
- # self.global_symbol_stop_loss_flag.clear()
98
- # self.logger.debug(f"{symbol} 无挂单列表。")
99
- # return
107
+ def get_historical_klines(self,symbol, bar='1m', limit=241):
108
+ # response = market_api.get_candlesticks(instId, bar=bar, limit=limit)
109
+ params = {
110
+ # 'instId': instId,
111
+ }
112
+ klines = self.exchange.fetch_ohlcv(symbol, timeframe=bar,limit=limit,params=params)
113
+ # if 'data' in response and len(response['data']) > 0:
114
+ if klines :
115
+ # return response['data']
116
+ return klines
117
+ else:
118
+ raise ValueError("Unexpected response structure or missing candlestick data")
119
+
120
+ def judge_cross_direction(self,fastklines,slowklines) :
121
+ # 创建DataFrame
122
+ df = pd.DataFrame({
123
+ 'fast': fastklines,
124
+ 'slow': slowklines
125
+ })
126
+
127
+ # 判断金叉和死叉
128
+ df['golden_cross'] = (df['fast'] > df['slow']) & (df['fast'].shift(1) < df['slow'].shift(1))
129
+ df['death_cross'] = (df['fast'] < df['slow']) & (df['fast'].shift(1) > df['slow'].shift(1))
130
+
131
+ # 从后往前找最近的交叉点
132
+ last_golden = df['golden_cross'].iloc[::-1].idxmax() if df['golden_cross'].any() else None
133
+ last_death = df['death_cross'].iloc[::-1].idxmax() if df['death_cross'].any() else None
134
+
135
+ # 判断最近的交叉类型
136
+ if last_golden is None and last_death is None:
137
+ return {
138
+ 'cross': -1, # 无交叉
139
+ 'index': None
140
+ }
141
+
142
+ # 如果金叉更近或只有金叉
143
+ if last_golden is not None and (last_death is None or last_golden > last_death):
144
+ return {
145
+ 'cross': 1, # 金叉
146
+ 'index': last_golden
147
+ }
148
+ # 如果死叉更近或只有死叉
149
+ else:
150
+ return {
151
+ 'cross': 0, # 死叉
152
+ 'index': last_death
153
+ }
154
+
155
+
156
+ def judge_ma_apex(self,symbol, fastklines,slowklines) -> bool:
157
+ df = pd.DataFrame({
158
+ 'ema': fastklines,
159
+ 'sma': slowklines
160
+ })
161
+
162
+ # 快线和慢线的差值
163
+ df['diff'] = df['ema']-df['sma']
164
+ # 计算斜率,【正】表示两线距离扩张,【负】表示两线距离收缩
165
+ df['slope'] = df['diff'].abs().diff().round(4)
166
+ df['flag'] = df['slope'] <= 0.0
167
+
168
+ self.logger.debug(f"{symbol}: slopes = \n{df[['ema','sma','diff','slope','flag']].iloc[-6:-1]} ")
169
+ # 检查最后两个斜率是否都为负
170
+ # 取slopes最新的第2个和第3个值进行判断
171
+ # 20250213 因为有持仓,因此判定条件更严谨,只有收缩才平仓
172
+ return all(slope < 0.0 for slope in df['slope'].iloc[-3:-1])
173
+
174
+ # 定义根据均线斜率判断 K 线方向的函数: 0 空 1 多 -1 平
175
+
176
+ # 定义根据均线斜率判断 K 线方向的函数: 0 空 1 多 -1 平
177
+ def judge_k_line_direction(self,symbol, pair_config, ema:pd.Series) -> int:
178
+ """
179
+ 判断K线方向
180
+ Args:
181
+ symbol: 交易对
182
+ pair_config: 配置参数
183
+ ema: EMA数据
184
+ Returns:
185
+ int: -1:平, 0:空, 1:多
186
+ """
187
+ def check_ema_range(ema_data: pd.Series, period: int, limit: float, tick_size: float) -> bool:
188
+ """检查EMA是否在指定范围内震荡"""
189
+ ema_window = ema_data[-period:]
190
+ price_range = ema_window.max() - ema_window.min()
191
+ return abs(price_range) <= limit * tick_size
192
+
193
+ def get_trend_direction(slope: float) -> int:
194
+ """根据斜率判断趋势方向"""
195
+ if slope > 0:
196
+ return 1 # 上升趋势
197
+ elif slope < 0:
198
+ return 0 # 下降趋势
199
+ return -1 # 震荡趋势
200
+
201
+ # 获取配置参数
202
+ tick_size = self.get_tick_size(symbol)
203
+ ema_range_period = int(pair_config.get('ema_range_period', 3))
204
+ ema_range_limit = float(pair_config.get('ema_range_limit', 1))
100
205
 
101
- # # 提取所有订单ID,包括普通订单和策略订单
102
- # order_ids = []
103
- # for order in orders:
104
- # # 处理订单ID
105
- # if 'id' in order:
106
- # order_ids.append(order['id'])
107
-
108
- # try:
109
- # # 批量取消订单
110
- # self.exchange.cancel_orders(order_ids, symbol=symbol)
111
- # self.logger.info(f"Orders {order_ids} cancelled for {symbol}")
112
- # except Exception as e:
113
- # self.logger.error(f"Error cancelling orders for {symbol}: {e}")
206
+ # 判断是否在震荡区间
207
+ if check_ema_range(ema, ema_range_period, ema_range_limit, tick_size):
208
+ direction = -1
209
+ else:
210
+ # 计算最新斜率并判断方向
211
+ latest_slope = ema.diff().iloc[-1]
212
+ direction = get_trend_direction(latest_slope)
213
+
214
+ self.logger.debug(f"{symbol}: 极差={abs(ema[-ema_range_period:].max() - ema[-ema_range_period:].min()):.9f} "
215
+ f"斜率={ema.diff().iloc[-1]:.9f}, K线方向 {direction}")
216
+
217
+ return direction
218
+
219
+ def check_reverse_position(self,symbol,position,pair_config):
220
+ side = position['side']
221
+ try:
222
+ klines = self.get_historical_klines(symbol=symbol)
114
223
 
224
+ # 计算 快线EMA & 慢线SMA
225
+ ema_length = pair_config.get('ema', 15)
226
+ sma_length = pair_config.get('sma', 50)
227
+
228
+ # 增加 金叉死叉 方向确认的 20250209
229
+ fastk = self.calculate_ema_pandas(symbol, klines, period=ema_length)
230
+ slowk = self.calculate_sma_pandas(symbol, klines, period=sma_length)
231
+
232
+ cross_direction = self.judge_cross_direction(fastklines=fastk,slowklines=slowk)
233
+ # 更新交叉状态
234
+ if cross_direction['cross'] != -1 : #本次不一定有交叉
235
+ self.cross_directions[symbol] = cross_direction
236
+
237
+ # 最新交叉方向
238
+ last_cross_direction = self.exchange.safe_dict(self.cross_directions,symbol,None)
239
+ # 计算 快线EMA & 慢线SMA
240
+ # 结合金叉死叉判断是否是周期顶部和底部
241
+ is_apex = self.judge_ma_apex(symbol=symbol,fastklines=fastk,slowklines=slowk)
242
+
243
+ self.logger.debug(f"{symbol} cross={last_cross_direction['cross']},见顶={is_apex},持仓方向={side}")
244
+ # 金叉逻辑
245
+ if last_cross_direction and last_cross_direction['cross'] == 1 and is_apex and side == 'long': # 金叉
246
+ self.logger.debug(f"{symbol} 金叉:{last_cross_direction['cross']},见顶={is_apex},持仓方向={side},开始清理多单!!")
247
+ self.close_all_positions(symbol=symbol, position=position)
248
+
249
+ # 死叉逻辑
250
+ elif last_cross_direction and last_cross_direction['cross'] == 0 and is_apex and side == 'short':
251
+ self.logger.debug(f"{symbol} 死叉:{last_cross_direction['cross']},见顶={is_apex},持仓方向={side},开始清理空单!!")
252
+ self.close_all_positions(symbol=symbol, position=position)
253
+
254
+ except KeyboardInterrupt:
255
+ self.logger.info("程序收到中断信号,开始退出...")
256
+ except Exception as e:
257
+ error_message = f"程序异常退出: {str(e)}"
258
+ self.logger.error(error_message,exc_info=True)
259
+ traceback.print_exc()
260
+ self.send_feishu_notification(error_message)
261
+
262
+ def calculate_sma_pandas(self,symbol,kLines,period):
263
+ """
264
+ 使用 pandas 计算 SMA
265
+ :param KLines K线
266
+ :param period: SMA 周期
267
+ :return: SMA 值
268
+ """
269
+ precision= self.get_precision_length(symbol)
270
+ df = pd.DataFrame(kLines, columns=['timestamp', 'open', 'high', 'low', 'close', 'volume'])
271
+ sma = df['close'].rolling(window=period).mean().round(precision)
272
+ return sma
273
+
274
+ def calculate_ema_pandas(self,symbol,kLines, period):
275
+ """
276
+ 使用 pandas 计算 EMA
277
+ :param KLines K线
278
+ :param period: EMA 周期
279
+ :return: EMA 值
280
+ """
281
+ precision= self.get_precision_length(symbol)
282
+ df = pd.DataFrame(kLines, columns=['timestamp', 'open', 'high', 'low', 'close', 'volume'])
283
+ # 计算EMA
284
+ ema = df['close'].ewm(span=period, adjust=False).mean().round(precision)
285
+ return ema
286
+
115
287
  # 计算平均利润
116
288
  def calculate_average_profit(self,symbol,position):
117
289
  # positions = self.fetch_positions()
@@ -148,15 +320,15 @@ class MultiAssetNewTradingBot:
148
320
  self.current_tier = "无"
149
321
  self.global_symbol_stop_loss_flag.clear()
150
322
  # self.logger.debug("已重置最高总盈利和档位状态")
151
-
323
+ # FIXME 目前只支持 单symbol
152
324
  def reset_take_profie(self):
153
325
  self.global_symbol_take_profit_price.clear()
154
326
  self.global_symbol_stop_loss_flag.clear()
155
327
  # 保留在止盈挂单中最高最低两个价格,计算止盈价格。
156
328
  self.max_market_price = 0.0
157
329
  self.min_market_price = float('inf') # 初始化为浮点数最大值
158
-
159
-
330
+ self.cross_directions = {}
331
+
160
332
  def round_price_to_tick(self,symbol, price):
161
333
  tick_size = float(self.exchange.market(symbol)['info']['tickSz'])
162
334
  # 计算 tick_size 的小数位数
@@ -166,6 +338,7 @@ class MultiAssetNewTradingBot:
166
338
  adjusted_price = round(price / tick_size) * tick_size
167
339
  return f"{adjusted_price:.{tick_decimals}f}"
168
340
  # 放弃当前委托
341
+
169
342
  def cancel_all_algo_orders(self,symbol):
170
343
 
171
344
  params = {
@@ -331,6 +504,7 @@ class MultiAssetNewTradingBot:
331
504
  return take_profit_price
332
505
 
333
506
  # 平仓
507
+
334
508
  def close_all_positions(self,symbol,position):
335
509
 
336
510
  amount = abs(float(position['contracts']))
@@ -364,35 +538,52 @@ class MultiAssetNewTradingBot:
364
538
  params=params
365
539
  )
366
540
  time.sleep(0.1) # 短暂延迟后再试
367
- self.self.reset_take_profie()
541
+ self.reset_take_profie()
368
542
  self.logger.info(f"{symbol} Close position response for {symbol}: {order}")
369
543
  self.send_feishu_notification(f"{symbol} 平仓订单完全成交 -{symbol} side: {side}")
370
544
 
371
545
  except Exception as e:
372
546
  self.logger.error(f"{symbol} Error closing position for {symbol}: {e}")
373
- self.send_feishu_notification(f"{symbol} Error closing position for {symbol}: {e}")
547
+ self.send_feishu_notification(f"{symbol} Error closing position for {symbol}: {e}")
548
+
549
+ def check_take_profit_trigger(self, symbol: str, position: dict) -> bool:
550
+ """
551
+ 检查是否触发止盈条件
552
+ Args:
553
+ symbol: 交易对
554
+ position: 持仓信息
555
+ Returns:
556
+ bool: 是否需要平仓
557
+ """
558
+ latest_take_profit_price = self.exchange.safe_float(self.global_symbol_take_profit_price, symbol, 0.0)
559
+ if latest_take_profit_price == 0.0:
560
+ self.logger.warning(f"{symbol} 未设置止盈价格,执行平仓")
561
+ return True
374
562
 
375
-
376
- def check_position(self,symbol, position):
377
- # 检查是否全局止损没有被触发的问题,处理持仓没有被执行的情况。
378
- latest_take_profit_price = self.exchange.safe_float(self.global_symbol_take_profit_price,symbol,0.0)
379
- if latest_take_profit_price == 0.0:
380
- self.close_all_positions(symbol, position)
563
+ mark_price = position['markPrice']
564
+ side = position['side']
565
+
566
+ if side == 'long' and mark_price < latest_take_profit_price:
567
+ self.logger.warning(f"!![非正常关闭]: {symbol} 方向 {side} - 市场价格 {mark_price} 低于止盈 {latest_take_profit_price},触发全局止盈")
568
+ return True
569
+ elif side == 'short' and mark_price > latest_take_profit_price:
570
+ self.logger.warning(f"!![非正常关闭]: {symbol} 方向 {side} - 市场价格 {mark_price} 高于止盈价 {latest_take_profit_price},触发全局止盈")
571
+ return True
572
+
573
+ return False
574
+
575
+ def check_position(self, symbol, position):
576
+ # 清理趋势相反的仓位
577
+ pair_config = self.trading_pairs_config.get(symbol, {})
578
+ self.check_reverse_position(symbol=symbol, position=position, pair_config=pair_config)
579
+
580
+ # 检查是否触发止盈
581
+ if self.check_take_profit_trigger(symbol, position):
582
+ self.close_all_positions(symbol=symbol, position=position)
381
583
  return
382
584
 
383
- if position['side'] == 'long':
384
- if position['markPrice'] < latest_take_profit_price:
385
- self.logger.warning(f"!![非正常关闭]: {symbol} 方向 {position['side']} - 市场价格 {position['markPrice']} 低于止止盈 {latest_take_profit_price},触发全局止盈")
386
- self.close_all_positions(symbol, position)
387
- return
388
- elif position['side'] =='short':
389
- if position['markPrice'] > latest_take_profit_price:
390
- self.logger.warning(f"!![非正常关闭]: {symbol} 方向 {position['side']} - 市场价格 {position['markPrice']} 高于止盈价 {latest_take_profit_price},触发全局止盈")
391
- self.close_all_positions(symbol, position)
392
- return
393
585
 
394
- def total_profit(self, symbol, position):
395
-
586
+ def check_total_profit(self, symbol, position):
396
587
 
397
588
  total_profit = self.calculate_average_profit(symbol, position)
398
589
  if total_profit > 0.0 :
@@ -488,8 +679,6 @@ class MultiAssetNewTradingBot:
488
679
 
489
680
  return
490
681
 
491
-
492
-
493
682
  def monitor_total_profit(self):
494
683
  self.logger.info("启动主循环,开始监控总盈利...")
495
684
  previous_position_size = sum(
@@ -513,12 +702,11 @@ class MultiAssetNewTradingBot:
513
702
  previous_position_size = current_position_size
514
703
  time.sleep(0.1)
515
704
  continue # 跳过本次循环
516
-
517
-
518
705
 
519
706
  for position in positions:
520
707
  symbol = position['symbol']
521
- self.total_profit(symbol, position)
708
+ self.check_total_profit(symbol, position)
709
+ # 对有错误的仓位进行处理
522
710
  self.check_position(symbol, position)
523
711
 
524
712
 
taker/main.py CHANGED
@@ -31,7 +31,7 @@ def main():
31
31
  import importlib.metadata
32
32
  version = importlib.metadata.version("openfund-taker")
33
33
 
34
- openfund_config_path = os.getenv('openfund_config_path','config.json')
34
+ openfund_config_path = 'config.json'
35
35
 
36
36
  with open(openfund_config_path, 'r') as f:
37
37
  config_data = json.load(f)
@@ -43,7 +43,7 @@ def main():
43
43
  package_name = __package__ or "taker"
44
44
 
45
45
  logger.info(f" ++ {package_name}:{version} is doing...")
46
- bot = MultiAssetNewTradingBot(platform_config, feishu_webhook=feishu_webhook_url, monitor_interval=monitor_interval,logger=logger)
46
+ bot = MultiAssetNewTradingBot(config_data, platform_config, feishu_webhook=feishu_webhook_url, monitor_interval=monitor_interval,logger=logger)
47
47
  bot.monitor_total_profit()
48
48
  # bot = ThreeLineTradingBot(platform_config, feishu_webhook=feishu_webhook_url, monitor_interval=monitor_interval)
49
49
  # bot.monitor_klines()