openfund-taker 1.3.15__py3-none-any.whl → 1.3.17__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.3.15
3
+ Version: 1.3.17
4
4
  Summary: Openfund-taker
5
5
  Requires-Python: >=3.9,<4.0
6
6
  Classifier: Programming Language :: Python :: 3
@@ -1,7 +1,7 @@
1
1
  taker/MultiAssetOldTradingBot.py,sha256=uBh_BxglvcbaHIsWHM7GI9Qa_QjzsxXaXJAAWEOMO5c,15315
2
2
  taker/ThreeLineTradingTaker.py,sha256=ElD9pKDO4nxw5VKNRrvXqyiU0gkV_1Mg_zk-hftfaPs,20553
3
3
  taker/TrailingSLAndTPTaker.py,sha256=rx3tw9TwFCpqnz3e0WlTtFVcn8mBbPHtp62n3RF86Kg,1144
4
- taker/TrailingSLTaker.py,sha256=iAFeGsgWVdMlaOQEYgRcjPPuRcmPsytCdguEKu1Qz9o,44928
4
+ taker/TrailingSLTaker.py,sha256=lOOv8tnJrPR3F_U31t9pZa3WwMwVvqv1gWmr1CKs07A,46554
5
5
  taker/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
6
  taker/chua_bitget.py,sha256=YY6XK5Bd-wlArsN5BnAfiqE0h1DPkti6i4TEB4F5zDA,12918
7
7
  taker/chua_bn.py,sha256=GnTePWlgDwdHgroBbEp1Ajcsf5_m_Vn_RV63SYzu2jI,10668
@@ -10,7 +10,7 @@ taker/chua_ok_all.py,sha256=2XnZM6QdB3juSE1pqQIJyh2x1XuhlTlnBKNA3owlJ9E,15267
10
10
  taker/chua_ok_bot.py,sha256=9SW0ujhi6PfN4yR1JZ9NaA37HtnXJ2QAWUfW52NG68w,13109
11
11
  taker/config.py,sha256=YPxghO5i0vgRg9Cja8kGj9O7pgSbbtzOgf3RexqXXwY,1188
12
12
  taker/main.py,sha256=QCEjINu3IgwWEGcuquHzeYjKJYAQrPe8ctQhMoIb9SA,2561
13
- openfund_taker-1.3.15.dist-info/METADATA,sha256=7cxw7Emu7UMHhNtE-TWEuJTMSDeoRkkoU6ebwSdslls,7528
14
- openfund_taker-1.3.15.dist-info/WHEEL,sha256=IYZQI976HJqqOpQU6PHkJ8fb3tMNBFjg-Cn-pwAbaFM,88
15
- openfund_taker-1.3.15.dist-info/entry_points.txt,sha256=a7mG8F7aOA5-Gk2vPWuAR4537faxaHUgM_jwIDBZoEc,50
16
- openfund_taker-1.3.15.dist-info/RECORD,,
13
+ openfund_taker-1.3.17.dist-info/METADATA,sha256=6lq4Ki7sp8pdkaMCDsWMDVRX8GMjn-VdkNpWmaet19M,7528
14
+ openfund_taker-1.3.17.dist-info/WHEEL,sha256=IYZQI976HJqqOpQU6PHkJ8fb3tMNBFjg-Cn-pwAbaFM,88
15
+ openfund_taker-1.3.17.dist-info/entry_points.txt,sha256=a7mG8F7aOA5-Gk2vPWuAR4537faxaHUgM_jwIDBZoEc,50
16
+ openfund_taker-1.3.17.dist-info/RECORD,,
taker/TrailingSLTaker.py CHANGED
@@ -134,33 +134,64 @@ class TrailingSLTaker:
134
134
  else:
135
135
  raise ValueError("Unexpected response structure or missing candlestick data")
136
136
 
137
- def get_last_solated_point(self,symbol,position,kLines):
138
- # 将K线数据转换为DataFrame格式,最后一个数据可能未完成。
137
+ def is_pivot_high(self, data, index, period, check_bounds=False):
138
+ """
139
+ 判断当前索引处是否为枢轴高点
140
+ :param data: 包含 'high' 列的 DataFrame
141
+ :param index: 当前索引
142
+ :param period: 前后比较的周期数
143
+ :param check_bounds: 是否检查边界
144
+ :return: 是否为枢轴高点
145
+ """
146
+ if check_bounds and (index < period or index >= len(data) - period):
147
+ return False
148
+ current_high = data.at[index, 'high']
149
+ prev_highs = data['high'].iloc[max(0,index - period):index]
150
+ next_highs = data['high'].iloc[index :min(len(data),index + period + 1)]
151
+ return all(current_high >= prev_highs) and all(current_high >= next_highs)
152
+
153
+
154
+ def is_pivot_low(self, data, index, period, check_bounds=False):
155
+ """
156
+ 判断当前索引处是否为枢轴低点
157
+ :param data: 包含 'low' 列的 DataFrame
158
+ :param index: 当前索引
159
+ :param period: 前后比较的周期数
160
+ :param check_bounds: 是否检查边界
161
+ :return: 是否为枢轴低点
162
+ """
163
+ if check_bounds and (index < period or index >= len(data) - period):
164
+ return False
165
+ current_low = data.at[index, 'low']
166
+ prev_lows = data['low'].iloc[max(0,index - period):index]
167
+ next_lows = data['low'].iloc[index :min(len(data),index + period + 1)]
168
+ return all(current_low <= prev_lows) and all(current_low <= next_lows)
169
+
170
+
171
+ def get_last_solated_point(self,symbol,position,kLines ,prd=20):
172
+ # 将K线数据转换为DataFrame格式
139
173
  df = pd.DataFrame(kLines, columns=['timestamp', 'open', 'high', 'low', 'close', 'volume'])
140
174
  df['timestamp'] = pd.to_datetime(df['timestamp'], unit='ms')
141
-
175
+
142
176
  # 根据position方向寻找孤立点
143
177
  side = position['side']
144
- window = 1 # 设置窗口大小,用于判断局部最值
178
+ window = prd # 设置窗口大小,用于判断局部最值
179
+ isolated_points = []
180
+ for i in range(len(df)-1, -1, -1):
181
+
182
+ if side == 'short':
183
+ # 找最近的孤立高点
184
+ if self.is_pivot_high(df, i, window,check_bounds=True):
185
+ # 获取最近的孤立高点
186
+ isolated_points.append(df.iloc[i])
187
+ break
188
+
189
+ else:
190
+ # 找最近的孤立低点
191
+ if self.is_pivot_low(df, i, window,check_bounds=True):
192
+ isolated_points.append(df.iloc[i])
193
+ break
145
194
 
146
- if side == 'short':
147
- # 找最近的孤立高点
148
- # 判断局部最高点:当前点比前后window个点都高
149
- df['is_high'] = df['high'].rolling(window=window*2+1, center=True).apply(
150
- lambda x: x[window] > max(x[:window]) and x[window] > max(x[window+1:]), raw=True
151
- )
152
- # 获取最近的孤立高点
153
- isolated_points = df[df['is_high']==True]['high'].iloc[-3:]
154
-
155
- else:
156
- # 找最近的孤立低点
157
- # 判断局部最低点:当前点比前后window个点都低
158
- df['is_low'] = df['low'].rolling(window=window*2+1, center=True).apply(
159
- lambda x: x[window] < min(x[:window]) and x[window] < min(x[window+1:]), raw=True
160
- )
161
- # 获取最近的孤立低点
162
- isolated_points = df[df['is_low']==True]['low'].iloc[-3:]
163
-
164
195
  return isolated_points
165
196
 
166
197
 
@@ -291,8 +322,9 @@ class TrailingSLTaker:
291
322
  self.logger.info(f"{symbol}: 持仓方向={side} 与 正确方向={correct_side} 相同 , 恢复正常。")
292
323
 
293
324
  # 根据情况 重新修正止损
294
- self.global_symbol_stop_loss_flag[symbol] = False
295
- self.set_global_stop_loss(symbol=symbol,position=position,stop_loss_pct=order_stop_loss_pct)
325
+ self.global_symbol_stop_loss_flag[symbol] = False
326
+ find_swing_point = pair_config.get('open_swing_point', False)
327
+ self.set_global_stop_loss(symbol=symbol,position=position,stop_loss_pct=order_stop_loss_pct ,find_swing_point=find_swing_point)
296
328
 
297
329
 
298
330
  except Exception as e:
@@ -606,7 +638,7 @@ class TrailingSLTaker:
606
638
  return True
607
639
 
608
640
 
609
- def set_global_stop_loss(self, symbol, position, stop_loss_pct=None):
641
+ def set_global_stop_loss(self, symbol, position, stop_loss_pct=None,find_swing_point=False):
610
642
  """设置全局止损
611
643
 
612
644
  Args:
@@ -654,21 +686,26 @@ class TrailingSLTaker:
654
686
  return
655
687
 
656
688
  # 250228 没有指定止损回撤阈值stop_loss_pct...
657
- if stop_loss_pct is None :
689
+ if find_swing_point :
658
690
  pair_config = self.trading_pairs_config.get(symbol, {})
659
691
  klines_period = str(pair_config.get('klines_period', '1m'))
660
692
  kLines = self.get_historical_klines_except_last(symbol=symbol,bar=klines_period)
661
-
693
+ swing_points_length = pair_config.get('swing_points_length', 20)
662
694
  if kLines:
663
- isolated_point = self.get_last_solated_point(symbol ,position , kLines)
695
+ isolated_points = self.get_last_solated_point(symbol ,position , kLines,prd=swing_points_length)
664
696
 
665
- if len(isolated_point) > 0 :
666
- last_isolated_point = float(isolated_point.iloc[-1])
667
- self.logger.debug(f"{symbol}: - {side} ,孤立点={last_isolated_point} ,止损价={sl_order_price}")
697
+ if len(isolated_points) > 0 :
698
+ last_isolated_point = isolated_points[0]
699
+
668
700
  if side == 'long':
669
- sl_order_price = max(last_isolated_point, sl_order_price)
670
- elif side =='short':
671
- sl_order_price = min(last_isolated_point, sl_order_price)
701
+ # sl_order_price = max(last_isolated_point, sl_order_price)
702
+ sl_order_price = last_isolated_point['low']
703
+ else:
704
+ # sl_order_price = min(last_isolated_point, sl_order_price)
705
+ sl_order_price = last_isolated_point['high']
706
+
707
+ self.logger.debug(f"{symbol}: - {side} ,止损价={sl_order_price} 孤立点=\n{last_isolated_point} ")
708
+
672
709
 
673
710
 
674
711
  last_sl_price= self.global_symbol_stop_loss_price.get(symbol,None)
@@ -929,7 +966,8 @@ class TrailingSLTaker:
929
966
  else:
930
967
 
931
968
  # 默认全局止损
932
- self.set_global_stop_loss(symbol, position)
969
+ find_swing_point = pair_config.get('open_swing_point', False)
970
+ self.set_global_stop_loss(symbol, position, find_swing_point=find_swing_point)
933
971
  self.logger.info(f"{symbol}: 全局止损阈值: {self.stop_loss_pct:.2f}%")
934
972
 
935
973
  return