bitunix-automated-crypto-trading 3.3.4__tar.gz → 3.3.6__tar.gz
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.
- {bitunix_automated_crypto_trading-3.3.4 → bitunix_automated_crypto_trading-3.3.6}/PKG-INFO +1 -1
- {bitunix_automated_crypto_trading-3.3.4 → bitunix_automated_crypto_trading-3.3.6}/README.md +7 -4
- {bitunix_automated_crypto_trading-3.3.4 → bitunix_automated_crypto_trading-3.3.6}/bitunix_automated_crypto_trading/BitunixSignal.py +55 -40
- {bitunix_automated_crypto_trading-3.3.4 → bitunix_automated_crypto_trading-3.3.6}/bitunix_automated_crypto_trading/config.py +3 -2
- bitunix_automated_crypto_trading-3.3.6/bitunix_automated_crypto_trading/version.py +1 -0
- {bitunix_automated_crypto_trading-3.3.4 → bitunix_automated_crypto_trading-3.3.6}/bitunix_automated_crypto_trading.egg-info/PKG-INFO +1 -1
- bitunix_automated_crypto_trading-3.3.4/bitunix_automated_crypto_trading/version.py +0 -1
- {bitunix_automated_crypto_trading-3.3.4 → bitunix_automated_crypto_trading-3.3.6}/bitunix_automated_crypto_trading/AsyncThreadRunner.py +0 -0
- {bitunix_automated_crypto_trading-3.3.4 → bitunix_automated_crypto_trading-3.3.6}/bitunix_automated_crypto_trading/BitunixApi.py +0 -0
- {bitunix_automated_crypto_trading-3.3.4 → bitunix_automated_crypto_trading-3.3.6}/bitunix_automated_crypto_trading/BitunixWebSocket.py +0 -0
- {bitunix_automated_crypto_trading-3.3.4 → bitunix_automated_crypto_trading-3.3.6}/bitunix_automated_crypto_trading/DataFrameHtmlRenderer.py +0 -0
- {bitunix_automated_crypto_trading-3.3.4 → bitunix_automated_crypto_trading-3.3.6}/bitunix_automated_crypto_trading/NotificationManager.py +0 -0
- {bitunix_automated_crypto_trading-3.3.4 → bitunix_automated_crypto_trading-3.3.6}/bitunix_automated_crypto_trading/SupportResistance.py +0 -0
- {bitunix_automated_crypto_trading-3.3.4 → bitunix_automated_crypto_trading-3.3.6}/bitunix_automated_crypto_trading/ThreadManager.py +0 -0
- {bitunix_automated_crypto_trading-3.3.4 → bitunix_automated_crypto_trading-3.3.6}/bitunix_automated_crypto_trading/TickerManager.py +0 -0
- {bitunix_automated_crypto_trading-3.3.4 → bitunix_automated_crypto_trading-3.3.6}/bitunix_automated_crypto_trading/__init__.py +0 -0
- {bitunix_automated_crypto_trading-3.3.4 → bitunix_automated_crypto_trading-3.3.6}/bitunix_automated_crypto_trading/bitunix.py +0 -0
- {bitunix_automated_crypto_trading-3.3.4 → bitunix_automated_crypto_trading-3.3.6}/bitunix_automated_crypto_trading/logger.py +0 -0
- {bitunix_automated_crypto_trading-3.3.4 → bitunix_automated_crypto_trading-3.3.6}/bitunix_automated_crypto_trading.egg-info/SOURCES.txt +0 -0
- {bitunix_automated_crypto_trading-3.3.4 → bitunix_automated_crypto_trading-3.3.6}/bitunix_automated_crypto_trading.egg-info/dependency_links.txt +0 -0
- {bitunix_automated_crypto_trading-3.3.4 → bitunix_automated_crypto_trading-3.3.6}/bitunix_automated_crypto_trading.egg-info/entry_points.txt +0 -0
- {bitunix_automated_crypto_trading-3.3.4 → bitunix_automated_crypto_trading-3.3.6}/bitunix_automated_crypto_trading.egg-info/requires.txt +0 -0
- {bitunix_automated_crypto_trading-3.3.4 → bitunix_automated_crypto_trading-3.3.6}/bitunix_automated_crypto_trading.egg-info/top_level.txt +0 -0
- {bitunix_automated_crypto_trading-3.3.4 → bitunix_automated_crypto_trading-3.3.6}/setup.cfg +0 -0
- {bitunix_automated_crypto_trading-3.3.4 → bitunix_automated_crypto_trading-3.3.6}/setup.py +0 -0
@@ -61,10 +61,12 @@ The platform can be configured through the `config.py` file or `config.txt`. Key
|
|
61
61
|
- `LOSS_AMOUNT`: Maximum loss amount
|
62
62
|
- `PROFIT_PERCENTAGE`: Target profit ROI percentage
|
63
63
|
- `LOSS_PERCENTAGE`: Maximum loss ROI percentage
|
64
|
-
- `
|
64
|
+
- `BOT_CONTROLS_TP_SL`: True or False
|
65
65
|
if false then take profit and stop loss will be placed by the bot when TP or SL is reached, if true then take profit and stop loss will be placed when the trade is opened
|
66
|
-
- `
|
67
|
-
if set to True then bot will
|
66
|
+
- `BOT_TRAIL_TP`
|
67
|
+
if set to True then bot will trail the TP in the direction of profit
|
68
|
+
- `BOT_TRAIL_SL`
|
69
|
+
if set to True then bot will trail the SL in the direction of profit
|
68
70
|
- `PROFIT_LOSS_PRICE_TYPE`: "MARK_PRICE" or "LAST_PRICE"
|
69
71
|
- `PROFIT_LOSS_ORDER_TYPE`: "MARKET" or "LIMIT"
|
70
72
|
- `OPTION_MOVING_AVERAGE`: Moving average period (1h, 1d, 15m, 5m, 1m)
|
@@ -181,7 +183,8 @@ The platform can be configured through the `config.py` file or `config.txt`. Key
|
|
181
183
|
- You can control the study like Moving Average, MACD, Bollinger Band, RSI or close proximity to high or low of the candle using the env file
|
182
184
|
- You can control the trading strategy using the CalculateStudy function in TickerManager.py and AutoTradeProcess function in BitunixSignal.py
|
183
185
|
- Changes are activated by unchecking and checking the AutoTrade checkbox
|
184
|
-
-
|
186
|
+
- BOT controled take profit and stop loss or take_profit and stop_loss create when order is created
|
187
|
+
- Trailing TP and SL in the direction of profit, if BOT_TRAIL_TP_SL to True and BOT_TAKE_PROFIT_STOP_LOSS to False in the config file
|
185
188
|
|
186
189
|
## Auto Trading
|
187
190
|
|
@@ -643,27 +643,21 @@ class BitunixSignal:
|
|
643
643
|
del inuse1, inuse2, inuseTickers
|
644
644
|
gc.collect()
|
645
645
|
|
646
|
-
|
647
|
-
"""Calculates the duration in minutes from trade time to current time."""
|
648
|
-
current_time_unix = int(time.time()) # Get current Unix timestamp
|
649
|
-
print(f"Current time (Unix): {current_time_unix}, Trade time (Unix): {trade_time_unix}")
|
650
|
-
duration_seconds = current_time_unix - trade_time_unix
|
651
|
-
duration_minutes = duration_seconds / 60 # Convert seconds to minutes
|
652
|
-
return round(duration_minutes)
|
653
|
-
|
646
|
+
|
654
647
|
async def get_duration(self,datetime_str):
|
655
648
|
"""Calculates the duration in minutes from a given datetime string to the current time."""
|
656
649
|
# Convert input datetime string to a datetime object
|
657
650
|
trade_time = datetime.strptime(datetime_str, "%Y-%m-%d %H:%M:%S")
|
658
|
-
|
659
|
-
# Convert datetime object to Unix timestamp
|
651
|
+
# Convert datetime object to Unix timestamp)
|
660
652
|
trade_time_unix = int(trade_time.timestamp())
|
661
|
-
|
653
|
+
print(f"trade_time_unix: {trade_time_unix}, trade_time: {trade_time}")
|
662
654
|
# Get current Unix timestamp
|
663
655
|
current_time_unix = int(time.time())
|
664
|
-
|
656
|
+
print(f"current_time_unix: {current_time_unix}, time: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
|
665
657
|
# Calculate duration in minutes
|
666
658
|
duration_minutes = (current_time_unix - trade_time_unix) / 60
|
659
|
+
print(f"diff: {current_time_unix - trade_time_unix}")
|
660
|
+
print(f"duration_minutes: {duration_minutes}")
|
667
661
|
|
668
662
|
return round(duration_minutes)
|
669
663
|
|
@@ -784,7 +778,7 @@ class BitunixSignal:
|
|
784
778
|
f'{colors.YELLOW} Opening {"long" if side=="BUY" else "short"} position for {row.symbol} with {qty} qty @ {price})'
|
785
779
|
)
|
786
780
|
datajs = None
|
787
|
-
if self.settings.
|
781
|
+
if self.settings.BOT_CONTROLS_TP_SL:
|
788
782
|
datajs = await self.bitunixApi.PlaceOrder(row.symbol, qty, price, side)
|
789
783
|
else:
|
790
784
|
if tpPrice == 0 and slPrice == 0:
|
@@ -812,7 +806,7 @@ class BitunixSignal:
|
|
812
806
|
current_time = time.time() * 1000
|
813
807
|
df=self.orderdf.copy(deep=False)
|
814
808
|
for index, row in df.iterrows():
|
815
|
-
if current_time - int(row.ctime) >
|
809
|
+
if current_time - int(row.ctime) > 60000:
|
816
810
|
self.notifications.add_notification(
|
817
811
|
f'{colors.LBLUE} Canceling order {row.orderId}, {row.symbol} {row.qty} created at {row.rtime} '
|
818
812
|
)
|
@@ -829,8 +823,8 @@ class BitunixSignal:
|
|
829
823
|
|
830
824
|
# Calculate the duration in minutes since the position was opened
|
831
825
|
ctime = row['ctime']
|
832
|
-
duration_minutes = await self.get_duration(ctime)
|
833
|
-
no_of_candles_since_current_open = await self.calculate_candles(period, duration_minutes)
|
826
|
+
#duration_minutes = await self.get_duration(ctime)
|
827
|
+
#no_of_candles_since_current_open = await self.calculate_candles(period, duration_minutes)
|
834
828
|
|
835
829
|
requiredCols=[f'{period}_open', f'{period}_close', f'{period}_high', f'{period}_low', f'{period}_ema_open', f"{period}_ema_close", f'{period}_macd', f'{period}_bbm', f'{period}_rsi', f'{period}_trendline', f'{period}_candle_trend', f'{period}_trend', f'{period}_cb', f'{period}_barcolor']
|
836
830
|
required_cols = set(requiredCols)
|
@@ -846,7 +840,7 @@ class BitunixSignal:
|
|
846
840
|
|
847
841
|
if select and int(self.settings.MAX_AUTO_TRADES)!=0:
|
848
842
|
|
849
|
-
if self.settings.
|
843
|
+
if self.settings.PROFIT_PERCENTAGE > 0 and self.settings.LOSS_PERCENTAGE > 0:
|
850
844
|
last, bid, ask, mtv = await self.GetTickerBidLastAsk(row.symbol)
|
851
845
|
price = (bid if side == "BUY" else ask if side == "SELL" else last) if bid<=last<=ask else last
|
852
846
|
decimal_places = abs(Decimal(str(price)).as_tuple().exponent)
|
@@ -861,13 +855,17 @@ class BitunixSignal:
|
|
861
855
|
old_tpPrice = None
|
862
856
|
tpStopType = self.settings.SL_STOP_TYPE
|
863
857
|
tpOrderType = self.settings.SL_ORDER_TYPE
|
858
|
+
tpOrderPrice = None
|
864
859
|
|
865
860
|
slPrice = None
|
866
861
|
slorderId = None
|
867
862
|
old_slPrice = None
|
868
863
|
slStopType = self.settings.SL_STOP_TYPE
|
869
864
|
slOrderType = self.settings.SL_ORDER_TYPE
|
865
|
+
slOrderPrice = None
|
870
866
|
|
867
|
+
roi = round((row['unrealizedPNL'] / (row['qty'] * row['avgOpenPrice'])) * 100 * self.settings.LEVERAGE,2)
|
868
|
+
|
871
869
|
datajs = await self.bitunixApi.GetPendingTpSlOrderData({'symbol': symbol})
|
872
870
|
if datajs:
|
873
871
|
for order in datajs:
|
@@ -885,35 +883,52 @@ class BitunixSignal:
|
|
885
883
|
old_slPrice = slPrice
|
886
884
|
|
887
885
|
# move TP and SL in the direction of profit
|
888
|
-
|
889
|
-
|
886
|
+
tp_midpoint = None
|
887
|
+
sl_midpoint = None
|
888
|
+
if self.settings.BOT_TRAIL_TP:
|
889
|
+
if old_tpPrice is not None:
|
890
|
+
tp_midpoint = old_tpPrice / (1 + self.settings.PROFIT_PERCENTAGE/100/self.settings.LEVERAGE) if side == "BUY" else old_tpPrice / (1 - self.settings.PROFIT_PERCENTAGE/100/self.settings.LEVERAGE) if tpPrice is not None else None
|
891
|
+
if tp_midpoint is not None and (price > tp_midpoint and side == "BUY" or price < tp_midpoint and side == "SELL"):
|
892
|
+
|
893
|
+
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)
|
894
|
+
tpPrice = Decimal(await self.str_precision(tpPrice))
|
895
|
+
tpPrice =float(str(tpPrice.quantize(Decimal(f'1e-{decimal_places}'))))
|
896
|
+
tpOrderPrice = await self.decrement_by_last_decimal(str(tpPrice))
|
890
897
|
|
891
|
-
|
892
|
-
|
893
|
-
|
894
|
-
|
898
|
+
|
899
|
+
if self.settings.BOT_TRAIL_SL:
|
900
|
+
if old_slPrice is not None:
|
901
|
+
sl_midpoint = old_slPrice / (1 - self.settings.LOSS_PERCENTAGE/100/self.settings.LEVERAGE) if side == "BUY" else old_slPrice / (1 + self.settings.LOSS_PERCENTAGE/100/self.settings.LEVERAGE) if tpPrice is not None else None
|
902
|
+
if sl_midpoint is not None and (price > sl_midpoint and side == "BUY" or price < sl_midpoint and side == "SELL"):
|
895
903
|
|
896
|
-
|
897
|
-
|
898
|
-
|
899
|
-
|
904
|
+
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)
|
905
|
+
slPrice = Decimal(await self.str_precision(slPrice))
|
906
|
+
slPrice = float(str(slPrice.quantize(Decimal(f'1e-{decimal_places}'))))
|
907
|
+
slOrderPrice = await self.increment_by_last_decimal(await self.str_precision(slPrice))
|
900
908
|
|
909
|
+
if (self.settings.BOT_TRAIL_TP and tpOrderPrice is not None) or (self.settings.BOT_TRAIL_SL and slOrderPrice is not None):
|
901
910
|
self.notifications.add_notification(
|
902
|
-
f'{colors.CYAN} {row.symbol} TP
|
911
|
+
f'{colors.CYAN} {row.symbol} price: {price}, ROI: {roi}%, TP: {old_tpPrice}, TP midpoint: {tp_midpoint}, new TP: {tpPrice}, SL: {old_slPrice}, SL midpoint: {sl_midpoint}, new SL: {slPrice}'
|
903
912
|
)
|
904
|
-
datajs3 = await self.bitunixApi.ModifyTpSlOrder({'orderId':slorderId,'slPrice':str(slPrice),'slQty':str(qty),'slStopType':slStopType,'slOrderType':slOrderType})
|
905
|
-
if datajs3 is not None:
|
906
|
-
self.notifications.add_notification(
|
907
|
-
f'{colors.CYAN} Stop Loss order for {row.symbol} moved from {old_slPrice} to {slPrice}'
|
908
|
-
)
|
909
|
-
datajs2 = await self.bitunixApi.ModifyTpSlOrder({'orderId':tporderId,'tpPrice':str(tpPrice), 'tpOrderPrice':str(tpOrderPrice), 'tpQty':str(qty),'tpStopType':tpStopType,'tpOrderType':tpOrderType})
|
910
|
-
if datajs2 is not None:
|
911
|
-
self.notifications.add_notification(
|
912
|
-
f'{colors.CYAN} Take Profit order for {row.symbol} moved from {old_tpPrice} to {tpPrice}'
|
913
|
-
)
|
914
|
-
|
915
913
|
|
916
|
-
|
914
|
+
|
915
|
+
if self.settings.BOT_TRAIL_TP and tpPrice is not None and tpOrderPrice is not None:
|
916
|
+
datajs2 = await self.bitunixApi.ModifyTpSlOrder({'orderId':tporderId,'tpPrice':str(tpPrice), 'tpOrderPrice':str(tpOrderPrice), 'tpQty':str(qty),'tpStopType':tpStopType,'tpOrderType':tpOrderType})
|
917
|
+
if datajs2 is not None:
|
918
|
+
self.notifications.add_notification(
|
919
|
+
f'{colors.CYAN} Take Profit order for {row.symbol} moved from {old_tpPrice} to {tpPrice}'
|
920
|
+
)
|
921
|
+
|
922
|
+
if self.settings.BOT_TRAIL_SL and slPrice is not None and slOrderPrice is not None:
|
923
|
+
datajs3 = await self.bitunixApi.ModifyTpSlOrder({'orderId':slorderId,'slPrice':str(slPrice),'slQty':str(qty),'slStopType':slStopType,'slOrderType':slOrderType})
|
924
|
+
if datajs3 is not None:
|
925
|
+
self.notifications.add_notification(
|
926
|
+
f'{colors.CYAN} Stop Loss order for {row.symbol} moved from {old_slPrice} to {slPrice}'
|
927
|
+
)
|
928
|
+
|
929
|
+
|
930
|
+
|
931
|
+
if self.settings.BOT_CONTROLS_TP_SL:
|
917
932
|
# check take profit amount or accept loss amount
|
918
933
|
if float(self.settings.LOSS_AMOUNT) > 0 and total_pnl < -float(self.settings.LOSS_AMOUNT):
|
919
934
|
last, bid, ask, mtv = await self.GetTickerBidLastAsk(row.symbol)
|
@@ -21,8 +21,9 @@ class Settings(BaseSettings):
|
|
21
21
|
LOSS_PERCENTAGE: float = Field(default=10, ge=0.0)
|
22
22
|
PROFIT_AMOUNT: float = Field(default=0, ge=0.0)
|
23
23
|
LOSS_AMOUNT: float = Field(default=5.0, ge=0.0)
|
24
|
-
|
25
|
-
|
24
|
+
BOT_CONTROLS_TP_SL: bool = Field(default=False)
|
25
|
+
BOT_TRAIL_TP: bool = Field(default=False)
|
26
|
+
BOT_TRAIL_SL: bool = Field(default=False)
|
26
27
|
TP_STOP_TYPE: str = Field(default="MARK_PRICE")
|
27
28
|
TP_ORDER_TYPE: str = Field(default="LIMIT")
|
28
29
|
SL_STOP_TYPE: str = Field(default="MARK_PRICE")
|
@@ -0,0 +1 @@
|
|
1
|
+
__version__ = "3.3.6"
|
@@ -1 +0,0 @@
|
|
1
|
-
__version__ = "3.3.4"
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|