openfund-taker 2.2.6__py3-none-any.whl → 2.2.7__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.
taker/main.py CHANGED
@@ -1,31 +1,12 @@
1
1
  import logging
2
+ import logging.config
2
3
  import yaml
3
- from logging.handlers import TimedRotatingFileHandler
4
4
 
5
5
  from taker.TrailingSLTaker import TrailingSLTaker
6
6
  from taker.TrailingSLAndTPTaker import TrailingSLAndTPTaker
7
7
  from taker.ThreeLineTradingTaker import ThreeLineTradingTaker
8
8
  from taker.SMCSLAndTPTaker import SMCSLAndTPTaker
9
9
  from pyfiglet import Figlet
10
-
11
- def build_logger(log_config) -> logging.Logger:
12
- # 配置日志
13
- # log_file = "log/okx_MultiAssetNewTradingBot.log"
14
- log_file = log_config["file"]
15
- logger = logging.getLogger(__name__)
16
- logger.setLevel(log_config["level"])
17
-
18
- file_handler = TimedRotatingFileHandler(log_file, when='midnight', interval=1, backupCount=7, encoding='utf-8')
19
- file_handler.suffix = "%Y-%m-%d"
20
- formatter = logging.Formatter('%(asctime)s - %(name)s - %(lineno)d - %(levelname)s - %(message)s')
21
- file_handler.setFormatter(formatter)
22
- logger.addHandler(file_handler)
23
-
24
- console_handler = logging.StreamHandler()
25
- console_handler.setFormatter(formatter)
26
- logger.addHandler(console_handler)
27
-
28
- return logger
29
10
 
30
11
  def read_config_file(file_path):
31
12
  try:
@@ -43,30 +24,31 @@ def read_config_file(file_path):
43
24
  def main():
44
25
  import importlib.metadata
45
26
  version = importlib.metadata.version("openfund-taker")
27
+
28
+ package_name = __package__ or "taker"
46
29
 
47
- # openfund_config_path = 'config.json'
48
30
  openfund_config_path = 'taker_config.yaml'
49
31
  config_data = read_config_file(openfund_config_path)
50
32
 
33
+
34
+ platform_config = config_data['platform']["okx"]
35
+ common_config = config_data['common']
36
+ taker = common_config.get('actived_taker', 'SMCSLAndTPTaker')
37
+ feishu_webhook_url = common_config['feishu_webhook']
38
+ monitor_interval = common_config.get("monitor_interval", 60) # 默认值为60秒
51
39
 
52
- # with open(openfund_config_path, 'r') as f:
53
- # config_data = json.load(f)
54
-
55
- platform_config = config_data['okx']
56
- feishu_webhook_url = config_data['feishu_webhook']
57
- monitor_interval = config_data.get("monitor_interval", 60) # 默认值为60秒
58
- logger = build_logger(config_data["Logger"])
59
- package_name = __package__ or "taker"
40
+ logging.config.dictConfig(config_data["Logger"])
41
+ logger = logging.getLogger("openfund-taker")
60
42
 
61
- taker = config_data.get('actived_taker', 'SMCSLAndTPTaker')
62
-
43
+ f = Figlet(font="standard") # 字体可选(如 "block", "bubble")
44
+ logger.info(f"\n{f.renderText("OpenFund Taker")}")
45
+
46
+ logger.info(f" ++ {package_name}.{taker}:{version} is doing...")
63
47
  # 根据配置动态创建策略实例
64
48
  strategy_class = globals()[taker]
65
- bot = strategy_class(config_data, platform_config, feishu_webhook=feishu_webhook_url, monitor_interval=monitor_interval,logger=logger)
66
- logger.info(f" ++ {package_name}.{taker}:{version} is doing...")
49
+ bot = strategy_class(config_data, platform_config, common_config, feishu_webhook=feishu_webhook_url, monitor_interval=monitor_interval,logger=logger)
50
+
67
51
 
68
- f = Figlet(font="standard") # 字体可选(如 "block", "bubble")
69
- logger.info(f"\n{f.renderText("OpenFund Taker")}")
70
52
  bot.monitor_total_profit()
71
53
  # bot = ThreeLineTradingBot(platform_config, feishu_webhook=feishu_webhook_url, monitor_interval=monitor_interval)
72
54
  # bot.monitor_klines()
@@ -1,17 +0,0 @@
1
- taker/MultiAssetOldTradingBot.py,sha256=uBh_BxglvcbaHIsWHM7GI9Qa_QjzsxXaXJAAWEOMO5c,15315
2
- taker/SMCSLAndTPTaker.py,sha256=rKt_TDT8kKiyYjfz0rC77MDygvuvjsmAO_hXoLDd8dU,28432
3
- taker/ThreeLineTradingTaker.py,sha256=ElD9pKDO4nxw5VKNRrvXqyiU0gkV_1Mg_zk-hftfaPs,20553
4
- taker/TrailingSLAndTPTaker.py,sha256=OPD1ZNqyM8jZ7Im-bWm_6Cu4_qfwKmNZ30XpbP6-l00,2746
5
- taker/TrailingSLTaker.py,sha256=eyS03afaPxkSZOzc3dgPGq_kIKYJ6mecAzmD8iD197U,48995
6
- taker/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
- taker/chua_bitget.py,sha256=YY6XK5Bd-wlArsN5BnAfiqE0h1DPkti6i4TEB4F5zDA,12918
8
- taker/chua_bn.py,sha256=GnTePWlgDwdHgroBbEp1Ajcsf5_m_Vn_RV63SYzu2jI,10668
9
- taker/chua_ok.py,sha256=5pPAoEYbFuKxfZwqNvOO890s-2cy6n69QiI0ZA0GTCQ,12474
10
- taker/chua_ok_all.py,sha256=2XnZM6QdB3juSE1pqQIJyh2x1XuhlTlnBKNA3owlJ9E,15267
11
- taker/chua_ok_bot.py,sha256=9SW0ujhi6PfN4yR1JZ9NaA37HtnXJ2QAWUfW52NG68w,13109
12
- taker/config.py,sha256=YPxghO5i0vgRg9Cja8kGj9O7pgSbbtzOgf3RexqXXwY,1188
13
- taker/main.py,sha256=3M1y_1sRIfkYNGWP0Wb3DfZFgHb0y4Cd45ERPnc1J9w,2927
14
- openfund_taker-2.2.6.dist-info/METADATA,sha256=Hi4UeLRdLgbYMH_1EgeC72z1v5Tgwz5t_dOTi9lK2eg,7529
15
- openfund_taker-2.2.6.dist-info/WHEEL,sha256=IYZQI976HJqqOpQU6PHkJ8fb3tMNBFjg-Cn-pwAbaFM,88
16
- openfund_taker-2.2.6.dist-info/entry_points.txt,sha256=a7mG8F7aOA5-Gk2vPWuAR4537faxaHUgM_jwIDBZoEc,50
17
- openfund_taker-2.2.6.dist-info/RECORD,,
@@ -1,300 +0,0 @@
1
- # -*- coding: utf-8 -*-
2
- import ccxt
3
- import time
4
- import logging
5
- import requests
6
- import json
7
- import trailing.okx.Trade_api as TradeAPI
8
- from logging.handlers import TimedRotatingFileHandler
9
-
10
- # 废弃 策略
11
- class MultiAssetOldTradingBot:
12
- def __init__(self, config, feishu_webhook=None, monitor_interval=4):
13
- self.stop_loss_pct = config["all_stop_loss_pct"] # 全局止损百分比
14
-
15
- # 止盈比例
16
- self.low_trail_stop_loss_pct = config["all_low_trail_stop_loss_pct"] # 第一档
17
- self.trail_stop_loss_pct = config["all_trail_stop_loss_pct"]# 第二档
18
- self.higher_trail_stop_loss_pct = config["all_higher_trail_stop_loss_pct"]# 第三档
19
- # 止盈阈值
20
- self.low_trail_profit_threshold = config["all_low_trail_profit_threshold"]# 第一档
21
- self.first_trail_profit_threshold = config["all_first_trail_profit_threshold"]# 第二档
22
- self.second_trail_profit_threshold = config["all_second_trail_profit_threshold"]# 第三档
23
-
24
- self.feishu_webhook = feishu_webhook
25
- self.monitor_interval = monitor_interval # 监控循环时间是分仓监控的3倍
26
- self.highest_total_profit = 0 # 记录最高总盈利
27
-
28
- # 配置交易所
29
- self.exchange = ccxt.okx({
30
- 'apiKey': config["apiKey"],
31
- 'secret': config["secret"],
32
- 'password': config["password"],
33
- 'timeout': 3000,
34
- 'rateLimit': 50,
35
- 'options': {'defaultType': 'future'},
36
- 'proxies': {'http': 'http://127.0.0.1:7890', 'https': 'http://127.0.0.1:7890'},
37
- })
38
-
39
- # 配置 OKX 第三方库
40
- self.trading_bot = TradeAPI.TradeAPI(config["apiKey"], config["secret"], config["password"], False, '0')
41
-
42
- # 配置日志
43
- log_file = "log/okx_MultiAssetTradingBot.log"
44
- logger = logging.getLogger(__name__)
45
- logger.setLevel(logging.INFO)
46
-
47
- file_handler = TimedRotatingFileHandler(log_file, when='midnight', interval=1, backupCount=7, encoding='utf-8')
48
- file_handler.suffix = "%Y-%m-%d"
49
- formatter = logging.Formatter('%(asctime)s - %(name)s - %(lineno)d - %(levelname)s - %(message)s')
50
- file_handler.setFormatter(formatter)
51
- logger.addHandler(file_handler)
52
-
53
- console_handler = logging.StreamHandler()
54
- console_handler.setFormatter(formatter)
55
- logger.addHandler(console_handler)
56
-
57
- self.logger = logger
58
- self.position_mode = self.get_position_mode() # 获取持仓模式
59
-
60
- def get_position_mode(self):
61
- try:
62
- # 假设获取账户持仓模式的 API
63
- response = self.exchange.private_get_account_config()
64
- data = response.get('data', [])
65
- if data and isinstance(data, list):
66
- # 取列表的第一个元素(假设它是一个字典),然后获取 'posMode'
67
- position_mode = data[0].get('posMode', 'single') # 默认值为单向
68
- self.logger.info(f"当前持仓模式: {position_mode}")
69
- return position_mode
70
- else:
71
- self.logger.error("无法检测持仓模式: 'data' 字段为空或格式不正确")
72
- return 'single' # 返回默认值
73
- except Exception as e:
74
- self.logger.error(f"无法检测持仓模式: {e}")
75
- return None
76
-
77
- def send_feishu_notification(self, message):
78
- if self.feishu_webhook:
79
- try:
80
- headers = {'Content-Type': 'application/json'}
81
- payload = {"msg_type": "text", "content": {"text": message}}
82
- response = requests.post(self.feishu_webhook, json=payload, headers=headers)
83
- if response.status_code == 200:
84
- self.logger.info("飞书通知发送成功")
85
- else:
86
- self.logger.error("飞书通知发送失败,状态码: %s", response.status_code)
87
- except Exception as e:
88
- self.logger.error("发送飞书通知时出现异常: %s", str(e))
89
-
90
- def fetch_positions(self):
91
- try:
92
- positions = self.exchange.fetch_positions()
93
- return positions
94
- except Exception as e:
95
- self.logger.error(f"Error fetching positions: {e}")
96
- return []
97
-
98
- def fetch_open_orders(self):
99
- try:
100
- orders = self.exchange.fetch_open_orders()
101
- return orders
102
- except Exception as e:
103
- self.logger.error(f"Error fetching open orders: {e}")
104
- return []
105
-
106
- def cancel_all_orders(self):
107
- orders = self.fetch_open_orders()
108
- for order in orders:
109
- try:
110
- self.exchange.cancel_order(order['id'])
111
- self.logger.info(f"Order {order['id']} cancelled.")
112
- except Exception as e:
113
- self.logger.error(f"Error cancelling order {order['id']}: {e}")
114
-
115
- # 平仓
116
- def close_all_positions(self):
117
- positions = self.fetch_positions()
118
- for position in positions:
119
- symbol = position['symbol']
120
- amount = abs(float(position['contracts']))
121
- side = position['side']
122
- td_mode = position['marginMode']
123
- if amount > 0:
124
- try:
125
- self.logger.info(f"Preparing to close position for {symbol}, side: {side}, amount: {amount}")
126
-
127
- if self.position_mode == 'long_short_mode':
128
- # 在双向持仓模式下,指定平仓方向
129
- pos_side = 'long' if side == 'long' else 'short'
130
- else:
131
- # 在单向模式下,不指定方向
132
- pos_side = 'net'
133
-
134
- # 将 symbol 转换为 API 需要的格式
135
- inst_id = symbol.replace('/', '-').replace(':USDT', '')
136
- if 'SWAP' not in inst_id: # 确保是永续合约标识
137
- inst_id += '-SWAP'
138
- # print(f'{inst_id}处理平仓')
139
-
140
- # 发送平仓请求并获取返回值
141
- response = self.trading_bot.close_positions(
142
- instId=inst_id,
143
- mgnMode=td_mode,
144
- posSide=pos_side,
145
- autoCxl='true'
146
- )
147
- self.logger.info(f"Close position response for {symbol}: {response}")
148
- time.sleep(0.1) # 短暂延迟后再试
149
- # 检查平仓结果
150
- if response.get('code') == '0': # 确认成功状态
151
- self.logger.info(f"Successfully closed position for {symbol}, side: {side}, amount: {amount}")
152
- self.send_feishu_notification(
153
- f"Successfully closed position for {symbol}, side: {side}, amount: {amount}")
154
- else:
155
- self.logger.error(f"Failed to close position for {symbol}: {response}")
156
- self.send_feishu_notification(f"Failed to close position for {symbol}: {response}")
157
-
158
- except Exception as e:
159
- self.logger.error(f"Error closing position for {symbol}: {e}")
160
- self.send_feishu_notification(f"Error closing position for {symbol}: {e}")
161
- # 计算平均利润
162
- def calculate_average_profit(self):
163
- positions = self.fetch_positions()
164
- total_profit_pct = 0.0
165
- num_positions = 0
166
-
167
- for position in positions:
168
- symbol = position['symbol']
169
- entry_price = float(position['entryPrice'])
170
- current_price = float(position['markPrice'])
171
- side = position['side']
172
-
173
- # 计算单个仓位的浮动盈利百分比
174
- if side == 'long':
175
- profit_pct = (current_price - entry_price) / entry_price * 100
176
- elif side == 'short':
177
- profit_pct = (entry_price - current_price) / entry_price * 100
178
- else:
179
- continue
180
-
181
- # 累加总盈利百分比
182
- total_profit_pct += profit_pct
183
- num_positions += 1
184
-
185
- # 记录单个仓位的盈利情况
186
- self.logger.info(f"仓位 {symbol},方向: {side},开仓价格: {entry_price},当前价格: {current_price},"
187
- f"浮动盈亏: {profit_pct:.2f}%")
188
-
189
- # 计算平均浮动盈利百分比
190
- average_profit_pct = total_profit_pct / num_positions if num_positions > 0 else 0
191
- return average_profit_pct
192
-
193
- def reset_highest_profit_and_tier(self):
194
- """重置最高总盈利和当前档位状态"""
195
- self.highest_total_profit = 0
196
- self.current_tier = "无"
197
- self.logger.info("已重置最高总盈利和档位状态")
198
-
199
- def monitor_total_profit(self):
200
- self.logger.info("启动主循环,开始监控总盈利...")
201
- previous_position_size = sum(
202
- abs(float(position['contracts'])) for position in self.fetch_positions()) # 初始总仓位大小
203
- try:
204
- while True:
205
- # 检查仓位总规模变化
206
- current_position_size = sum(abs(float(position['contracts'])) for position in self.fetch_positions())
207
- if current_position_size > previous_position_size:
208
- self.send_feishu_notification(f"检测到仓位变化操作,重置最高盈利和档位状态")
209
- self.logger.info("检测到新增仓位操作,重置最高盈利和档位状态")
210
- self.reset_highest_profit_and_tier()
211
- previous_position_size = current_position_size
212
- continue # 跳过本次循环
213
-
214
- total_profit = self.calculate_average_profit()
215
- if total_profit > 0.0 :
216
- self.logger.info(f"当前总盈利: {total_profit:.2f}%")
217
- self.send_feishu_notification(f"当前总盈利: {total_profit:.2f}%")
218
- if total_profit > self.highest_total_profit:
219
- self.highest_total_profit = total_profit
220
- # 确定当前盈利档位
221
- if self.highest_total_profit >= self.second_trail_profit_threshold:
222
- self.current_tier = "第二档移动止盈"
223
- elif self.highest_total_profit >= self.first_trail_profit_threshold:
224
- self.current_tier = "第一档移动止盈"
225
- elif self.highest_total_profit >= self.low_trail_profit_threshold:
226
- self.current_tier = "低档保护止盈"
227
- else:
228
- self.current_tier = "无"
229
- if total_profit > 0.0 :
230
- self.logger.info(
231
- f"当前总盈利: {total_profit:.2f}%,最高总盈利: {self.highest_total_profit:.2f}%,当前档位: {self.current_tier}")
232
- self.send_feishu_notification(
233
- f"当前总盈利: {total_profit:.2f}%,最高总盈利: {self.highest_total_profit:.2f}%,当前档位: {self.current_tier}")
234
-
235
- '''
236
- 第一档 低档保护止盈:当盈利达到0.3%触发,要么到第二档,要么回到0.2%止盈
237
- 第二档:盈利达到1%触发,记录最高价,最高价的80%是止盈位
238
- 第三档:盈利达到3%触发,记录最高价,最高价的75%是止盈位
239
- '''
240
- # 各档止盈逻辑
241
- if self.current_tier == "低档保护止盈":
242
- self.logger.info(f"低档回撤止盈阈值: {self.low_trail_stop_loss_pct:.2f}%")
243
- if total_profit <= self.low_trail_stop_loss_pct:
244
- self.send_feishu_notification(f"总盈利触发低档保护止盈,当前回撤到: {total_profit:.2f}%,执行全部平仓")
245
- self.logger.info(f"总盈利触发低档保护止盈,当前回撤到: {total_profit:.2f}%,执行全部平仓")
246
- self.close_all_positions()
247
- self.reset_highest_profit_and_tier()
248
- continue
249
- elif self.current_tier == "第一档移动止盈":
250
- trail_stop_loss = self.highest_total_profit * (1 - self.trail_stop_loss_pct)
251
- self.logger.info(f"第一档回撤止盈阈值: {trail_stop_loss:.2f}%")
252
- if total_profit <= trail_stop_loss:
253
- self.close_all_positions()
254
- self.reset_highest_profit_and_tier()
255
-
256
- self.send_feishu_notification(
257
- f"总盈利达到第一档回撤阈值,最高总盈利: {self.highest_total_profit:.2f}%,当前回撤到: {total_profit:.2f}%,执行全部平仓")
258
- self.logger.info(
259
- f"总盈利达到第一档回撤阈值,最高总盈利: {self.highest_total_profit:.2f}%,当前回撤到: {total_profit:.2f}%,执行全部平仓")
260
- continue
261
-
262
- elif self.current_tier == "第二档移动止盈":
263
- trail_stop_loss = self.highest_total_profit * (1 - self.higher_trail_stop_loss_pct)
264
- self.logger.info(f"第二档回撤止盈阈值: {trail_stop_loss:.2f}%")
265
- if total_profit <= trail_stop_loss:
266
- self.close_all_positions()
267
- self.reset_highest_profit_and_tier()
268
- self.logger.info(f"总盈利达到第二档回撤阈值,最高总盈利: {self.highest_total_profit:.2f}%,当前回撤到: {total_profit:.2f}%,执行全部平仓")
269
- self.send_feishu_notification(f"总盈利达到第二档回撤阈值,最高总盈利: {self.highest_total_profit:.2f}%,当前回撤到: {total_profit:.2f}%,执行全部平仓")
270
- continue
271
- # 全局止损
272
- if total_profit <= -self.stop_loss_pct:
273
- self.close_all_positions()
274
- self.reset_highest_profit_and_tier()
275
- self.logger.info(f"总盈利触发全局止损,当前回撤到: {total_profit:.2f}%,执行全部平仓")
276
- self.send_feishu_notification(f"总盈利触发全局止损,当前回撤到: {total_profit:.2f}%,执行全部平仓")
277
- continue
278
-
279
-
280
- time.sleep(self.monitor_interval)
281
-
282
- except KeyboardInterrupt:
283
- self.logger.info("程序收到中断信号,开始退出...")
284
- except Exception as e:
285
- error_message = f"程序异常退出: {str(e)}"
286
- self.logger.error(error_message)
287
- self.send_feishu_notification(error_message)
288
-
289
-
290
- if __name__ == '__main__':
291
- with open('config.json', 'r') as f:
292
- config_data = json.load(f)
293
-
294
- # 指定具体平台配置,例如 OKX
295
- platform_config = config_data['okx']
296
- feishu_webhook_url = config_data['feishu_webhook']
297
- monitor_interval = config_data.get("monitor_interval", 4) # 默认值为4秒
298
-
299
- bot = MultiAssetTradingBot(platform_config, feishu_webhook=feishu_webhook_url, monitor_interval=monitor_interval)
300
- bot.monitor_total_profit()
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes