bitunix-automated-crypto-trading 3.3.9__py3-none-any.whl → 3.4.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.
@@ -87,8 +87,8 @@ class AsyncThreadRunner:
87
87
  # For now, we'll just log and continue, allowing the manager to detect if the thread dies from other reasons.
88
88
 
89
89
  # Check stop event again before sleeping to allow immediate stopping
90
- if self._stop_event.is_set():
91
- break
90
+ #if self._stop_event.is_set():
91
+ # break
92
92
 
93
93
  # Use asyncio.sleep to allow graceful cancellation
94
94
  try:
@@ -158,14 +158,14 @@ class BitunixSignal:
158
158
  self.StoreDepthDataTask = AsyncThreadRunner(self.bitunixPublicDepthWebSocketClient.run_websocket, self.logger, 0, self.StoreDepthData)
159
159
  self.StoreDepthDataTask.start_thread(thread_name="StoreDepthData")
160
160
  self.depth_que = asyncio.Queue()
161
- self.ProcessDepthDataTask = AsyncThreadRunner(self.ProcessDepthData, self.logger, interval=0) # run only once
161
+ self.ProcessDepthDataTask = AsyncThreadRunner(self.ProcessDepthData, self.logger, interval=int(self.settings.TICKER_DATA_API_INTERVAL)) # run only once
162
162
  self.ProcessDepthDataTask.start_thread(thread_name="ProcessDepthData")
163
163
 
164
164
  self.bitunixPublicTickerWebSocketClient.tickerList = self.tickerList
165
165
  self.StoreTickerDataTask = AsyncThreadRunner(self.bitunixPublicTickerWebSocketClient.run_websocket, self.logger, 0, self.StoreTickerData)
166
166
  self.StoreTickerDataTask.start_thread(thread_name="StoreTickerData")
167
167
  self.ticker_que = asyncio.Queue()
168
- self.ProcessTickerDataTask = AsyncThreadRunner(self.ProcessTickerData, self.logger, interval=0) # run only once
168
+ self.ProcessTickerDataTask = AsyncThreadRunner(self.ProcessTickerData, self.logger, interval=int(self.settings.TICKER_DATA_API_INTERVAL)) # run only once
169
169
  self.ProcessTickerDataTask.start_thread(thread_name="ProcessTickerData")
170
170
 
171
171
 
@@ -238,38 +238,39 @@ class BitunixSignal:
238
238
 
239
239
  #api data
240
240
  async def GetTickerData(self):
241
- if not self.settings.USE_PUBLIC_WEBSOCKET:
242
- start=time.time()
243
- # Get the current time and set the seconds and microseconds to zero
244
- current_time = datetime.now()
245
- current_minute = current_time.replace(second=0, microsecond=0)
246
- ts = int(current_minute.timestamp())*1000
247
-
248
- #api used insted of websocket
249
- data = await self.bitunixApi.GetTickerData()
250
- self.tickerdf = pd.DataFrame()
251
- if data:
252
-
253
- # Create a DataFrame from the data
254
- self.tickerdf = pd.DataFrame(data, columns=["symbol", "last"])
255
-
256
- #remove not required symbols
257
- self.tickerdf.loc[~self.tickerdf['symbol'].isin(self.tickerObjects.symbols()), :] = None
258
- self.tickerdf.dropna(inplace=True)
259
-
260
- self.tickerdf['ts']=ts
261
- self.tickerdf["tickerObj"] = self.tickerdf["symbol"].map(self.tickerObjects.get_tickerDict())
262
- self.tuples_list = list(zip(self.tickerdf["tickerObj"], self.tickerdf["last"].astype(float), self.tickerdf["ts"]))
263
- self.tickerObjects.form_candle(self.tuples_list)
241
+ if self.settings.VERBOSE_LOGGING:
242
+ self.logger.info(f"GetTickerData started")
243
+ start=time.time()
244
+ # Get the current time and set the seconds and microseconds to zero
245
+ current_time = datetime.now()
246
+ current_minute = current_time.replace(second=0, microsecond=0)
247
+ ts = int(current_minute.timestamp())*1000
248
+
249
+ #api used insted of websocket
250
+ data = await self.bitunixApi.GetTickerData()
251
+ self.tickerdf = pd.DataFrame()
252
+ if data:
253
+
254
+ # Create a DataFrame from the data
255
+ self.tickerdf = pd.DataFrame(data, columns=["symbol", "last"])
256
+
257
+ #remove not required symbols
258
+ self.tickerdf.loc[~self.tickerdf['symbol'].isin(self.tickerObjects.symbols()), :] = None
259
+ self.tickerdf.dropna(inplace=True)
260
+
261
+ self.tickerdf['ts']=ts
262
+ self.tickerdf["tickerObj"] = self.tickerdf["symbol"].map(self.tickerObjects.get_tickerDict())
263
+ self.tuples_list = list(zip(self.tickerdf["tickerObj"], self.tickerdf["last"].astype(float), self.tickerdf["ts"]))
264
+ self.tickerObjects.form_candle(self.tuples_list)
264
265
 
265
- self.lastTickerDataTime = time.time()
266
- if self.settings.VERBOSE_LOGGING:
267
- self.logger.info(f"GetTickerData: elapsed time {time.time()-start}")
268
- if self.settings.BENCHMARK:
269
- self.connection = sqlite3.connect(self.settings.DATABASE)
270
- self.cursor = self.connection.cursor()
271
- self.cursor.execute("INSERT INTO benchmark (process_name, time) VALUES (?, ?)", ("GetTickerData", time.time()-start))
272
- self.connection.commit()
266
+ self.lastTickerDataTime = time.time()
267
+ if self.settings.VERBOSE_LOGGING:
268
+ self.logger.info(f"GetTickerData: elapsed time {time.time()-start}")
269
+ if self.settings.BENCHMARK:
270
+ self.connection = sqlite3.connect(self.settings.DATABASE)
271
+ self.cursor = self.connection.cursor()
272
+ self.cursor.execute("INSERT INTO benchmark (process_name, time) VALUES (?, ?)", ("GetTickerData", time.time()-start))
273
+ self.connection.commit()
273
274
 
274
275
  async def drain_queue(self, queue):
275
276
  items = []
@@ -285,32 +286,34 @@ class BitunixSignal:
285
286
 
286
287
  # Function to process the last price deque
287
288
  async def ProcessTickerData(self):
288
- while True:
289
- try:
290
- latest_data = {}
291
- reversed_items = await self.drain_queue(self.ticker_que)
292
- while reversed_items:
293
- message = reversed_items.popleft()
294
- data = json.loads(message)
295
- if data.get('symbol') and data.get('ch') == 'ticker':
296
- symbol = data["symbol"]
297
- ts = data["ts"]
298
- if symbol not in latest_data or ts > latest_data[symbol]['ts']:
299
- latest_data[symbol] = {'ts': ts, 'last': float(data['data']['la'])}
300
- await asyncio.sleep(0.01)
301
- # Convert to DataFrame
302
- self.tickerdf = pd.DataFrame.from_dict(latest_data, orient="index")
303
- if not self.tickerdf.empty:
304
- self.tickerdf["tickerObj"] = self.tickerdf.index.map(self.tickerObjects.get_tickerDict())
305
- self.tuples_list = list(zip(self.tickerdf["tickerObj"], self.tickerdf["last"].astype(float), self.tickerdf["ts"]))
306
- self.tickerObjects.form_candle(self.tuples_list)
307
- self.lastTickerDataTime = time.time()
308
- except Exception as e:
309
- self.logger.info(f"Function: ProcessTickerData, {e}, {e.args}, {type(e).__name__}")
310
- self.logger.info(traceback.print_exc())
311
- await asyncio.sleep(0.01)
312
- self.logger.info(f"ProcessTickerData: exitied out of the loop, exiting app")
313
- #os._exit(1) # Exit the program
289
+ if self.settings.VERBOSE_LOGGING:
290
+ self.logger.info(f"Started ProcessTickerData")
291
+ start=time.time()
292
+ try:
293
+ # Get the current time and set the seconds and microseconds to zero
294
+ latest_data = {}
295
+ reversed_items = await self.drain_queue(self.ticker_que)
296
+ while reversed_items:
297
+ message = reversed_items.popleft()
298
+ data = json.loads(message)
299
+ if data.get('symbol') and data.get('ch') == 'ticker':
300
+ symbol = data["symbol"]
301
+ ts = data["ts"]
302
+ if symbol not in latest_data or ts > latest_data[symbol]['ts']:
303
+ latest_data[symbol] = {'ts': ts, 'last': float(data['data']['la'])}
304
+ await asyncio.sleep(0.01)
305
+ # Convert to DataFrame
306
+ self.tickerdf = pd.DataFrame.from_dict(latest_data, orient="index")
307
+ if not self.tickerdf.empty:
308
+ self.tickerdf["tickerObj"] = self.tickerdf.index.map(self.tickerObjects.get_tickerDict())
309
+ self.tuples_list = list(zip(self.tickerdf["tickerObj"], self.tickerdf["last"].astype(float), self.tickerdf["ts"]))
310
+ self.tickerObjects.form_candle(self.tuples_list)
311
+ self.lastTickerDataTime = time.time()
312
+ except Exception as e:
313
+ self.logger.info(f"Function: ProcessTickerData, {e}, {e.args}, {type(e).__name__}")
314
+ self.logger.info(traceback.print_exc())
315
+ if self.settings.VERBOSE_LOGGING:
316
+ self.logger.info(f"ProcessTickerData: elapsed time {time.time()-start}")
314
317
 
315
318
 
316
319
  #websocket data to update bid and ask
@@ -320,30 +323,31 @@ class BitunixSignal:
320
323
 
321
324
  # Function to process the bid, ask
322
325
  async def ProcessDepthData(self):
323
- while True:
324
- try:
325
- latest_data = {}
326
- reversed_items = await self.drain_queue(self.depth_que)
327
- while reversed_items:
328
- message = reversed_items.popleft()
329
- data = json.loads(message)
330
- if data.get('symbol') and data.get('ch') == 'depth_book1':
331
- symbol = data["symbol"]
332
- ts = data["ts"]
333
- if symbol not in latest_data or ts > latest_data[symbol]['ts']:
334
- latest_data[symbol] = {'ts': ts, 'bid': float(data['data']['b'][0][0]), 'ask': float(data['data']['a'][0][0])}
335
- await asyncio.sleep(0.01)
336
- # Convert to DataFrame
337
- self.depthdf = pd.DataFrame.from_dict(latest_data, orient="index")
338
- if not self.depthdf.empty:
339
- self.depthdf["tickerObj"] = self.depthdf.index.map(self.tickerObjects.get_tickerDict())
340
- self.depthdf.apply(self.apply_depth_data2, axis=1)
341
- except Exception as e:
342
- self.logger.info(f"Function: ProcessTickerData, {e}, {e.args}, {type(e).__name__}")
343
- self.logger.info(traceback.print_exc())
344
- await asyncio.sleep(0.01)
345
- self.logger.info(f"ProcessDepthData: exitied out of the loop, exiting app")
346
- #os._exit(1) # Exit the program
326
+ if self.settings.VERBOSE_LOGGING:
327
+ self.logger.info(f"Started ProcessDepthData")
328
+ start=time.time()
329
+ try:
330
+ latest_data = {}
331
+ reversed_items = await self.drain_queue(self.depth_que)
332
+ while reversed_items:
333
+ message = reversed_items.popleft()
334
+ data = json.loads(message)
335
+ if data.get('symbol') and data.get('ch') == 'depth_book1':
336
+ symbol = data["symbol"]
337
+ ts = data["ts"]
338
+ if symbol not in latest_data or ts > latest_data[symbol]['ts']:
339
+ latest_data[symbol] = {'ts': ts, 'bid': float(data['data']['b'][0][0]), 'ask': float(data['data']['a'][0][0])}
340
+ await asyncio.sleep(0.01)
341
+ # Convert to DataFrame
342
+ self.depthdf = pd.DataFrame.from_dict(latest_data, orient="index")
343
+ if not self.depthdf.empty:
344
+ self.depthdf["tickerObj"] = self.depthdf.index.map(self.tickerObjects.get_tickerDict())
345
+ self.depthdf.apply(self.apply_depth_data2, axis=1)
346
+ except Exception as e:
347
+ self.logger.info(f"Function: ProcessTickerData, {e}, {e.args}, {type(e).__name__}")
348
+ self.logger.info(traceback.print_exc())
349
+ if self.settings.VERBOSE_LOGGING:
350
+ self.logger.info(f"ProcessDepthData: elapsed time {time.time()-start}")
347
351
 
348
352
  def apply_depth_data2(self, row):
349
353
  row["tickerObj"].set_ask(row["ask"])
@@ -930,6 +934,8 @@ class BitunixSignal:
930
934
  if price > sl_midpoint and side == "BUY" or price < sl_midpoint and side == "SELL":
931
935
  if breakeven_calc:
932
936
  slPrice = price * (1 - float(self.settings.PROFIT_PERCENTAGE) /100 /self.settings.LEVERAGE) if side == "BUY" else price * (1 + float(self.settings.PROFIT_PERCENTAGE) / 100 / self.settings.LEVERAGE)
937
+ if slPrice < avgOpenPrice and side == "BUY" or slPrice > avgOpenPrice and side == "SELL":
938
+ slPrice = avgOpenPrice
933
939
  else:
934
940
  slPrice = price * (1 - float(self.settings.LOSS_PERCENTAGE) / 100 / self.settings.LEVERAGE) if side == "BUY" else price * (1 + float(self.settings.LOSS_PERCENTAGE) / 100 / self.settings.LEVERAGE)
935
941
  slPrice = Decimal(await self.str_precision(slPrice))
@@ -944,7 +950,7 @@ class BitunixSignal:
944
950
  datajs3 = await self.bitunixApi.ModifyTpSlOrder({'orderId':slorderId,'slPrice':str(slPrice),'slQty':str(qty),'slStopType':slStopType,'slOrderType':slOrderType})
945
951
  if datajs3 is not None:
946
952
  self.notifications.add_notification(
947
- f'{colors.CYAN} Stop Loss order for {row.symbol} moved from {old_slPrice} to {"break even" if breakeven_calc else ""} {slPrice}'
953
+ f'{colors.CYAN} Stop Loss order for {row.symbol} moved from {old_slPrice} to {"profitable" if breakeven_calc else ""} {slPrice}'
948
954
  )
949
955
 
950
956
 
@@ -330,8 +330,9 @@ class Interval:
330
330
 
331
331
  buy_conditions = ema_open or macd_open or bbm_open or rsi_open or bos_open or trendline_open
332
332
  additional_buy_conditions = (
333
- (not self.settings.ADX_STUDY or not self.settings.ADX_CHECK_ON_OPEN or self.adx_signal == "STRONG") and
334
- (not self.settings.CANDLE_TREND_STUDY or not self.settings.CANDLE_TREND_CHECK_ON_OPEN or self.candle_trend == "BULLISH")
333
+ (self.settings.ADX_STUDY and self.settings.ADX_CHECK_ON_OPEN and self.adx_signal == "STRONG") if self.settings.ADX_STUDY and self.settings.ADX_CHECK_ON_OPEN else True
334
+ ) and (
335
+ (self.settings.CANDLE_TREND_STUDY and self.settings.CANDLE_TREND_CHECK_ON_OPEN and self.candle_trend == "BULLISH") if self.settings.CANDLE_TREND_STUDY and self.settings.CANDLE_TREND_CHECK_ON_OPEN else True
335
336
  )
336
337
 
337
338
 
@@ -345,8 +346,9 @@ class Interval:
345
346
 
346
347
  sell_conditions = ema_close or macd_close or bbm_close or rsi_close or bos_close or trendline_close
347
348
  additional_sell_conditions = (
348
- (self.settings.ADX_STUDY and self.settings.ADX_CHECK_ON_OPEN and self.adx_signal == "STRONG") and
349
- (self.settings.CANDLE_TREND_STUDY and self.settings.CANDLE_TREND_CHECK_ON_OPEN or self.candle_trend == "BEARISH")
349
+ (self.settings.ADX_STUDY and self.settings.ADX_CHECK_ON_OPEN and self.adx_signal == "STRONG") if self.settings.ADX_STUDY and self.settings.ADX_CHECK_ON_OPEN else True
350
+ ) and (
351
+ (self.settings.CANDLE_TREND_STUDY and self.settings.CANDLE_TREND_CHECK_ON_OPEN and self.candle_trend == "BEARISH") if self.settings.CANDLE_TREND_STUDY and self.settings.CANDLE_TREND_CHECK_ON_OPEN else True
350
352
  )
351
353
 
352
354
  # Determine current signal
@@ -372,8 +374,9 @@ class Interval:
372
374
 
373
375
  buy_conditions = ema_open and macd_open and bbm_open and rsi_open and bos_open and trendline_open
374
376
  additional_buy_conditions = (
375
- (not self.settings.ADX_STUDY or not self.settings.ADX_CHECK_ON_OPEN or self.adx_signal == "STRONG") and
376
- (not self.settings.CANDLE_TREND_STUDY or not self.settings.CANDLE_TREND_CHECK_ON_OPEN or self.candle_trend == "BULLISH")
377
+ (self.settings.ADX_STUDY and self.settings.ADX_CHECK_ON_OPEN and self.adx_signal == "STRONG") if self.settings.ADX_STUDY and self.settings.ADX_CHECK_ON_OPEN else True
378
+ ) and (
379
+ (self.settings.CANDLE_TREND_STUDY and self.settings.CANDLE_TREND_CHECK_ON_OPEN and self.candle_trend == "BULLISH") if self.settings.CANDLE_TREND_STUDY and self.settings.CANDLE_TREND_CHECK_ON_OPEN else True
377
380
  )
378
381
 
379
382
  # Check for SELL signal
@@ -392,8 +395,9 @@ class Interval:
392
395
 
393
396
  sell_conditions = ema_close and macd_close and bbm_close and rsi_close and bos_close and trendline_close
394
397
  additional_sell_conditions = (
395
- (self.settings.ADX_STUDY and self.settings.ADX_CHECK_ON_OPEN and self.adx_signal == "STRONG") or
396
- (self.settings.CANDLE_TREND_STUDY and self.settings.CANDLE_TREND_CHECK_ON_OPEN or self.candle_trend == "BEARISH")
398
+ (self.settings.ADX_STUDY and self.settings.ADX_CHECK_ON_OPEN and self.adx_signal == "STRONG") if self.settings.ADX_STUDY and self.settings.ADX_CHECK_ON_OPEN else True
399
+ ) and (
400
+ (self.settings.CANDLE_TREND_STUDY and self.settings.CANDLE_TREND_CHECK_ON_OPEN and self.candle_trend == "BEARISH") if self.settings.CANDLE_TREND_STUDY and self.settings.CANDLE_TREND_CHECK_ON_OPEN else True
397
401
  )
398
402
 
399
403
  # Determine current signal
@@ -1 +1 @@
1
- __version__ = "3.3.9"
1
+ __version__ = "3.4.0"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: bitunix_automated_crypto_trading
3
- Version: 3.3.9
3
+ Version: 3.4.0
4
4
  Summary: Bitunix Futures Auto Trading Platform
5
5
  Home-page: https://github.com/tcj2001/bitunix-automated-crypto-trading
6
6
  Author: tcj2001
@@ -1,18 +1,18 @@
1
- bitunix_automated_crypto_trading/AsyncThreadRunner.py,sha256=ZTznmxIBQ81oT4nFMa8ic7PGh-3QpStNh6tGG-3RHU0,6502
1
+ bitunix_automated_crypto_trading/AsyncThreadRunner.py,sha256=tnnLqU2EaD-XPRghFrFeKiZBWDxbGaos_ozrh20_NfA,6504
2
2
  bitunix_automated_crypto_trading/BitunixApi.py,sha256=5qg-K5IcsAbb6K1feP9zL7RzSz7JzdGAxoY8R_YWxWE,15666
3
- bitunix_automated_crypto_trading/BitunixSignal.py,sha256=6YI-X5pXxM9ifvY8S7u0e6HyrXYVlUsYBWXgVpAfxbw,92090
3
+ bitunix_automated_crypto_trading/BitunixSignal.py,sha256=VMfJEKiJbt1UOwi6gsQ4mAidmKs4NCzs3V7CrZaRua4,92377
4
4
  bitunix_automated_crypto_trading/BitunixWebSocket.py,sha256=uiqAcis3u-ct07tjaTiC87ujzvcAtVRZ31CMiTBDW_M,11309
5
5
  bitunix_automated_crypto_trading/DataFrameHtmlRenderer.py,sha256=Pqdzhh_nfIxFEZH9L_R5QXB8moDPbgeTGT_hmBkHWMg,2899
6
6
  bitunix_automated_crypto_trading/NotificationManager.py,sha256=exs6REABBA1omTeTGuUuECzxs5dGqdyL7oI8WyxS6Xc,798
7
7
  bitunix_automated_crypto_trading/SupportResistance.py,sha256=x_to4M4OHg0h8o40DXDBa4E_5io-y2Lb5qo2VzFnu_8,5765
8
- bitunix_automated_crypto_trading/TickerManager.py,sha256=tYzO7-vxb-60a-yvsRDC4w9GNdTsqWwy8DxbagtsqAc,42023
8
+ bitunix_automated_crypto_trading/TickerManager.py,sha256=2eQNeSUDPya39oBL-ObyaVUYpzn0q9ykk7q93-A7S1k,42762
9
9
  bitunix_automated_crypto_trading/__init__.py,sha256=1hzk6nX8NnUCr1tsq8oFq1qGCNhNwnwldWE75641Eew,78
10
10
  bitunix_automated_crypto_trading/bitunix.py,sha256=dlf5m0964JW6-9V-xFWv0_4C3OWJ6yTq22E4qWWsGSI,27038
11
11
  bitunix_automated_crypto_trading/config.py,sha256=AlcB0mmwOPfVWuiPrEiexk_JK9qhM2l9sZIdPBtNvqM,6146
12
12
  bitunix_automated_crypto_trading/logger.py,sha256=NHnA5JZdUFkTAhB7i-1iCAwrdf1fxhDuRvJUkbKPi9Y,2923
13
- bitunix_automated_crypto_trading/version.py,sha256=W-NPfrZxGZd77L27ZfNBeZFiVIWjDNLUvZpIjOMIqSY,21
14
- bitunix_automated_crypto_trading-3.3.9.dist-info/METADATA,sha256=r6O6GEO7JvYJSoWS3ZX08Znm_8-XVjhgsRKykKs1-6w,996
15
- bitunix_automated_crypto_trading-3.3.9.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
16
- bitunix_automated_crypto_trading-3.3.9.dist-info/entry_points.txt,sha256=UXREYHuSl2XYd_tOtLIq0zg3d1kX3lixX5SpN8yGBw4,82
17
- bitunix_automated_crypto_trading-3.3.9.dist-info/top_level.txt,sha256=uyFzHUCOsp8elnG2Ovor6xXcf7dxRxY-C-Txiwix64Q,33
18
- bitunix_automated_crypto_trading-3.3.9.dist-info/RECORD,,
13
+ bitunix_automated_crypto_trading/version.py,sha256=DKmNcG3UtnZIAj5xty7yLrIQp4fPaaT1yvrbtln45_8,21
14
+ bitunix_automated_crypto_trading-3.4.0.dist-info/METADATA,sha256=dK1dcaufdtHdO4c5OadX3XpKhF-mMAh7N5nxtSIZQME,996
15
+ bitunix_automated_crypto_trading-3.4.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
16
+ bitunix_automated_crypto_trading-3.4.0.dist-info/entry_points.txt,sha256=UXREYHuSl2XYd_tOtLIq0zg3d1kX3lixX5SpN8yGBw4,82
17
+ bitunix_automated_crypto_trading-3.4.0.dist-info/top_level.txt,sha256=uyFzHUCOsp8elnG2Ovor6xXcf7dxRxY-C-Txiwix64Q,33
18
+ bitunix_automated_crypto_trading-3.4.0.dist-info/RECORD,,