From 72731932e27eb70c7849ef21a8bde5330d9ed4d0 Mon Sep 17 00:00:00 2001 From: Michael Whittle Date: Fri, 11 Aug 2023 19:57:58 +0100 Subject: [PATCH 1/8] removed statsmodels and scipy which is huge and causing a lot of problems and most likely not used --- .github/workflows/unit-tests.yml | 2 +- .vscode/settings.json | 5 +- CHANGELOG.md | 4 + Dockerfile | 2 +- README.md | 2 +- models/Trading.py | 60 ----- models/config/binance_parser.py | 2 +- requirements.txt | 2 - .../trading/test_trading_indicators.py | 219 ------------------ 9 files changed, 12 insertions(+), 286 deletions(-) diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml index e0128410..1afcae90 100644 --- a/.github/workflows/unit-tests.yml +++ b/.github/workflows/unit-tests.yml @@ -24,7 +24,7 @@ jobs: - name: Find typos with codespell uses: codespell-project/actions-codespell@master with: - ignore_words_list: zar,hist,VAI + ignore_words_list: zar,hist skip: "*.json,./tests/unit_tests/responses" - uses: actions/cache@v2 with: diff --git a/.vscode/settings.json b/.vscode/settings.json index d5af5bd9..266fff7e 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,5 @@ { - "python.formatting.provider": "black", + "python.formatting.provider": "none", "python.formatting.blackArgs": [ "--line-length", "160" @@ -8,4 +8,7 @@ "--max-line-length=160", "--ignore=E203,E266,E501,W503,F403,F401,C901", ], + "[python]": { + "editor.defaultFormatter": "ms-python.black-formatter" + }, } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 74e9fcda..d2981f81 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,10 @@ Upgrade version: Upgrade library dependencies (if required): - python3 -m pip install -r requirements.txt -U +## [8.2.0] - 2023-04 + +- removed statsmodels which has a dependency on scipy which is huge and causes a lot of problems + ## [8.0.*] - 2023-04 - bug fixes and improvements diff --git a/Dockerfile b/Dockerfile index 3d9f4218..d8254c44 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,7 +2,7 @@ FROM python:3.11.4-slim-bullseye AS compile-image RUN DEBIAN_FRONTEND=noninteractive apt-get update && \ apt-get install --no-install-recommends -y \ - build-essential gfortran && \ + build-essential && \ rm -rf /var/lib/apt/lists/* WORKDIR /app diff --git a/README.md b/README.md index 6b2a8176..f532dc57 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Python Crypto Bot v8.1.1 (pycryptobot) +# Python Crypto Bot v8.2.0 (pycryptobot) [![Docker](https://github.com/whittlem/pycryptobot/actions/workflows/container.yml/badge.svg)](https://github.com/whittlem/pycryptobot/actions/workflows/container.yml/badge.svg) [![Tests](https://github.com/whittlem/pycryptobot/actions/workflows/unit-tests.yml/badge.svg)](https://github.com/whittlem/pycryptobot/actions/workflows/unit-tests.yml/badge.svg) diff --git a/models/Trading.py b/models/Trading.py index 2ac6b793..9450dc7a 100644 --- a/models/Trading.py +++ b/models/Trading.py @@ -19,12 +19,8 @@ ) from pandas import concat, DataFrame, Series from datetime import datetime, timedelta -from statsmodels.tsa.statespace.sarimax import SARIMAX, SARIMAXResultsWrapper -from statsmodels.tools.sm_exceptions import ConvergenceWarning from views.PyCryptoBot import RichText -warnings.simplefilter("ignore", ConvergenceWarning) - class TechnicalAnalysis: def __init__(self, data=DataFrame(), total_periods: int = 300, app: object = None) -> None: @@ -772,62 +768,6 @@ def add_williamsr(self, period: int = 14) -> None: # self.df["williamsr" + str(period)] = self.df["williamsr" + str(period)].replace(nan, -50) self.df["williamsr" + str(period)] = ta.willr(high=self.df["high"], close=self.df["close"], low=self.df["low"], interval=period, fillna=self.df.close) - def seasonal_arima_model(self) -> SARIMAXResultsWrapper: - """Returns the Seasonal ARIMA Model for price predictions""" - - # hyperparameters for SARIMAX - if not self.df.index.freq: - freq = str(self.df["granularity"].iloc[-1]).replace("m", "T").replace("h", "H").replace("d", "D") - if freq.isdigit(): - freq += "S" - self.df.index = self.df.index.to_period(freq) - model = SARIMAX(self.df["close"], trend="n", order=(0, 1, 0), seasonal_order=(1, 1, 1, 12)) - return model.fit(disp=-1) - - def seasonal_arima_model_fitted_values(self): # TODO: annotate return type - """Returns the Seasonal ARIMA Model for price predictions""" - - return self.seasonal_arima_model().fittedvalues - - def seasonal_arima_model_prediction(self, minutes: int = 180) -> tuple: - """Returns seasonal ARIMA model prediction - - Parameters - ---------- - minutes : int - Number of minutes to predict - """ - - if not isinstance(minutes, int): - raise TypeError("Prediction minutes is not numeric.") - - if minutes < 1 or minutes > 4320: - raise ValueError("Predication minutes is out of range") - - results_ARIMA = self.seasonal_arima_model() - - start_ts = self.df.last_valid_index() - end_ts = start_ts + timedelta(minutes=minutes) - pred = results_ARIMA.predict(start=str(start_ts), end=str(end_ts), dynamic=True) - - try: - if len(pred) == 0: - df_last = self.df["close"].tail(1) - return ( - str(df_last.index.values[0]).replace("T", " ").replace(".000000000", ""), - df_last.values[0], - ) - else: - df_last = pred.tail(1) - return ( - str(df_last.index.values[0]).replace("T", " ").replace(".000000000", ""), - df_last.values[0], - ) - except Exception: - return None - - return None - def simple_moving_average(self, period: int) -> float: """Calculates the Simple Moving Average (SMA)""" diff --git a/models/config/binance_parser.py b/models/config/binance_parser.py index 7214176e..4ce43134 100644 --- a/models/config/binance_parser.py +++ b/models/config/binance_parser.py @@ -48,7 +48,7 @@ def parse_market(market): "NGN", "BRL", "BVND", - "VAI", + # "VAI", # causes codespell to fail in Github Actions ] for qc in quote_currencies: diff --git a/requirements.txt b/requirements.txt index 17c4cb74..749da805 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,8 +2,6 @@ urllib3>=1.26.5 pandas==1.5.1 pandas-ta numpy -scipy>=1.8.1 -statsmodels requests==2.31.0 matplotlib==3.3.3 mock==4.0.3 diff --git a/tests/unit_tests/trading/test_trading_indicators.py b/tests/unit_tests/trading/test_trading_indicators.py index 253cdd31..e4c35dc7 100644 --- a/tests/unit_tests/trading/test_trading_indicators.py +++ b/tests/unit_tests/trading/test_trading_indicators.py @@ -1,231 +1,12 @@ import sys import pandas as pd from numpy import around, round, float64, ceil -from statsmodels.compat.pandas import assert_series_equal, assert_frame_equal sys.path.append(".") # pylint: disable=import-error from models.Trading import TechnicalAnalysis -def test_should_calculate_add_change_pcnt(): - """ - Adds the close percentage to the DataFrame : close_pc - Adds the cumulative returns the DataFrame : close_cpc - - Excellent video to understand cumulative returns : https://www.youtube.com/watch?v=fWHQwqT3lNY - """ - - # GIVEN a series of values - closes_list = [0.0003, 0.0004, 0.0010, 0.0020, 0.0009] - df = pd.DataFrame( - {"date": ["2021-10-10 14:30:00", "2021-10-10 14:31:00", "2021-10-10 14:32:00", "2021-10-10 14:33:00", "2021-10-10 14:34:00"], "close": closes_list} - ) - df["date"] = pd.to_datetime(df["date"], format="%Y-%d-%m %H:%M:%S") - df.set_index(["date"]) - - ta = TechnicalAnalysis(df) - - # WHEN calculate the percentage evolution and cumulative returns percentage - ta.add_change_pcnt() - - # THEN percentage evolution and cumulative returns percentage should be added to dataframe - actual = ta.get_df() - - close_pc = [ - calculate_percentage_evol(closes_list[0], closes_list[0]), - calculate_percentage_evol(closes_list[0], closes_list[1]), - calculate_percentage_evol(closes_list[1], closes_list[2]), - calculate_percentage_evol(closes_list[2], closes_list[3]), - calculate_percentage_evol(closes_list[3], closes_list[4]), - ] - - close_cpc = [] - close_cpc.append(0.000000) - close_cpc.append((1 + close_pc[1]) * (1 + close_cpc[0]) - 1) - close_cpc.append((1 + close_pc[2]) * (1 + close_cpc[1]) - 1) - close_cpc.append((1 + close_pc[3]) * (1 + close_cpc[2]) - 1) - close_cpc.append((1 + close_pc[4]) * (1 + close_cpc[3]) - 1) - - expected = pd.DataFrame( - { - "date": ["2021-10-10 14:30:00", "2021-10-10 14:31:00", "2021-10-10 14:32:00", "2021-10-10 14:33:00", "2021-10-10 14:34:00"], - "close": closes_list, - "close_pc": close_pc, - "close_cpc": close_cpc, - } - ) - expected["date"] = pd.to_datetime(df["date"], format="%Y-%d-%m %H:%M:%S") - expected.set_index(["date"]) - assert_frame_equal(actual, expected) - - -def test_should_calculate_add_cma(): - """ - Adds the Cumulative Moving Average (CMA) to the DataFrame : cma - """ - - # GIVEN a series of values - closes_list = [0.0003, 0.0004, 0.0010, 0.0020, 0.0009] - df = pd.DataFrame( - {"date": ["2021-10-10 14:30:00", "2021-10-10 14:31:00", "2021-10-10 14:32:00", "2021-10-10 14:33:00", "2021-10-10 14:34:00"], "close": closes_list} - ) - df["date"] = pd.to_datetime(df["date"], format="%Y-%d-%m %H:%M:%S") - df.set_index(["date"]) - - ta = TechnicalAnalysis(df) - - # WHEN calculate the cumulative moving average - ta.add_cma() - - # THEN Cumulative Moving Average should be added to dataframe - actual = ta.get_df() - expected = pd.DataFrame( - { - "date": ["2021-10-10 14:30:00", "2021-10-10 14:31:00", "2021-10-10 14:32:00", "2021-10-10 14:33:00", "2021-10-10 14:34:00"], - "close": closes_list, - "cma": [ - 0.0003, - 0.00035, - 0.0005666666666666667, - 0.000925, - 0.00092, - ], # pandas_ta is doing some strange rounding, so we need to provide the expected values below - } - ) - expected["date"] = pd.to_datetime(df["date"], format="%Y-%d-%m %H:%M:%S") - expected.set_index(["date"]) - assert_frame_equal(actual, expected) - - -def test_should_calculate_add_sma_20(): - """ - Add the Simple Moving Average (SMA) to the DataFrame : - """ - - # GIVEN a series of values - closes_list = [ - 0.0003, - 0.0004, - 0.0010, - 0.0020, - 0.0009, - 0.0008, - 0.0009, - 0.0010, - 0.0012, - 0.0015, - 0.0025, - 0.0015, - 0.0014, - 0.0016, - 0.0030, - 0.0032, - 0.0035, - 0.0024, - 0.0023, - 0.0022, - 0.0021, - 0.0020, - ] - df = pd.DataFrame( - { - "date": [ - "2021-10-10 14:30:00", - "2021-10-10 14:31:00", - "2021-10-10 14:32:00", - "2021-10-10 14:33:00", - "2021-10-10 14:34:00", - "2021-10-10 14:35:00", - "2021-10-10 14:36:00", - "2021-10-10 14:37:00", - "2021-10-10 14:38:00", - "2021-10-10 14:39:00", - "2021-10-10 14:40:00", - "2021-10-10 14:41:00", - "2021-10-10 14:42:00", - "2021-10-10 14:43:00", - "2021-10-10 14:44:00", - "2021-10-10 14:45:00", - "2021-10-10 14:46:00", - "2021-10-10 14:47:00", - "2021-10-10 14:48:00", - "2021-10-10 14:49:00", - "2021-10-10 14:50:00", - "2021-10-10 14:51:00", - ], - "close": closes_list, - } - ) - df["date"] = pd.to_datetime(df["date"], format="%Y-%d-%m %H:%M:%S") - df.set_index(["date"]) - - ta = TechnicalAnalysis(df) - - # WHEN calculate the cumulative moving average 20 - ta.add_sma(20) - - # THEN - actual = ta.get_df() - expected = pd.DataFrame( - { - "date": [ - "2021-10-10 14:30:00", - "2021-10-10 14:31:00", - "2021-10-10 14:32:00", - "2021-10-10 14:33:00", - "2021-10-10 14:34:00", - "2021-10-10 14:35:00", - "2021-10-10 14:36:00", - "2021-10-10 14:37:00", - "2021-10-10 14:38:00", - "2021-10-10 14:39:00", - "2021-10-10 14:40:00", - "2021-10-10 14:41:00", - "2021-10-10 14:42:00", - "2021-10-10 14:43:00", - "2021-10-10 14:44:00", - "2021-10-10 14:45:00", - "2021-10-10 14:46:00", - "2021-10-10 14:47:00", - "2021-10-10 14:48:00", - "2021-10-10 14:49:00", - "2021-10-10 14:50:00", - "2021-10-10 14:51:00", - ], - "close": closes_list, - "sma20": [ # pandas_ta is doing some strange rounding, so we need to provide the expected values below - 0.0003, - 0.0004, - 0.001, - 0.002, - 0.0009, - 0.0008, - 0.0009, - 0.001, - 0.0012, - 0.0015, - 0.0025, - 0.0015, - 0.0014, - 0.0016, - 0.003, - 0.0032, - 0.0035, - 0.0024, - 0.0023, - 0.0016799999999999999, - 0.00177, - 0.0018499999999999999, - ], - } - ) - expected["date"] = pd.to_datetime(df["date"], format="%Y-%d-%m %H:%M:%S") - expected.set_index(["date"]) - - assert_frame_equal(actual, expected) - - def calculate_mean_on_range(start, end, list) -> float64: """ Calculates the mean on a range of values From cb66ef96b62e46e221a35ca222ce4aa33a5c6a9c Mon Sep 17 00:00:00 2001 From: Michael Whittle Date: Fri, 11 Aug 2023 20:00:50 +0100 Subject: [PATCH 2/8] Update binance_parser.py --- models/config/binance_parser.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/models/config/binance_parser.py b/models/config/binance_parser.py index 4ce43134..7214176e 100644 --- a/models/config/binance_parser.py +++ b/models/config/binance_parser.py @@ -48,7 +48,7 @@ def parse_market(market): "NGN", "BRL", "BVND", - # "VAI", # causes codespell to fail in Github Actions + "VAI", ] for qc in quote_currencies: From b36a66a312ecb5ca94243c7b0da428e92c40b1e4 Mon Sep 17 00:00:00 2001 From: Michael Whittle Date: Fri, 11 Aug 2023 20:04:31 +0100 Subject: [PATCH 3/8] updated codespell ignore words --- .github/workflows/unit-tests.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml index 1afcae90..8660c5bf 100644 --- a/.github/workflows/unit-tests.yml +++ b/.github/workflows/unit-tests.yml @@ -24,8 +24,8 @@ jobs: - name: Find typos with codespell uses: codespell-project/actions-codespell@master with: - ignore_words_list: zar,hist - skip: "*.json,./tests/unit_tests/responses" + ignore-words-list = zar,hist,VAI + skip = .venv,.git,*.json,./tests/unit_tests/responses - uses: actions/cache@v2 with: path: ${{ env.pythonLocation }} From b10fa915013632d098ccff11959e9791714abf0c Mon Sep 17 00:00:00 2001 From: Michael Whittle Date: Fri, 11 Aug 2023 20:05:42 +0100 Subject: [PATCH 4/8] updated codespell ignore words --- .github/workflows/unit-tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml index 8660c5bf..153fccc1 100644 --- a/.github/workflows/unit-tests.yml +++ b/.github/workflows/unit-tests.yml @@ -25,7 +25,7 @@ jobs: uses: codespell-project/actions-codespell@master with: ignore-words-list = zar,hist,VAI - skip = .venv,.git,*.json,./tests/unit_tests/responses + skip = "".venv,.git,*.json,./tests/unit_tests/responses" - uses: actions/cache@v2 with: path: ${{ env.pythonLocation }} From 7f9e44e1ce23c100dae014af8a76c8bae51d7842 Mon Sep 17 00:00:00 2001 From: Michael Whittle Date: Fri, 11 Aug 2023 20:06:51 +0100 Subject: [PATCH 5/8] updated codespell ignore words --- .github/workflows/unit-tests.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml index 153fccc1..d22b87fe 100644 --- a/.github/workflows/unit-tests.yml +++ b/.github/workflows/unit-tests.yml @@ -24,8 +24,8 @@ jobs: - name: Find typos with codespell uses: codespell-project/actions-codespell@master with: - ignore-words-list = zar,hist,VAI - skip = "".venv,.git,*.json,./tests/unit_tests/responses" + ignore-words-list: zar,hist,VAI + skip: ".venv,.git,*.json,./tests/unit_tests/responses" - uses: actions/cache@v2 with: path: ${{ env.pythonLocation }} From 03004f49bc5e63f7da181f24d150cee4a56b0348 Mon Sep 17 00:00:00 2001 From: Michael Whittle Date: Fri, 11 Aug 2023 20:08:13 +0100 Subject: [PATCH 6/8] updated codespell ignore words --- .github/workflows/unit-tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml index d22b87fe..56ad6716 100644 --- a/.github/workflows/unit-tests.yml +++ b/.github/workflows/unit-tests.yml @@ -24,7 +24,7 @@ jobs: - name: Find typos with codespell uses: codespell-project/actions-codespell@master with: - ignore-words-list: zar,hist,VAI + ignore_words_list: vai,zar,hist skip: ".venv,.git,*.json,./tests/unit_tests/responses" - uses: actions/cache@v2 with: From 47f033e4aac1d9ed04383d0d40362c2872e1ef49 Mon Sep 17 00:00:00 2001 From: Michael Whittle Date: Fri, 11 Aug 2023 20:17:46 +0100 Subject: [PATCH 7/8] removed seasonal arima model predictions as it's very processor intensive and not needed --- config.json.sample | 3 -- controllers/PyCryptoBot.py | 20 ------- examples/create-graphs.py | 1 - models/BotConfig.py | 2 - models/config/default_parser.py | 1 - pages/config.py | 4 -- views/TradingGraphs.py | 96 --------------------------------- websvc/app/pages/pages.py | 28 ---------- 8 files changed, 155 deletions(-) diff --git a/config.json.sample b/config.json.sample index 3917be3e..e404d961 100644 --- a/config.json.sample +++ b/config.json.sample @@ -34,7 +34,6 @@ "trailingbuypcnt": 0.5, "telegramtradesonly": 0, "granularity": "1hour", - "enableml": 0, "use_sell_fee": 1 } }, @@ -73,7 +72,6 @@ "trailingbuypcnt": 0.5, "telegramtradesonly": 0, "granularity": "3600", - "enableml": 0 } }, "coinbasepro": { @@ -111,7 +109,6 @@ "trailingbuypcnt": 0.5, "telegramtradesonly": 0, "granularity": "3600", - "enableml": 0 } }, "telegram": { diff --git a/controllers/PyCryptoBot.py b/controllers/PyCryptoBot.py index 0d6f8e0f..1a9ec4f1 100644 --- a/controllers/PyCryptoBot.py +++ b/controllers/PyCryptoBot.py @@ -910,17 +910,6 @@ def _notify(notification: str = "", level: str = "normal") -> None: self.console_log.print(self.table_console) self.table_console = Table(title=None, box=None, show_header=False, show_footer=False) # clear table - if self.enableml: - # Seasonal Autoregressive Integrated Moving Average (ARIMA) model (ML prediction for 3 intervals from now) - if not self.is_sim: - try: - prediction = _technical_analysis.arima_model_prediction(int(self.granularity.to_integer / 60) * 3) # 3 intervals from now - _notify( - f"Seasonal ARIMA model predicts the closing self.price will be {str(round(prediction[1], 2))} at {prediction[0]} (delta: {round(prediction[1] - self.price, 2)})" - ) - except Exception: - pass - if self.state.last_action == "BUY": # display support, resistance and fibonacci levels if not self.is_sim: @@ -2304,15 +2293,6 @@ def config_option_row_enum( default_value=False, arg_name="manualtradesonly", ) - config_option_row_bool( - "AI/ML Predictions", - "enableml", - "Enable AI / Machine Learning Predictions", - break_below=False, - store_invert=False, - default_value=False, - arg_name="predictions", - ) config_option_row_str( "Start Method", "startmethod", diff --git a/examples/create-graphs.py b/examples/create-graphs.py index 646fba8c..1453abd2 100644 --- a/examples/create-graphs.py +++ b/examples/create-graphs.py @@ -17,5 +17,4 @@ # tradinggraphs.render_fibonacci_retracement(True) # tradinggraphs.render_support_resistance(True) # tradinggraphs.render_candle_sticks(30, True) -# tradinggraphs.render_arima_model_prediction(1, True) tradinggraphs.render_bollinger_bands() diff --git a/models/BotConfig.py b/models/BotConfig.py index 9312a990..74e241fa 100644 --- a/models/BotConfig.py +++ b/models/BotConfig.py @@ -121,7 +121,6 @@ def __init__(self, *args, **kwargs): self.disabletelegram = False self.disablelog = False self.disabletracker = True - self.enableml = False self.websocket = False self.exitaftersell = False self.ignorepreviousbuy = True @@ -424,7 +423,6 @@ def _parse_arguments(self): parser.add_argument("--insufficientfundslogging", type=int, help="Enable insufficient funds logging") parser.add_argument("--logbuysellinjson", type=int, help="Log buy and sell orders in a JSON file") parser.add_argument("--manualtradesonly", type=int, help="Manual Trading Only (HODL)") - parser.add_argument("--predictions", type=int, help="Enable AI / Machine Learning Predictions") parser.add_argument("--startmethod", type=str, help="Bot start method ('scanner', 'standard', 'telegram')") parser.add_argument("--recvwindow", type=int, help="Binance exchange API recvwindow, integer between 5000 and 60000") parser.add_argument("--lastaction", type=str, help="Manually set the last action performed by the bot (BUY, SELL)") diff --git a/models/config/default_parser.py b/models/config/default_parser.py index 2fcb98a2..78255179 100644 --- a/models/config/default_parser.py +++ b/models/config/default_parser.py @@ -244,7 +244,6 @@ def config_option_date( config_option_bool(option_name="insufficientfundslogging", option_default=False, store_name="enableinsufficientfundslogging", store_invert=False) config_option_bool(option_name="logbuysellinjson", option_default=False, store_name="logbuysellinjson", store_invert=False) config_option_bool(option_name="manualtradesonly", option_default=False, store_name="manual_trades_only", store_invert=False) - config_option_bool(option_name="predictions", option_default=False, store_name="enableml", store_invert=False) config_option_str(option_name="startmethod", option_default="standard", store_name="startmethod", valid_options=["scanner", "standard", "telegram"]) config_option_int(option_name="recvwindow", option_default=5000, store_name="recv_window", value_min=5000, value_max=60000) config_option_str(option_name="lastaction", option_default=None, store_name="last_action", valid_options=["BUY", "SELL"]) diff --git a/pages/config.py b/pages/config.py index 11f05da8..1509c43f 100644 --- a/pages/config.py +++ b/pages/config.py @@ -480,10 +480,6 @@ "label": "Disable Bot Logs", "value": "disablelog", }, - { - "label": "Enable Machine Learning Messages", - "value": "enableml", - }, ], value=[1], id="switches-extras", diff --git a/views/TradingGraphs.py b/views/TradingGraphs.py index 02c17bc2..cbfeddc9 100644 --- a/views/TradingGraphs.py +++ b/views/TradingGraphs.py @@ -302,36 +302,6 @@ def format_date(x, pos=None): # pylint: disable=unused-argument if saveOnly is False: plt.show() - def render_seasonal_arima_model(self, saveFile="", saveOnly=False): - """Render the seasonal ARIMA model - - Parameters - ---------- - saveFile : str, optional - Save the figure - saveOnly : bool - Save the figure without displaying it - """ - - fittedValues = self.technical_analysis.seasonal_arima_model_fitted_values() - - plt.plot(self.df["close"], label="original") - plt.plot(fittedValues, color="red", label="fitted") - plt.title("RSS: %.4f" % sum((fittedValues - self.df["close"]) ** 2)) - plt.legend() - plt.ylabel("Price") - plt.xticks(rotation=90) - plt.tight_layout() - - try: - if saveFile != "": - plt.savefig(saveFile) - except OSError: - raise SystemExit(f"Unable to save: {saveFile}") - - if saveOnly is False: - plt.show() - def render_sma_and_macd(self, saveFile="", saveOnly=False): """Render the self.price, SMA20, SMA50, and SMA200 @@ -369,72 +339,6 @@ def render_sma_and_macd(self, saveFile="", saveOnly=False): if saveOnly is False: plt.show() - def render_arima_model_prediction(self, days=30, saveOnly=False): - """Render the seasonal ARIMA model prediction - - Parameters - ---------- - days : int - Number of days to predict - saveOnly : bool - Save the figure without displaying it - """ - - # get dataframe from technical analysis object - df = self.technical_analysis.get_df() - - if not isinstance(days, int): - raise TypeError("Prediction days is not numeric.") - - if days < 1 or days > len(df): - raise ValueError("Predication days is out of range") - - # extract market and granularity from trading dataframe - market = df.iloc[0].market - granularity = df.iloc[0].granularity - - results_ARIMA = self.technical_analysis.seasonal_arima_model() - - df = pd.DataFrame(self.df["close"]) - start_date = df.last_valid_index() - end_date = start_date + timedelta(days=days) - pred = results_ARIMA.predict(start=str(start_date), end=str(end_date), dynamic=True) - - fig, axes = plt.subplots(ncols=1, figsize=(12, 6)) # pylint: disable=unused-variable - fig.autofmt_xdate() - ax1 = plt.subplot(111) - ax1.set_title("Seasonal ARIMA Model Prediction") - - date = pd.to_datetime(pred.index).to_pydatetime() - - pred_length = len(pred) - # the evenly spaced plot indices - # indices = np.arange(pred_length) # TODO: why is this here? - - def format_date(x, pos=None): # pylint: disable=unused-argument - thisind = np.clip(int(x + 0.5), 0, pred_length - 1) - return date[thisind].strftime("%Y-%m-%d %H:%M:%S") - - fig, ax = plt.subplots(ncols=1, figsize=(12, 6)) # pylint: disable=unused-variable - fig.autofmt_xdate() - - ax = plt.subplot(111) - ax.set_title("Seasonal ARIMA Model Prediction") - ax.plot(pred, label="prediction", color="black") - ax.xaxis.set_major_formatter(ticker.FuncFormatter(format_date)) - - plt.xticks(rotation=90) - plt.tight_layout() - - try: - RichText.notify(f"creating: graphs/SAM_{market}_{str(granularity)}.png", self.app, "info") - plt.savefig(f"graphs/SAM_{market}_{str(granularity)}.png", dpi=300) - except OSError: - raise SystemExit(f"Unable to save: graphs/SAM_{market}_{str(granularity)}.png") - - if saveOnly is False: - plt.show() - def render_candle_stick_astral_pattern(self, period=30, saveOnly=False): # get dataframe from technical analysis object df = self.technical_analysis.get_df() diff --git a/websvc/app/pages/pages.py b/websvc/app/pages/pages.py index 8980e0a8..44279d35 100644 --- a/websvc/app/pages/pages.py +++ b/websvc/app/pages/pages.py @@ -450,32 +450,6 @@ def technical_analysis(exchange: str, market: str, g1, g2, g3) -> str: adx14_6h_class = "table-danger" adx14_6h_desc = "Weak Trend Up" - def arima_predictions(even_rows: bool = True): - results_ARIMA = ta.seasonal_arima_model() - start_date = df_1h.last_valid_index() - end_date = start_date + datetime.timedelta(days=3) - arima_pred = results_ARIMA.predict( - start=str(start_date), end=str(end_date), dynamic=True - ) - - if even_rows: - arima_pred_rows = arima_pred.iloc[::2] - else: - arima_pred_rows = arima_pred.iloc[1::2] - - html = "" - for index, pred in arima_pred_rows.items(): - html += f""" - - = ticker[1] else 'table-danger'}> - {index} - {pred} - - - """ - - return html - return f""" {header()} @@ -955,7 +929,6 @@ def arima_predictions(even_rows: bool = True): Time Prediction - {arima_predictions(True)}
@@ -964,7 +937,6 @@ def arima_predictions(even_rows: bool = True): Time Prediction - {arima_predictions(False)}
From e629923b7d1a2900cfe61a68eef00b3d3b3153d4 Mon Sep 17 00:00:00 2001 From: Michael Whittle Date: Fri, 11 Aug 2023 22:42:17 +0100 Subject: [PATCH 8/8] fixed broken test --- config.json.sample | 4 ++-- tests/unit_tests/test_telegram_bot.py | 5 +---- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/config.json.sample b/config.json.sample index e404d961..2722b9b9 100644 --- a/config.json.sample +++ b/config.json.sample @@ -71,7 +71,7 @@ "sellsmartswitch": 0, "trailingbuypcnt": 0.5, "telegramtradesonly": 0, - "granularity": "3600", + "granularity": "3600" } }, "coinbasepro": { @@ -108,7 +108,7 @@ "sellsmartswitch": 0, "trailingbuypcnt": 0.5, "telegramtradesonly": 0, - "granularity": "3600", + "granularity": "3600" } }, "telegram": { diff --git a/tests/unit_tests/test_telegram_bot.py b/tests/unit_tests/test_telegram_bot.py index bd821e05..b81ff374 100644 --- a/tests/unit_tests/test_telegram_bot.py +++ b/tests/unit_tests/test_telegram_bot.py @@ -1,12 +1,9 @@ import os import sys import unittest -# pylint: disable=import-error -from models.telegram import ( - Wrapper, -) sys.path.append(".") +from models.telegram import Wrapper wrapper = Wrapper("config.json.sample") wrapper.helper.datafolder = os.path.join(os.curdir, "tests", "unit_tests", "data")