bitunix-automated-crypto-trading 3.1.5__tar.gz → 3.1.7__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.1.5 → bitunix_automated_crypto_trading-3.1.7}/PKG-INFO +1 -1
- {bitunix_automated_crypto_trading-3.1.5 → bitunix_automated_crypto_trading-3.1.7}/README.md +7 -0
- {bitunix_automated_crypto_trading-3.1.5 → bitunix_automated_crypto_trading-3.1.7}/bitunix_automated_crypto_trading/BitunixSignal.py +30 -20
- {bitunix_automated_crypto_trading-3.1.5 → bitunix_automated_crypto_trading-3.1.7}/bitunix_automated_crypto_trading/TickerManager.py +98 -25
- {bitunix_automated_crypto_trading-3.1.5 → bitunix_automated_crypto_trading-3.1.7}/bitunix_automated_crypto_trading/config.py +11 -5
- {bitunix_automated_crypto_trading-3.1.5 → bitunix_automated_crypto_trading-3.1.7}/bitunix_automated_crypto_trading.egg-info/PKG-INFO +1 -1
- {bitunix_automated_crypto_trading-3.1.5 → bitunix_automated_crypto_trading-3.1.7}/setup.py +1 -1
- {bitunix_automated_crypto_trading-3.1.5 → bitunix_automated_crypto_trading-3.1.7}/bitunix_automated_crypto_trading/AsyncThreadRunner.py +0 -0
- {bitunix_automated_crypto_trading-3.1.5 → bitunix_automated_crypto_trading-3.1.7}/bitunix_automated_crypto_trading/BitunixApi.py +0 -0
- {bitunix_automated_crypto_trading-3.1.5 → bitunix_automated_crypto_trading-3.1.7}/bitunix_automated_crypto_trading/BitunixWebSocket.py +0 -0
- {bitunix_automated_crypto_trading-3.1.5 → bitunix_automated_crypto_trading-3.1.7}/bitunix_automated_crypto_trading/DataFrameHtmlRenderer.py +0 -0
- {bitunix_automated_crypto_trading-3.1.5 → bitunix_automated_crypto_trading-3.1.7}/bitunix_automated_crypto_trading/NotificationManager.py +0 -0
- {bitunix_automated_crypto_trading-3.1.5 → bitunix_automated_crypto_trading-3.1.7}/bitunix_automated_crypto_trading/SupportResistance.py +0 -0
- {bitunix_automated_crypto_trading-3.1.5 → bitunix_automated_crypto_trading-3.1.7}/bitunix_automated_crypto_trading/ThreadManager.py +0 -0
- {bitunix_automated_crypto_trading-3.1.5 → bitunix_automated_crypto_trading-3.1.7}/bitunix_automated_crypto_trading/__init__.py +0 -0
- {bitunix_automated_crypto_trading-3.1.5 → bitunix_automated_crypto_trading-3.1.7}/bitunix_automated_crypto_trading/bitunix.py +0 -0
- {bitunix_automated_crypto_trading-3.1.5 → bitunix_automated_crypto_trading-3.1.7}/bitunix_automated_crypto_trading/logger.py +0 -0
- {bitunix_automated_crypto_trading-3.1.5 → bitunix_automated_crypto_trading-3.1.7}/bitunix_automated_crypto_trading.egg-info/SOURCES.txt +0 -0
- {bitunix_automated_crypto_trading-3.1.5 → bitunix_automated_crypto_trading-3.1.7}/bitunix_automated_crypto_trading.egg-info/dependency_links.txt +0 -0
- {bitunix_automated_crypto_trading-3.1.5 → bitunix_automated_crypto_trading-3.1.7}/bitunix_automated_crypto_trading.egg-info/entry_points.txt +0 -0
- {bitunix_automated_crypto_trading-3.1.5 → bitunix_automated_crypto_trading-3.1.7}/bitunix_automated_crypto_trading.egg-info/requires.txt +0 -0
- {bitunix_automated_crypto_trading-3.1.5 → bitunix_automated_crypto_trading-3.1.7}/bitunix_automated_crypto_trading.egg-info/top_level.txt +0 -0
- {bitunix_automated_crypto_trading-3.1.5 → bitunix_automated_crypto_trading-3.1.7}/setup.cfg +0 -0
@@ -26,6 +26,7 @@ A real-time cryptocurrency trading platform built with FastAPI and WebSocket tec
|
|
26
26
|
- MACD
|
27
27
|
- Bollinger Bands
|
28
28
|
- RSI
|
29
|
+
- Support and Resistance levels
|
29
30
|
- Brearish or bullish candle based on the close near high or low of the current candle
|
30
31
|
- strength based on consecutive colored candles count
|
31
32
|
- ADX
|
@@ -48,6 +49,7 @@ A real-time cryptocurrency trading platform built with FastAPI and WebSocket tec
|
|
48
49
|
The platform can be configured through the `config.py` file or `config.txt`. Key configuration parameters include:
|
49
50
|
- Trading Parameters:
|
50
51
|
- `AUTOTRADE` : True or False
|
52
|
+
- `TICKERS`: supply a list of tickers seperated by comma to trade, e.g., "BTCUSDT,ETHUSDT" or "" to auto select based on MIN_VOLUME and THRESHOLD
|
51
53
|
- `LEVERAGE`: Trading leverage (1-100)
|
52
54
|
- `THRESHOLD`: Ticker selection based close near high or low of the day
|
53
55
|
- `MIN_VOLUME`: Ticker selection based on Minimum trading volume
|
@@ -59,6 +61,7 @@ The platform can be configured through the `config.py` file or `config.txt`. Key
|
|
59
61
|
- `BARS`: Number of bars to use for study and charting
|
60
62
|
|
61
63
|
- `Technical Indicators Parameters`:
|
64
|
+
- `BOS_PERIOD`: Break of structure period, number of bars to look back to determine the previous high or low
|
62
65
|
- `MA_FAST`: Fast moving average period
|
63
66
|
- `MA_MEDIUM`: Medium moving average period
|
64
67
|
- `MA_SLOW`: Slow moving average period
|
@@ -72,6 +75,7 @@ The platform can be configured through the `config.py` file or `config.txt`. Key
|
|
72
75
|
- `ADX_PERIOD`: ADX period
|
73
76
|
|
74
77
|
- `Study Parameters`:
|
78
|
+
- `BOS_STUDY`: Enable Break Of Structure study
|
75
79
|
- `EMA_STUDY`: Enable EMA study
|
76
80
|
- `EMA_CHART`: Display EMA chart
|
77
81
|
- `EMA_STUDY`: Enable EMA study
|
@@ -98,9 +102,11 @@ The platform can be configured through the `config.py` file or `config.txt`. Key
|
|
98
102
|
- `RSI_CHECK_ON_OPEN`: Check RSI on open
|
99
103
|
- `RSI_CHECK_ON_CLOSE`: Check RSI on close
|
100
104
|
|
105
|
+
- `TRENDLINE_PEAK_DISTANCE` : distance between peaks or troughs
|
101
106
|
- `TRENDLINE_STUDY`: Enable Trendline support and resistance study
|
102
107
|
- `TRENDLINE_CHART`: Display Trendline chart
|
103
108
|
- `TRENDLINE_LOOKBACK`: Lookback period for trendline study
|
109
|
+
- `TRENDLINE_BREAKOUT`: Check if breakout from support or resistance line
|
104
110
|
- `TRENDLINE_CHECK_ON_OPEN`: Check Trendline support and resistance on open
|
105
111
|
- `TRENDLINE_CHECK_ON_CLOSE`: Check Trendline support and resistance on close
|
106
112
|
|
@@ -155,6 +161,7 @@ The platform can be configured through the `config.py` file or `config.txt`. Key
|
|
155
161
|
- Max auto trades
|
156
162
|
- Take Profit amount
|
157
163
|
- Accept Loss amount
|
164
|
+
- BOS study is basically when the price breakout from the previous high or low
|
158
165
|
- 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
|
159
166
|
- You can control the trading strategy using the CalculateStudy function in TickerManager.py and AutoTradeProcess function in BitunixSignal.py
|
160
167
|
- Changes are activated by unchecking and checking the AutoTrade checkbox
|
@@ -99,19 +99,23 @@ class BitunixSignal:
|
|
99
99
|
self.tickerObjects.update_settings(settings)
|
100
100
|
|
101
101
|
async def load_tickers(self):
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
102
|
+
if self.settings.TICKERS=="":
|
103
|
+
symbols = await self.bitunixApi.GetTickerList(float(self.settings.THRESHOLD), float(self.settings.MIN_VOLUME))
|
104
|
+
self.pendingPositions= await self.bitunixApi.GetPendingPositionData()
|
105
|
+
self.pendingOrders= await self.bitunixApi.GetPendingOrderData()
|
106
|
+
olist=[]
|
107
|
+
plist=[]
|
108
|
+
if self.pendingPositions:
|
109
|
+
plist = [entry['symbol'] for entry in self.pendingPositions]
|
110
|
+
if self.pendingOrders['orderList']:
|
111
|
+
olist = [entry['symbol'] for entry in self.pendingOrders['orderList']]
|
112
|
+
newlist=olist+plist+list(set(symbols))
|
113
|
+
self.tickerList=newlist[:300]
|
114
|
+
self.tickerList.remove("STMXUSDT")
|
115
|
+
#self.tickerList=['POLUSDT']
|
116
|
+
else:
|
117
|
+
self.tickerList = self.settings.TICKERS.split(",")
|
118
|
+
self.tickerList = [sym.strip().upper() for sym in self.tickerList if sym.strip()]
|
115
119
|
|
116
120
|
[await self.add_ticker_to_tickerObjects(sym) for sym in self.tickerList]
|
117
121
|
self.notifications.add_notification(f"{len(self.tickerList)} ticker list loaded")
|
@@ -559,11 +563,16 @@ class BitunixSignal:
|
|
559
563
|
self.signaldf_filtered = self.tickerObjects.signaldf_filtered
|
560
564
|
|
561
565
|
if not self.positiondf.empty and not self.signaldf_full.empty:
|
562
|
-
columns=['symbol', f"{period}_trend", f"{period}_cb", f"{period}_barcolor",
|
566
|
+
columns=['symbol', f"{period}_trend", f"{period}_cb", f"{period}_barcolor",
|
567
|
+
f"{period}_bos",
|
568
|
+
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}_open", f"{period}_close", f"{period}_high", f"{period}_low"]
|
563
569
|
columns2=["qty", "side", "unrealizedPNL", "realizedPNL", "ctime", "avgOpenPrice", "bid", "bidcolor", "last", "lastcolor", "ask", "askcolor", "charts", "bitunix", "action", "add", "reduce"]
|
564
570
|
if set(columns).issubset(self.signaldf_full.columns) and set(columns2).issubset(self.positiondf.columns):
|
565
|
-
columnOrder= ['symbol', "side", "unrealizedPNL", "realizedPNL", f"{period}_trend", f"{period}_cb", f"{period}_barcolor",
|
571
|
+
columnOrder= ['symbol', "side", "unrealizedPNL", "realizedPNL", f"{period}_trend", f"{period}_cb", f"{period}_barcolor",
|
572
|
+
f"{period}_bos",
|
573
|
+
f"{period}_ema_open", f"{period}_ema_close", f"{period}_macd", f"{period}_bbm", f"{period}_rsi", f"{period}_trendline", f"{period}_adx", f"{period}_candle_trend", f"{period}_open", f"{period}_close", f"{period}_high", f"{period}_low", "qty", "ctime", "avgOpenPrice", "bid", "bidcolor", "last", "lastcolor", "ask", "askcolor", "charts", "bitunix", "action", "add", "reduce"]
|
566
574
|
self.positiondf2 = pd.merge(self.positiondf, self.signaldf_full[["symbol", f"{period}_open", f"{period}_close", f"{period}_high", f"{period}_low",
|
575
|
+
f"{period}_bos",
|
567
576
|
f"{period}_ema_open", f"{period}_ema_close", f"{period}_macd", f"{period}_bbm", f"{period}_rsi", f"{period}_trendline", f"{period}_adx", f"{period}_candle_trend",
|
568
577
|
f"{period}_trend",f"{period}_cb", f"{period}_barcolor"]], left_on="symbol", right_index=True, how="left")[columnOrder]
|
569
578
|
self.positiondfStyle= self.positiondfrenderer.render_html(self.positiondf2)
|
@@ -578,6 +587,7 @@ class BitunixSignal:
|
|
578
587
|
# Assign to self.signaldf for HTML rendering
|
579
588
|
self.signaldf = self.signaldf_filtered[[
|
580
589
|
"symbol", f"{period}_trend",f"{period}_cb", f"{period}_barcolor",
|
590
|
+
f"{period}_bos",
|
581
591
|
f"{period}_ema_open", f"{period}_ema_close", f"{period}_macd", f"{period}_bbm", f"{period}_rsi", f"{period}_trendline",f"{period}_adx",f"{period}_candle_trend",
|
582
592
|
'lastcolor', 'bidcolor', 'askcolor', 'bid', 'last', 'ask',
|
583
593
|
f"{period}_open", f"{period}_close", f"{period}_high", f"{period}_low",
|
@@ -640,7 +650,7 @@ class BitunixSignal:
|
|
640
650
|
#open position upto a max of max_auto_trades from the signal list
|
641
651
|
df=self.signaldf.copy(deep=False)
|
642
652
|
for index, row in df.iterrows():
|
643
|
-
side = "BUY" if row[f'{period}_barcolor'] == self.green else "SELL" if row[f'{period}_barcolor'] == self.red else ""
|
653
|
+
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 ""
|
644
654
|
if side != "":
|
645
655
|
select = True
|
646
656
|
self.pendingPositions = await self.bitunixApi.GetPendingPositionData({'symbol': row.symbol})
|
@@ -945,8 +955,8 @@ class BitunixSignal:
|
|
945
955
|
continue
|
946
956
|
|
947
957
|
# candle reversed
|
948
|
-
if self.settings.CANDLE_TREND_STUDY and self.settings.
|
949
|
-
if row.side == 'BUY' and self.signaldf_full.at[row.symbol, f'{period}_barcolor'] == self.red and self.signaldf_full.at[row.symbol, f'{period}_candle_trend'] == "
|
958
|
+
if self.settings.CANDLE_TREND_STUDY and self.settings.CANDLE_TREND_REVERSAL_CHECK_ON_CLOSE:
|
959
|
+
if row.side == 'BUY' and self.signaldf_full.at[row.symbol, f'{period}_barcolor'] == self.red and self.signaldf_full.at[row.symbol, f'{period}_cb'] > 1 and self.signaldf_full.at[row.symbol, f'{period}_candle_trend'] == "BULLISH":
|
950
960
|
last, bid, ask, mtv = await self.GetTickerBidLastAsk(row.symbol)
|
951
961
|
price = (ask if row['side'] == "BUY" else bid if row['side'] == "SELL" else last) if bid<=last<=ask else last
|
952
962
|
|
@@ -963,7 +973,7 @@ class BitunixSignal:
|
|
963
973
|
)
|
964
974
|
continue
|
965
975
|
|
966
|
-
if row.side == 'SELL' and self.signaldf_full.at[row.symbol, f'{period}_barcolor'] == self.green
|
976
|
+
if row.side == 'SELL' and self.signaldf_full.at[row.symbol, f'{period}_barcolor'] == self.green and self.signaldf_full.at[row.symbol, f'{period}_cb'] > 1 and self.signaldf_full.at[row.symbol, f'{period}_candle_trend'] == "BULLISH":
|
967
977
|
last, bid, ask, mtv = await self.GetTickerBidLastAsk(row.symbol)
|
968
978
|
price = (ask if row['side'] == "BUY" else bid if row['side'] == "SELL" else last) if bid<=last<=ask else last
|
969
979
|
|
@@ -982,7 +992,7 @@ class BitunixSignal:
|
|
982
992
|
|
983
993
|
await asyncio.sleep(0)
|
984
994
|
|
985
|
-
|
995
|
+
self.lastAutoTradeTime = time.time()
|
986
996
|
except Exception as e:
|
987
997
|
stack = traceback.extract_stack()
|
988
998
|
function_name = stack[-1].name
|
@@ -63,6 +63,23 @@ class Interval:
|
|
63
63
|
# Get the last color and its consecutive count
|
64
64
|
self.signal_strength = df['Consecutive'].iloc[-1]
|
65
65
|
|
66
|
+
# Break of Strcuture
|
67
|
+
if self.settings.BOS_STUDY:
|
68
|
+
if df['high'].size > 1 and df['low'].size > 1 and df['close'].size > 1:
|
69
|
+
high = talib.MAX(df.iloc[:-1]['high'].values, timeperiod=self.settings.BOS_PERIOD)[-1]
|
70
|
+
low = talib.MIN(df.iloc[:-1]['low'].values, timeperiod=self.settings.BOS_PERIOD)[-1]
|
71
|
+
close = df['close'].iloc[-1]
|
72
|
+
if close > high:
|
73
|
+
self.bos_signal = "BUY"
|
74
|
+
elif close < low:
|
75
|
+
self.bos_signal = "SELL"
|
76
|
+
else:
|
77
|
+
self.bos_signal = "HOLD"
|
78
|
+
else:
|
79
|
+
self.bos_signal = "HOLD"
|
80
|
+
else:
|
81
|
+
self.bos_signal = "HOLD"
|
82
|
+
|
66
83
|
# Calculate the Moving Averages
|
67
84
|
if self.settings.EMA_STUDY:
|
68
85
|
df['ma_fast'] = talib.EMA(df['close'], timeperiod=self.settings.MA_FAST)
|
@@ -116,6 +133,14 @@ class Interval:
|
|
116
133
|
else:
|
117
134
|
self.ema_open_signal = "HOLD"
|
118
135
|
self.ema_close_signal = "HOLD"
|
136
|
+
|
137
|
+
if self.settings.EMA_CLOSE_ON_FAST_MEDIUM:
|
138
|
+
if df['close'].iloc[-1] > df['ma_fast'].iloc[-1] and df['ma_fast'].iloc[-1] > df['ma_medium'].iloc[-1]:
|
139
|
+
self.ema_close_signal = "BUY"
|
140
|
+
elif df['close'].iloc[-1] < df['ma_fast'].iloc[-1] and df['ma_fast'].iloc[-1] < df['ma_medium'].iloc[-1]:
|
141
|
+
self.ema_close_signal = "SELL"
|
142
|
+
else:
|
143
|
+
self.ema_close_signal = "HOLD"
|
119
144
|
else:
|
120
145
|
# Drop EMA columns if not used
|
121
146
|
df.drop(['ma_fast', 'ma_medium', 'ma_slow', 'ma_slope', 'ma_angle'], axis=1, inplace=True, errors='ignore')
|
@@ -233,16 +258,20 @@ class Interval:
|
|
233
258
|
df.fillna({'support_line':0}, inplace=True)
|
234
259
|
df.fillna({'resistance_line':0}, inplace=True)
|
235
260
|
if df is not None and len(df) >= 2:
|
236
|
-
if
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
self.trendline_signal = "SELL"
|
261
|
+
if self.settings.TRENDLINE_BREAKOUT:
|
262
|
+
if df['close'].iloc[-2] > df['support_line'].iloc[-2] and df['open'].iloc[-1] > df['support_line'].iloc[-1] and df['close'].iloc[-1] > df['open'].iloc[-1]:
|
263
|
+
self.trendline_signal = "BUY"
|
264
|
+
elif df['close'].iloc[-2] < df['resistance_line'].iloc[-2] and df['open'].iloc[-1] < df['resistance_line'].iloc[-1] and df['close'].iloc[-1] < df['open'].iloc[-1]:
|
265
|
+
self.trendline_signal = "SELL"
|
266
|
+
else:
|
267
|
+
self.trendline_signal = "HOLD"
|
244
268
|
else:
|
245
|
-
|
269
|
+
if df['high'].iloc[-3] >= df['support_line'].iloc[-3] and df['close'].iloc[-2] < df['support_line'].iloc[-2] and df['close'].iloc[-1] < df['open'].iloc[-1]:
|
270
|
+
self.trendline_signal = "SELL"
|
271
|
+
elif df['low'].iloc[-3] <= df['resistance_line'].iloc[-3] and df['close'].iloc[-2] > df['resistance_line'].iloc[-2] and df['close'].iloc[-1] > df['open'].iloc[-1]:
|
272
|
+
self.trendline_signal = "BUY"
|
273
|
+
else:
|
274
|
+
self.trendline_signal = "HOLD"
|
246
275
|
|
247
276
|
# Calculate the ADX
|
248
277
|
if self.settings.ADX_STUDY:
|
@@ -288,6 +317,7 @@ class Interval:
|
|
288
317
|
|
289
318
|
# Check for BUY signal
|
290
319
|
buy_conditions = (
|
320
|
+
(self.settings.BOS_STUDY and self.bos_signal == "BUY") or
|
291
321
|
(self.settings.EMA_STUDY and self.settings.EMA_CHECK_ON_OPEN and self.ema_open_signal == "BUY") or
|
292
322
|
(self.settings.MACD_STUDY and self.settings.MACD_CHECK_ON_OPEN and self.macd_signal == "BUY") or
|
293
323
|
(self.settings.BBM_STUDY and self.settings.BBM_CHECK_ON_OPEN and self.bbm_signal == "BUY") or
|
@@ -301,6 +331,7 @@ class Interval:
|
|
301
331
|
|
302
332
|
# Check for SELL signal
|
303
333
|
sell_conditions = (
|
334
|
+
(self.settings.BOS_STUDY and self.bos_signal == "SELL") or
|
304
335
|
(self.settings.EMA_STUDY and self.settings.EMA_CHECK_ON_OPEN and self.ema_open_signal == "SELL") or
|
305
336
|
(self.settings.MACD_STUDY and self.settings.MACD_CHECK_ON_OPEN and self.macd_signal == "SELL") or
|
306
337
|
(self.settings.BBM_STUDY and self.settings.BBM_CHECK_ON_OPEN and self.bbm_signal == "SELL") or
|
@@ -320,17 +351,34 @@ class Interval:
|
|
320
351
|
else:
|
321
352
|
self.current_signal = "HOLD"
|
322
353
|
else:
|
323
|
-
# If EMA is enabled and crossing and MACD is enabled and crossing and BBM is enabled and crossing and RSI is enbabled and crossing
|
324
|
-
# and
|
325
|
-
# ADX is enabled and strong and candle trend is enabled and bullish
|
326
|
-
# then BUY or SELL
|
327
354
|
buy_conditions = (
|
328
|
-
(
|
329
|
-
|
330
|
-
|
331
|
-
(
|
332
|
-
|
355
|
+
(self.settings.BOS_STUDY and self.bos_signal == "BUY")
|
356
|
+
or not self.settings.BOS_STUDY
|
357
|
+
) and (
|
358
|
+
(self.settings.EMA_STUDY and self.settings.EMA_CHECK_ON_OPEN and self.ema_open_signal == "BUY")
|
359
|
+
or not self.settings.EMA_STUDY or not self.settings.EMA_CHECK_ON_OPEN
|
360
|
+
) and (
|
361
|
+
(self.settings.MACD_STUDY and self.settings.MACD_CHECK_ON_OPEN and self.macd_signal == "BUY")
|
362
|
+
or not self.settings.MACD_STUDY or not self.settings.MACD_CHECK_ON_OPEN
|
363
|
+
) and (
|
364
|
+
(self.settings.BBM_STUDY and self.settings.BBM_CHECK_ON_OPEN and self.bbm_signal == "BUY")
|
365
|
+
or not self.settings.BBM_STUDY or not self.settings.BBM_CHECK_ON_OPEN
|
366
|
+
) and (
|
367
|
+
(self.settings.RSI_STUDY and self.settings.RSI_CHECK_ON_OPEN and self.rsi_signal == "BUY")
|
368
|
+
or not self.settings.RSI_STUDY or not self.settings.RSI_CHECK_ON_OPEN
|
369
|
+
) and (
|
370
|
+
(self.settings.TRENDLINE_STUDY and self.settings.TRENDLINE_CHECK_ON_OPEN and self.trendline_signal == "BUY")
|
371
|
+
or not self.settings.TRENDLINE_STUDY or not self.settings.TRENDLINE_CHECK_ON_OPEN
|
333
372
|
)
|
373
|
+
if not any([
|
374
|
+
self.settings.EMA_STUDY, self.settings.MACD_STUDY, self.settings.BBM_STUDY,
|
375
|
+
self.settings.RSI_STUDY, self.settings.TRENDLINE_STUDY
|
376
|
+
]) and not any([
|
377
|
+
self.settings.EMA_CHECK_ON_OPEN, self.settings.MACD_CHECK_ON_OPEN, self.settings.BBM_CHECK_ON_OPEN,
|
378
|
+
self.settings.RSI_CHECK_ON_OPEN, self.settings.TRENDLINE_CHECK_ON_OPEN
|
379
|
+
]):
|
380
|
+
buy_conditions = False
|
381
|
+
|
334
382
|
additional_buy_conditions = (
|
335
383
|
(not self.settings.ADX_STUDY or not self.settings.ADX_CHECK_ON_OPEN or self.adx_signal == "STRONG") and
|
336
384
|
(not self.settings.CANDLE_TREND_STUDY or not self.settings.CANDLE_TREND_CHECK_ON_OPEN or self.candle_trend == "BULLISH")
|
@@ -338,15 +386,36 @@ class Interval:
|
|
338
386
|
|
339
387
|
# Check for SELL signal
|
340
388
|
sell_conditions = (
|
341
|
-
(
|
342
|
-
|
343
|
-
|
344
|
-
(
|
345
|
-
|
389
|
+
(self.settings.BOS_STUDY and self.bos_signal == "SELL")
|
390
|
+
or not self.settings.BOS_STUDY
|
391
|
+
) and (
|
392
|
+
(self.settings.EMA_STUDY and self.settings.EMA_CHECK_ON_OPEN and self.ema_open_signal == "SELL")
|
393
|
+
or not self.settings.EMA_STUDY or not self.settings.EMA_CHECK_ON_OPEN
|
394
|
+
) and (
|
395
|
+
(self.settings.MACD_STUDY and self.settings.MACD_CHECK_ON_OPEN and self.macd_signal == "SELL")
|
396
|
+
or not self.settings.MACD_STUDY or not self.settings.MACD_CHECK_ON_OPEN
|
397
|
+
) and (
|
398
|
+
(self.settings.BBM_STUDY and self.settings.BBM_CHECK_ON_OPEN and self.bbm_signal == "SELL")
|
399
|
+
or not self.settings.BBM_STUDY or not self.settings.BBM_CHECK_ON_OPEN
|
400
|
+
) and (
|
401
|
+
(self.settings.RSI_STUDY and self.settings.RSI_CHECK_ON_OPEN and self.rsi_signal == "SELL")
|
402
|
+
or not self.settings.RSI_STUDY or not self.settings.RSI_CHECK_ON_OPEN
|
403
|
+
) and (
|
404
|
+
(self.settings.TRENDLINE_STUDY and self.settings.TRENDLINE_CHECK_ON_OPEN and self.trendline_signal == "SELL")
|
405
|
+
or not self.settings.TRENDLINE_STUDY or not self.settings.TRENDLINE_CHECK_ON_OPEN
|
346
406
|
)
|
407
|
+
if not any([
|
408
|
+
self.settings.EMA_STUDY, self.settings.MACD_STUDY, self.settings.BBM_STUDY,
|
409
|
+
self.settings.RSI_STUDY, self.settings.TRENDLINE_STUDY
|
410
|
+
]) and not any([
|
411
|
+
self.settings.EMA_CHECK_ON_OPEN, self.settings.MACD_CHECK_ON_OPEN, self.settings.BBM_CHECK_ON_OPEN,
|
412
|
+
self.settings.RSI_CHECK_ON_OPEN, self.settings.TRENDLINE_CHECK_ON_OPEN
|
413
|
+
]):
|
414
|
+
sell_conditions = False
|
415
|
+
|
347
416
|
additional_sell_conditions = (
|
348
|
-
(
|
349
|
-
(
|
417
|
+
(self.settings.ADX_STUDY and self.settings.ADX_CHECK_ON_OPEN and self.adx_signal == "STRONG") or
|
418
|
+
(self.settings.CANDLE_TREND_STUDY and self.settings.CANDLE_TREND_CHECK_ON_OPEN or self.candle_trend == "BEARISH")
|
350
419
|
)
|
351
420
|
|
352
421
|
# Determine current signal
|
@@ -623,6 +692,7 @@ class Tickers:
|
|
623
692
|
if not interval._data is None and len(interval._data) >= self.settings.BARS:
|
624
693
|
args[0].get_interval_ticks(intervalId)._data = interval._data
|
625
694
|
args[0].get_interval_ticks(intervalId).current_signal = interval.current_signal
|
695
|
+
args[0].get_interval_ticks(intervalId).bos_signal = interval.bos_signal
|
626
696
|
args[0].get_interval_ticks(intervalId).ema_open_signal = interval.ema_open_signal
|
627
697
|
args[0].get_interval_ticks(intervalId).ema_close_signal = interval.ema_close_signal
|
628
698
|
args[0].get_interval_ticks(intervalId).macd_signal = interval.macd_signal
|
@@ -660,6 +730,8 @@ class Tickers:
|
|
660
730
|
f"{period}_trend": intervalObj.current_signal,
|
661
731
|
f"{period}_cb": intervalObj.signal_strength,
|
662
732
|
f"{period}_barcolor": lastcandle['barcolor'],
|
733
|
+
f"{period}_bos": intervalObj.bos_signal,
|
734
|
+
f"{period}_ema_open": intervalObj.ema_open_signal,
|
663
735
|
f"{period}_ema_open": intervalObj.ema_open_signal,
|
664
736
|
f"{period}_ema_close": intervalObj.ema_close_signal,
|
665
737
|
f"{period}_macd":intervalObj.macd_signal,
|
@@ -687,6 +759,7 @@ class Tickers:
|
|
687
759
|
'lastcolor': "", 'bidcolor': "", 'askcolor': "", 'bid': 0.0, 'ask': 0.0, 'last': 0.0,
|
688
760
|
f"{period}_cb":0, f"{period}_barcolor": "", f"{period}_trend": "",
|
689
761
|
f"{period}_open": 0.0, f"{period}_close": 0.0, f"{period}_high": 0.0, f"{period}_low": 0.0,
|
762
|
+
f"{period}_bos": "",
|
690
763
|
f"{period}_ema": "", f"{period}_macd": "", f"{period}_bbm": "", f"{period}_rsi": "", f"{period}_trendline": "", f"{period}_candle_trend": "", f"{period}_adx": ""
|
691
764
|
}
|
692
765
|
df.fillna(fill_values, inplace=True)
|
@@ -6,11 +6,14 @@ import sqlite3
|
|
6
6
|
class Settings(BaseSettings):
|
7
7
|
# Start autotrading on start
|
8
8
|
AUTOTRADE: bool = Field(default=False)
|
9
|
+
|
10
|
+
#Ticker list
|
11
|
+
TICKERS:str = Field(default="")
|
12
|
+
THRESHOLD: float = Field(default=5.0, ge=0.0)
|
13
|
+
MIN_VOLUME: int = Field(default=10_000_000, ge=0)
|
9
14
|
|
10
15
|
# Trading Parameters
|
11
16
|
LEVERAGE: int = Field(default=20, ge=1, le=100)
|
12
|
-
THRESHOLD: float = Field(default=5.0, ge=0.0)
|
13
|
-
MIN_VOLUME: int = Field(default=10_000_000, ge=0)
|
14
17
|
ORDER_AMOUNT_PERCENTAGE: float = Field(default=0.01, ge=0.0, le=100)
|
15
18
|
MAX_AUTO_TRADES: int = Field(default=10, ge=0)
|
16
19
|
PROFIT_AMOUNT: float = Field(default=0.25, ge=0.0)
|
@@ -19,6 +22,7 @@ class Settings(BaseSettings):
|
|
19
22
|
BARS: int = Field(default=100, ge=1)
|
20
23
|
|
21
24
|
# Technical Indicators Parameters
|
25
|
+
BOS_PERIOD: int = Field(default=20, ge=1)
|
22
26
|
MA_FAST: int = Field(default=10, ge=1)
|
23
27
|
MA_MEDIUM: int = Field(default=20, ge=1)
|
24
28
|
MA_SLOW: int = Field(default=50, ge=1)
|
@@ -34,6 +38,7 @@ class Settings(BaseSettings):
|
|
34
38
|
# Technical Indicators
|
35
39
|
OPEN_ON_ANY_SIGNAL: bool = Field(default=True)
|
36
40
|
|
41
|
+
BOS_STUDY: bool = Field(default=True)
|
37
42
|
EMA_CHART: bool = Field(default=True)
|
38
43
|
EMA_STUDY: bool = Field(default=True)
|
39
44
|
EMA_CROSSING: bool = Field(default=False)
|
@@ -59,10 +64,10 @@ class Settings(BaseSettings):
|
|
59
64
|
RSI_CHECK_ON_OPEN: bool = Field(default=False)
|
60
65
|
RSI_CHECK_ON_CLOSE: bool = Field(default=False)
|
61
66
|
|
67
|
+
TRENDLINE_PEAK_DISTANCE: int = Field(default=1, ge=0, le=30)
|
62
68
|
TRENDLINE_CHART: bool = Field(default=True)
|
63
69
|
TRENDLINE_STUDY: bool = Field(default=True)
|
64
|
-
|
65
|
-
TRENDLINE_LOOKBACK: int = Field(default=20, ge=10, le=200)
|
70
|
+
TRENDLINE_BREAKOUT: bool = Field(default=False)
|
66
71
|
TRENDLINE_CHECK_ON_OPEN: bool = Field(default=False)
|
67
72
|
TRENDLINE_CHECK_ON_CLOSE: bool = Field(default=False)
|
68
73
|
|
@@ -72,7 +77,7 @@ class Settings(BaseSettings):
|
|
72
77
|
|
73
78
|
CANDLE_TREND_STUDY: bool = Field(default=True)
|
74
79
|
CANDLE_TREND_CHECK_ON_OPEN: bool = Field(default=False)
|
75
|
-
|
80
|
+
CANDLE_TREND_REVERSAL_CHECK_ON_CLOSE: bool = Field(default=False)
|
76
81
|
|
77
82
|
# Time Intervals
|
78
83
|
SCREEN_REFRESH_INTERVAL: int = Field(default=1, ge=1)
|
@@ -101,6 +106,7 @@ class Settings(BaseSettings):
|
|
101
106
|
# Specify the file name for loading environment variables
|
102
107
|
env_file = os.path.dirname(os.path.abspath(__file__))+"/config.txt"
|
103
108
|
|
109
|
+
|
104
110
|
@classmethod
|
105
111
|
def load_from_db(cls, db_path: str, table_name: str = "settings"):
|
106
112
|
# Connect to SQLite database
|
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
|