Skip to content
This repository has been archived by the owner on Aug 27, 2024. It is now read-only.

Commit

Permalink
implement price utils & caching
Browse files Browse the repository at this point in the history
not added to algorithms yet
  • Loading branch information
CelestialCrafter committed Nov 20, 2023
1 parent 3db4785 commit 571c6c7
Show file tree
Hide file tree
Showing 10 changed files with 110 additions and 135 deletions.
6 changes: 3 additions & 3 deletions algorithms/custom_bollinger_rsi.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
from .bollinger_bands import algorithm as bollinger_bands
from .rsi import algorithm as rsi

def algorithm(prices, rsi_window=13, bollinger_window=30):
upper_band, lower_band, middle_band = bollinger_bands(prices, window_size=bollinger_window)
rsi_line = rsi(prices, window_size=rsi_window)
def algorithm(prices, window_size_rsi=13, window_size_bollinger_bands=30):
upper_band, lower_band, middle_band = bollinger_bands(prices, window_size=window_size_bollinger_bands)
rsi_line = rsi(prices, window_size=window_size_rsi)

return upper_band, lower_band, middle_band, rsi_line

Expand Down
4 changes: 0 additions & 4 deletions config.json

This file was deleted.

157 changes: 47 additions & 110 deletions environment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,124 +3,61 @@ channels:
- conda-forge
- defaults
dependencies:
- _libgcc_mutex=0.1=conda_forge
- _openmp_mutex=4.5=2_kmp_llvm
- binutils_linux-64=2.28.1=he4fe6c7_1
- blas=1.1=openblas
- brotli=1.0.9=h5eee18b_7
- brotli-bin=1.0.9=h5eee18b_7
- bzip2=1.0.8=h7b6447c_0
- ca-certificates=2023.08.22=h06a4308_0
- contourpy=1.0.5=py310hdb19cb5_0
- cycler=0.11.0=pyhd3eb1b0_0
- cyrus-sasl=2.1.28=h9c0eb46_1
- dbus=1.13.18=hb2f20db_0
- expat=2.5.0=h6a678d5_0
- fontconfig=2.14.1=h4c34cd2_2
- fonttools=4.25.0=pyhd3eb1b0_0
- freetype=2.12.1=h4a9f257_0
- gcc_linux-64=7.2.0=hc7b1ceb_1
- giflib=5.2.1=h5eee18b_3
- glib=2.69.1=h4ff587b_1
- gst-plugins-base=1.14.1=h6a678d5_1
- gstreamer=1.14.1=h5eee18b_1
- icu=58.2=he6710b0_3
- jpeg=9e=h5eee18b_1
- kiwisolver=1.4.4=py310h6a678d5_0
- krb5=1.20.1=h568e23c_1
- lcms2=2.12=h3be6417_0
- ld_impl_linux-64=2.38=h1181459_1
- lerc=3.0=h295c915_0
- libbrotlicommon=1.0.9=h5eee18b_7
- libbrotlidec=1.0.9=h5eee18b_7
- libbrotlienc=1.0.9=h5eee18b_7
- libclang=14.0.6=default_hc6dbbc7_1
- libclang13=14.0.6=default_he11475f_1
- libcups=2.4.2=ha637b67_0
- libdeflate=1.17=h5eee18b_1
- libedit=3.1.20221030=h5eee18b_0
- libevent=2.1.12=h8f2d780_0
- libffi=3.3=he6710b0_2
- libgcc-ng=13.2.0=h807b86a_2
- libgfortran-ng=13.2.0=h69a702a_2
- libgfortran5=13.2.0=ha4646dd_2
- libllvm14=14.0.6=hef93074_0
- libopenblas=0.3.24=pthreads_h413a1c8_0
- libpng=1.6.39=h5eee18b_0
- libpq=12.15=h37d81fd_1
- libstdcxx-ng=11.2.0=h1234567_1
- libta-lib=0.4.0=hd590300_2
- libtiff=4.5.1=h6a678d5_0
- libuuid=1.41.5=h5eee18b_0
- libwebp=1.3.2=h11a3e52_0
- libwebp-base=1.3.2=h5eee18b_0
- libxcb=1.15=h7f8727e_0
- libxkbcommon=1.0.1=h5eee18b_1
- libxml2=2.10.4=hcbfbd50_0
- libxslt=1.1.37=h2085143_0
- llvm-openmp=14.0.6=h9e868ea_0
- lz4-c=1.9.4=h6a678d5_0
- matplotlib=3.7.2=py310h06a4308_0
- matplotlib-base=3.7.2=py310h1128e8f_0
- munkres=1.1.4=py_0
- mysql=5.7.24=he378463_2
- ncurses=6.4=h6a678d5_0
- nspr=4.35=h6a678d5_0
- nss=3.89.1=h6a678d5_0
- numpy=1.26.0=py310heeff2f4_0
- numpy-base=1.26.0=py310h8a23956_0
- openblas=0.3.24=pthreads_h7a3da1a_0
- openjpeg=2.4.0=h3ad879b_0
- openssl=1.1.1w=h7f8727e_0
- packaging=23.1=py310h06a4308_0
- pcre=8.45=h295c915_0
- pillow=10.0.1=py310ha6cbd5a_0
- pip=23.2.1=py310h06a4308_0
- ply=3.11=py310h06a4308_0
- pyparsing=3.0.9=py310h06a4308_0
- pyqt=5.15.7=py310h6a678d5_1
- python=3.10.0=h12debd9_5
- python-dateutil=2.8.2=pyhd3eb1b0_0
- python_abi=3.10=2_cp310
- qt-main=5.15.2=h5b8104b_9
- qt-webengine=5.15.9=h9ab4d14_7
- qtwebkit=5.212=h3fafdc1_5
- readline=8.2=h5eee18b_0
- setuptools=68.0.0=py310h06a4308_0
- sip=6.6.2=py310h6a678d5_0
- six=1.16.0=pyhd3eb1b0_1
- sqlite=3.41.2=h5eee18b_0
- ta-lib=0.4.28=py310h1f7b6fc_0
- tk=8.6.12=h1ccaba5_0
- toml=0.10.2=pyhd3eb1b0_0
- tornado=6.3.3=py310h5eee18b_0
- tzdata=2023c=h04d1e81_0
- wheel=0.41.2=py310h06a4308_0
- xz=5.4.2=h5eee18b_0
- zlib=1.2.13=h5eee18b_0
- zstd=1.5.5=hc292b87_0
- bzip2=1.0.8
- ca-certificates=2023.7.22
- intel-openmp=2023.2.0
- libblas=3.9.0
- libcblas=3.9.0
- libffi=3.4.4
- liblapack=3.9.0
- libta-lib=0.4.0
- mkl=2020.4
- openssl=3.0.11
- pip=23.2.1
- python=3.10.13
- python_abi=3.10
- setuptools=68.0.0
- sqlite=3.41.2
- ta-lib=0.4.19
- tk=8.6.12
- vc=14.2
- vs2015_runtime=14.27.29016
- wheel=0.41.2
- xz=5.4.2
- zlib=1.2.13
- pip:
- blinker==1.6.3
- async-timeout==4.0.3
- blinker==1.6.2
- certifi==2023.7.22
- charset-normalizer==3.3.0
- click==8.1.7
- colorama==0.4.6
- contourpy==1.1.1
- cycler==0.12.0
- dnspython==2.4.2
- flask==3.0.0
- hiredis==2.2.3
- flask==2.3.3
- fonttools==4.43.0
- idna==3.4
- importlib-metadata==6.8.0
- itsdangerous==2.1.2
- jinja2==3.1.2
- kiwisolver==1.4.5
- markupsafe==2.1.3
- platformdirs==3.11.0
- matplotlib==3.8.0
- numpy==1.26.0
- packaging==23.1
- pandas==2.1.1
- pillow==10.0.1
- pyjwt==2.8.0
- pymongo==4.5.0
- pyqt5-sip==12.11.0
- pyparsing==3.1.1
- python-dateutil==2.8.2
- python-dotenv==1.0.0
- redis==5.0.1
- pytz==2023.3.post1
- redis==5.0.0
- requests==2.31.0
- tomli==2.0.1
- urllib3==2.0.6
- waitress==2.1.2
- werkzeug==3.0.0
- yapf==0.40.2
- zipp==3.17.0
prefix: /home/celestial/anaconda3/envs/auto-trading
- schedule==1.2.1
- six==1.16.0
- tzdata==2023.3
- urllib3==2.0.5
- werkzeug==2.3.7
prefix: C:\Users\Celestial2\miniconda3\envs\auto-trading
4 changes: 1 addition & 3 deletions plot.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
import json
import numpy as np
import matplotlib.pyplot as plt
from price import get_prices
from plots.bollinger_bands import plot as boillinger_bands
from plots.rsi import plot as rsi

config = json.load(open('config.json', 'r'))
prices = get_prices(address=config['address'] if 'address' in config else None)
prices = get_prices()

# RSI
plt.subplot(221)
Expand Down
4 changes: 2 additions & 2 deletions plots/bollinger_bands.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
from algorithms.bollinger_bands import algorithm as boillinger_bands
import plots.colors as colors

def plot(prices):
upper_band, lower_band, middle_band = boillinger_bands(prices)
def plot(prices, **kwargs):
upper_band, lower_band, middle_band = boillinger_bands(prices, **kwargs)

indicies = np.arange(0, upper_band.shape[0])
sliced_prices = prices[:upper_band.shape[0]]
Expand Down
6 changes: 3 additions & 3 deletions plots/custom_bollinger_rsi.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
import numpy as np
import matplotlib.pyplot as plt
import plots.colors as colors
from matplotlib.gridspec import GridSpec
from algorithms.custom_bollinger_rsi import algorithm as custom_bollinger_rsi
from plots.rsi import plot as rsi
from plots.bollinger_bands import plot as bollinger_bands
import plots.colors as colors

def plot(prices):
def plot(prices, **kwargs):
gs = GridSpec(3, 1, figure=plt.gcf())

plt.subplot(gs[0, :])
indicies = np.arange(0, prices.shape[0])
plt.plot(indicies, prices, color=colors.mainline())

upper_band, lower_band, middle_band, rsi_line = custom_bollinger_rsi(prices)
upper_band, lower_band, middle_band, rsi_line = custom_bollinger_rsi(prices, **kwargs)
sliced_prices = prices[:min(upper_band.shape[0], rsi_line.shape[0])]
indicies = np.arange(0, indicies.shape[0])

Expand Down
4 changes: 2 additions & 2 deletions plots/rsi.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
from algorithms.rsi import algorithm as rsi
import plots.colors as colors

def plot(prices):
rsi_line = rsi(prices)
def plot(prices, **kwargs):
rsi_line = rsi(prices, **kwargs)
indicies = np.arange(0, rsi_line.shape[0])

plt.plot(indicies, rsi_line, color=colors.mainline())
Expand Down
48 changes: 47 additions & 1 deletion price.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,60 @@
import schedule, os, time
import numpy as np
from requests import get
from redis import from_url
from dotenv import load_dotenv
from threading import Thread

load_dotenv()
redis = from_url(os.environ['REDIS_URI'])

# {60 300 900 3600 21600 86400}
# 1m 5m 15m 1h 6h 1d
# 5h 25h 3d3h 12d12h 2mo15d 10mo
def get_prices(pair, interval=21600):
def get_prices(pair='ETH-USD', interval=21600):
ohlc = get(f'https://api.exchange.coinbase.com/products/{pair}/candles?granularity={interval}').json()
ticker = get(f'https://api.exchange.coinbase.com/products/{pair}/ticker').json()

current = float(ticker['price'])
prices = [point[4] for point in ohlc]

return np.flip([current, *prices])

def get_cached_prices(interval=21600):
np.array(redis.lrange(f'prices:{interval}', 0, -1))

def get_periods(period_size, period_type, interval):
if period_type == 'months':
period_multiplier = 30 * 24 * 60 * 60
elif period_type == 'weeks':
period_multiplier = 7 * 24 * 60 * 60
elif period_type == 'days':
period_multiplier = 24 * 60 * 60
elif period_type == 'hours':
period_multiplier = 60 * 60
elif period_type == 'minutes':
period_multiplier = 60
elif period_type == 'seconds':
period_multiplier = 1
period_seconds = period_size * period_multiplier

return period_seconds / interval

# Price Caching
cachedIntervals = [60, 300, 3600, 21600]

def cache_prices():
for interval in cachedIntervals:
print(f'Caching prices for {interval}')
prices = get_prices(interval=interval)
redis.lpush(f'prices:{interval}', *prices)

schedule.every(1).minutes.do(cache_prices)

def job_loop():
while True:
schedule.run_pending()
time.sleep(1)

thread = Thread(target=job_loop, daemon=True)
thread.start()
5 changes: 2 additions & 3 deletions views/internal_checker.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import jwt, json, os
import jwt, os
from redis import from_url
from price import get_prices
from ipaddress import ip_address
Expand Down Expand Up @@ -31,8 +31,7 @@ def internal_checker():
if jwt_decoded['event'] != 'auth':
return 'Unauthorized', 401

config = json.load(open('config.json', 'r'))
prices = get_prices(config['pair'], interval=config['interval'])
prices = get_prices()

# Convert list of algorithms into {name: signal}
algorithms = get_algorithms()
Expand Down
7 changes: 3 additions & 4 deletions views/plot.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
import io, json
import io
import matplotlib
import matplotlib.pyplot as plt
import plots.colors as colors
from utils import get_algorithms
from price import get_prices
from price import get_cached_prices
from importlib import import_module
from utils import get_algorithms

matplotlib.use('Agg')

def plot(algorithm):
config = json.load(open('config.json', 'r'))
prices = get_prices(config['pair'], interval=config['interval'])
prices = get_cached_prices()

if algorithm not in ['price', *get_algorithms()]:
return 'Invalid Algorithm', 404
Expand Down

0 comments on commit 571c6c7

Please sign in to comment.