bitunix-automated-crypto-trading 3.2.9__py3-none-any.whl → 3.3.1__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.
@@ -120,9 +120,9 @@ class BitunixApi:
120
120
  response.raise_for_status()
121
121
  return response.json()
122
122
 
123
- async def PlaceOrder(self, ticker, qty, price, side, positionId=0, tradeSide="OPEN",reduceOnly=False, takeProfitPrice=0, stopLossPrice=0):
123
+ async def PlaceOrder(self, ticker, qty, price, side, positionId=0, tradeSide="OPEN",reduceOnly=False, tpPrice=0, tpOrderPrice=0, slPrice=0, slOrderPrice=0):
124
124
  datajs = None
125
- if takeProfitPrice == 0 or stopLossPrice == 0:
125
+ if tpPrice == 0 and slPrice == 0:
126
126
  data = {
127
127
  "side": side,
128
128
  "orderType":"LIMIT",
@@ -134,7 +134,7 @@ class BitunixApi:
134
134
  "positionId":positionId
135
135
  }
136
136
  datajs = await self._post_authenticated(self.placeOrder_Url,data)
137
- elif takeProfitPrice == 0:
137
+ elif tpPrice == 0:
138
138
  data = {
139
139
  "side": side,
140
140
  "orderType":"LIMIT",
@@ -142,14 +142,14 @@ class BitunixApi:
142
142
  "price": price,
143
143
  "symbol": ticker,
144
144
  "tradeSide":tradeSide,
145
- "slPrice": stopLossPrice,
146
- "slStopType":'MARK_PRICE',
145
+ "slPrice": slPrice,
147
146
  "slStopType": self.settings.PROFIT_LOSS_PRICE_TYPE,
148
147
  "slOrderType": self.settings.PROFIT_LOSS_ORDER_TYPE,
148
+ "slOrderPrice": slOrderPrice,
149
149
  "positionId":positionId
150
150
  }
151
151
  datajs = await self._post_authenticated(self.placeOrder_Url,data)
152
- elif stopLossPrice == 0:
152
+ elif slPrice == 0:
153
153
  data = {
154
154
  "side": side,
155
155
  "orderType":"LIMIT",
@@ -157,10 +157,10 @@ class BitunixApi:
157
157
  "price": price,
158
158
  "symbol": ticker,
159
159
  "tradeSide":tradeSide,
160
- "tpPrice": takeProfitPrice,
160
+ "tpPrice": tpPrice,
161
161
  "tpStopType": self.settings.PROFIT_LOSS_PRICE_TYPE,
162
162
  "tpOrderType": self.settings.PROFIT_LOSS_ORDER_TYPE,
163
- "tpOrderPrice":takeProfitPrice,
163
+ "tpOrderPrice":tpOrderPrice,
164
164
  "positionId":positionId
165
165
  }
166
166
  datajs = await self._post_authenticated(self.placeOrder_Url,data)
@@ -172,14 +172,14 @@ class BitunixApi:
172
172
  "price": price,
173
173
  "symbol": ticker,
174
174
  "tradeSide":tradeSide,
175
- "tpPrice": takeProfitPrice,
175
+ "tpPrice": tpPrice,
176
176
  "tpStopType": self.settings.PROFIT_LOSS_PRICE_TYPE,
177
177
  "tpOrderType": self.settings.PROFIT_LOSS_ORDER_TYPE,
178
- "tpOrderPrice":takeProfitPrice,
179
- "slPrice": stopLossPrice,
178
+ "tpOrderPrice":tpOrderPrice,
179
+ "slPrice": slPrice,
180
180
  "slStopType": self.settings.PROFIT_LOSS_PRICE_TYPE,
181
181
  "slOrderType": self.settings.PROFIT_LOSS_ORDER_TYPE,
182
- "slOrderPrice": stopLossPrice,
182
+ "slOrderPrice": slOrderPrice,
183
183
  "positionId":positionId
184
184
  }
185
185
  datajs = await self._post_authenticated(self.placeOrder_Url,data)
@@ -3,6 +3,8 @@ import pandas as pd
3
3
  import json
4
4
  import asyncio
5
5
  from datetime import datetime, timedelta, timezone
6
+ from decimal import Decimal
7
+
6
8
  from collections import defaultdict
7
9
  import traceback
8
10
  import time
@@ -664,7 +666,18 @@ class BitunixSignal:
664
666
 
665
667
  return round(duration_minutes)
666
668
 
667
-
669
+ async def str_precision(self,num):
670
+ num_decimal = Decimal(str(num)) # Convert to Decimal to preserve precision
671
+ decimal_places = abs(num_decimal.as_tuple().exponent) # Get original decimal places
672
+ return f"{num:.{decimal_places}f}" # Format with the original precision
673
+
674
+ async def increment_by_last_decimal(self, value_str):
675
+ value = Decimal(value_str)
676
+ # Count number of decimal places
677
+ decimal_places = abs(value.as_tuple().exponent)
678
+ increment = Decimal(f'1e-{decimal_places}')
679
+ return float(value + increment)
680
+
668
681
 
669
682
  async def calculate_candles(self, timeframe, duration_minutes):
670
683
 
@@ -703,14 +716,17 @@ class BitunixSignal:
703
716
  #open position upto a max of max_auto_trades from the signal list
704
717
  df=self.signaldf.copy(deep=False)
705
718
  for index, row in df.iterrows():
706
-
707
- # Calculate the duration in minutes since the position was opened
708
719
  await asyncio.sleep(5)
720
+ data=None
721
+ # Calculate the duration in minutes since the position was opened
709
722
  data = await self.bitunixApi.GetPositionHistoryData({'symbol': row['symbol']})
710
- xtime = float(data['positionList'][0]['mtime'])
711
- mtime = pd.to_datetime(xtime, unit='ms').tz_localize('UTC').tz_convert(cst).strftime('%Y-%m-%d %H:%M:%S')
712
- duration_minutes = await self.get_duration(mtime)
713
- if duration_minutes > self.settings.DELAY_IN_MINUTES_FOR_SAME_TICKER_TRADES:
723
+ duration_minutes = None
724
+ if data and 'positionList' in data and len(data['positionList']) > 0:
725
+ xtime = float(data['positionList'][0]['mtime'])
726
+ mtime = pd.to_datetime(xtime, unit='ms').tz_localize('UTC').tz_convert(cst).strftime('%Y-%m-%d %H:%M:%S')
727
+ duration_minutes = await self.get_duration(mtime)
728
+ self.logger.info(f"row.symbol: {row.symbol} , duration_minutes: {duration_minutes}, last trade time: {mtime if duration_minutes is not None else 'N/A'}")
729
+ if duration_minutes is None or duration_minutes > self.settings.DELAY_IN_MINUTES_FOR_SAME_TICKER_TRADES:
714
730
  side = "BUY" if row[f'{period}_barcolor'] == self.green and row[f'{period}_trend'] == "BUY" else "SELL" if row[f'{period}_barcolor'] == self.red and row[f'{period}_trend'] == "SELL" else ""
715
731
  if side != "":
716
732
  select = True
@@ -721,37 +737,54 @@ class BitunixSignal:
721
737
  if self.pendingOrders and len(self.pendingOrders['orderList']) == 1:
722
738
  select = False
723
739
  if select:
740
+ balance = float(self.portfoliodf["available"].iloc[0]) + float(self.portfoliodf["crossUnrealizedPNL"].iloc[0])
741
+
724
742
  last, bid, ask, mtv = await self.GetTickerBidLastAsk(row.symbol)
725
743
 
726
744
  price = (bid if side == "BUY" else ask if side == "SELL" else last) if bid<=last<=ask else last
745
+ qty= str(max(balance * (float(self.settings.ORDER_AMOUNT_PERCENTAGE) / 100 ) / price * int(self.settings.LEVERAGE),mtv))
727
746
 
728
- tp_price=0
747
+ decimal_places = abs(Decimal(str(price)).as_tuple().exponent)
748
+
749
+ tpPrice=0
750
+ tpOrderPrice=0
729
751
  if self.settings.PROFIT_AMOUNT > 0:
730
- tp_price = price * (1 + float(self.settings.PROFIT_AMOUNT)) if side == "BUY" else price * (1 - float(self.settings.PROFIT_AMOUNT))
752
+ tpPrice = (price * qty + float(self.settings.PROFIT_AMOUNT))/qty if side == "BUY" else (price * qty - float(self.settings.PROFIT_AMOUNT))/qty
753
+ tpPrice = Decimal(await self.str_precision(tpPrice))
754
+ tpPrice =float(str(tpPrice.quantize(Decimal(f'1e-{decimal_places}'))))
755
+ tpOrderPrice = await self.increment_by_last_decimal(str(tpPrice))
731
756
  if self.settings.PROFIT_PERCENTAGE > 0 or self.settings.PROFIT_AMOUNT > 0:
732
- tp_price = 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)
757
+ tpPrice = 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)
758
+ tpPrice = Decimal(await self.str_precision(tpPrice))
759
+ tpPrice = float(str(tpPrice.quantize(Decimal(f'1e-{decimal_places}'))))
760
+ tpOrderPrice = await self.increment_by_last_decimal(await self.str_precision(tpPrice))
733
761
 
734
- lp_price=0
762
+ slPrice=0
763
+ slOrderPrice=0
735
764
  if self.settings.LOSS_AMOUNT > 0:
736
- lp_price = price * (1 - float(self.settings.LOSS_AMOUNT)) if side == "BUY" else price * (1 + float(self.settings.LOSS_AMOUNT))
765
+ slPrice = (price * qty - float(self.settings.LOSS_AMOUNT))/qty if side == "BUY" else (price * qty + float(self.settings.LOSS_AMOUNT))/qty
766
+ slPrice = Decimal(await self.str_precision(slPrice))
767
+ slPrice = float(str(slPrice.quantize(Decimal(f'1e-{decimal_places}'))))
768
+ slOrderPrice = await self.increment_by_last_decimal(str(slPrice))
737
769
  if self.settings.LOSS_PERCENTAGE > 0 or self.settings.LOSS_AMOUNT > 0:
738
- lp_price = 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)
770
+ 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)
771
+ slPrice = Decimal(await self.str_precision(slPrice))
772
+ slPrice = float(str(slPrice.quantize(Decimal(f'1e-{decimal_places}'))))
773
+ slOrderPrice = await self.increment_by_last_decimal(await self.str_precision(slPrice))
739
774
 
740
- balance = float(self.portfoliodf["available"].iloc[0]) + float(self.portfoliodf["crossUnrealizedPNL"].iloc[0])
741
- qty= str(max(balance * (float(self.settings.ORDER_AMOUNT_PERCENTAGE) / 100 ) / price * int(self.settings.LEVERAGE),mtv))
742
775
 
743
776
  self.notifications.add_notification(
744
777
  f'{colors.YELLOW} Opening {"long" if side=="BUY" else "short"} position for {row.symbol} with {qty} qty @ {price})'
745
778
  )
746
779
  datajs = None
747
- if tp_price == 0 and lp_price == 0:
780
+ if tpPrice == 0 and slPrice == 0:
748
781
  datajs = await self.bitunixApi.PlaceOrder(row.symbol, qty, price, side)
749
- elif tp_price == 0:
750
- datajs = await self.bitunixApi.PlaceOrder(row.symbol, qty, price, side, stopLossPrice=lp_price)
751
- elif lp_price == 0:
752
- datajs = await self.bitunixApi.PlaceOrder(row.symbol, qty, price, side, takeProfitPrice=tp_price)
782
+ elif tpPrice == 0:
783
+ datajs = await self.bitunixApi.PlaceOrder(row.symbol, qty, price, side, slPrice=slPrice, slOrderPrice=slOrderPrice)
784
+ elif slPrice == 0:
785
+ datajs = await self.bitunixApi.PlaceOrder(row.symbol, qty, price, side, tpPrice=tpPrice, tpOrderPrice=tpOrderPrice)
753
786
  else:
754
- datajs = await self.bitunixApi.PlaceOrder(row.symbol, qty, price, side, takeProfitPrice=tp_price, stopLossPrice=lp_price)
787
+ datajs = await self.bitunixApi.PlaceOrder(row.symbol, qty, price, side, tpPrice=tpPrice, tpOrderPrice=tpOrderPrice, slPrice=slPrice, slOrderPrice=slOrderPrice)
755
788
  count=count+1
756
789
  else:
757
790
  self.logger.info(f"Skipping {row.symbol} as it has been opened for less than {self.settings.DELAY_IN_MINUTES_FOR_SAME_TICKER_TRADES} minutes")
@@ -1 +1 @@
1
- __version__ = "3.2.9"
1
+ __version__ = "3.3.1"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: bitunix_automated_crypto_trading
3
- Version: 3.2.9
3
+ Version: 3.3.1
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,6 +1,6 @@
1
1
  bitunix_automated_crypto_trading/AsyncThreadRunner.py,sha256=bNIM_1xRYQOFEsIn74EX6qVpC59-GMhhr2CeiPr_GWg,3253
2
- bitunix_automated_crypto_trading/BitunixApi.py,sha256=NnvI8_PhliZmNEJHjwV6-AwDixU2sBFpTrtItVkyz58,13545
3
- bitunix_automated_crypto_trading/BitunixSignal.py,sha256=rKwPJ-XbKNRryxZFBxV1ED6nqho9Uvqcwuqeo2eMM8c,74699
2
+ bitunix_automated_crypto_trading/BitunixApi.py,sha256=P5lAToQDl-q8yjLD0bH3G8ajY_fxx3XKet0rS9UP7Pg,13504
3
+ bitunix_automated_crypto_trading/BitunixSignal.py,sha256=AbOhi9ehn_QY7ZAVlU_fnIUNKWoVKuy7VLZIE2v75kU,77286
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
@@ -11,9 +11,9 @@ bitunix_automated_crypto_trading/__init__.py,sha256=1hzk6nX8NnUCr1tsq8oFq1qGCNhN
11
11
  bitunix_automated_crypto_trading/bitunix.py,sha256=lxwnYARxldA2oU6GdjupilXIlnUh4RX8rQLCOn7x13I,27143
12
12
  bitunix_automated_crypto_trading/config.py,sha256=7h8GvMH1SFuFPhKM3azA2pVS0w2CRzKtUankhI-IKHY,5655
13
13
  bitunix_automated_crypto_trading/logger.py,sha256=NHnA5JZdUFkTAhB7i-1iCAwrdf1fxhDuRvJUkbKPi9Y,2923
14
- bitunix_automated_crypto_trading/version.py,sha256=2stnwoFx_N57ue44omsLCY3PMJmR-I2ZBFSGy-Dn8kM,21
15
- bitunix_automated_crypto_trading-3.2.9.dist-info/METADATA,sha256=8e5lNlFeNHBH0fnqHs_p9RgQ4dKIx_bfaUtwBq1CBEg,996
16
- bitunix_automated_crypto_trading-3.2.9.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
17
- bitunix_automated_crypto_trading-3.2.9.dist-info/entry_points.txt,sha256=UXREYHuSl2XYd_tOtLIq0zg3d1kX3lixX5SpN8yGBw4,82
18
- bitunix_automated_crypto_trading-3.2.9.dist-info/top_level.txt,sha256=uyFzHUCOsp8elnG2Ovor6xXcf7dxRxY-C-Txiwix64Q,33
19
- bitunix_automated_crypto_trading-3.2.9.dist-info/RECORD,,
14
+ bitunix_automated_crypto_trading/version.py,sha256=vFVFOckEr44mXptQFYzU0w8rn7ILjARfK9BoWOrTJxA,21
15
+ bitunix_automated_crypto_trading-3.3.1.dist-info/METADATA,sha256=pjC1qj0p9YPnHNXbIfllgnuedbaHWH61mk9tgBqrHJo,996
16
+ bitunix_automated_crypto_trading-3.3.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
17
+ bitunix_automated_crypto_trading-3.3.1.dist-info/entry_points.txt,sha256=UXREYHuSl2XYd_tOtLIq0zg3d1kX3lixX5SpN8yGBw4,82
18
+ bitunix_automated_crypto_trading-3.3.1.dist-info/top_level.txt,sha256=uyFzHUCOsp8elnG2Ovor6xXcf7dxRxY-C-Txiwix64Q,33
19
+ bitunix_automated_crypto_trading-3.3.1.dist-info/RECORD,,