Skip to content

Commit

Permalink
Merge pull request #825 from whittlem/beta
Browse files Browse the repository at this point in the history
Merging beta into main
  • Loading branch information
whittlem authored Aug 11, 2023
2 parents d562d8e + e629923 commit c0833d4
Show file tree
Hide file tree
Showing 17 changed files with 15 additions and 447 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/unit-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ jobs:
- name: Find typos with codespell
uses: codespell-project/actions-codespell@master
with:
ignore_words_list: zar,hist,VAI
skip: "*.json,./tests/unit_tests/responses"
ignore_words_list: vai,zar,hist
skip: ".venv,.git,*.json,./tests/unit_tests/responses"
- uses: actions/cache@v2
with:
path: ${{ env.pythonLocation }}
Expand Down
5 changes: 4 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"python.formatting.provider": "black",
"python.formatting.provider": "none",
"python.formatting.blackArgs": [
"--line-length",
"160"
Expand All @@ -8,4 +8,7 @@
"--max-line-length=160",
"--ignore=E203,E266,E501,W503,F403,F401,C901",
],
"[python]": {
"editor.defaultFormatter": "ms-python.black-formatter"
},
}
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -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)

Expand Down
7 changes: 2 additions & 5 deletions config.json.sample
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@
"trailingbuypcnt": 0.5,
"telegramtradesonly": 0,
"granularity": "1hour",
"enableml": 0,
"use_sell_fee": 1
}
},
Expand Down Expand Up @@ -72,8 +71,7 @@
"sellsmartswitch": 0,
"trailingbuypcnt": 0.5,
"telegramtradesonly": 0,
"granularity": "3600",
"enableml": 0
"granularity": "3600"
}
},
"coinbasepro": {
Expand Down Expand Up @@ -110,8 +108,7 @@
"sellsmartswitch": 0,
"trailingbuypcnt": 0.5,
"telegramtradesonly": 0,
"granularity": "3600",
"enableml": 0
"granularity": "3600"
}
},
"telegram": {
Expand Down
20 changes: 0 additions & 20 deletions controllers/PyCryptoBot.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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",
Expand Down
1 change: 0 additions & 1 deletion examples/create-graphs.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()
2 changes: 0 additions & 2 deletions models/BotConfig.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)")
Expand Down
60 changes: 0 additions & 60 deletions models/Trading.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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)"""

Expand Down
1 change: 0 additions & 1 deletion models/config/default_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -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"])
Expand Down
4 changes: 0 additions & 4 deletions pages/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -480,10 +480,6 @@
"label": "Disable Bot Logs",
"value": "disablelog",
},
{
"label": "Enable Machine Learning Messages",
"value": "enableml",
},
],
value=[1],
id="switches-extras",
Expand Down
2 changes: 0 additions & 2 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
5 changes: 1 addition & 4 deletions tests/unit_tests/test_telegram_bot.py
Original file line number Diff line number Diff line change
@@ -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")
Expand Down
Loading

0 comments on commit c0833d4

Please sign in to comment.