-
Notifications
You must be signed in to change notification settings - Fork 770
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
116 changed files
with
1,905 additions
and
714 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
from starlette.responses import JSONResponse | ||
|
||
from jesse.modes.import_candles_mode import CandleExchange | ||
from jesse.modes.import_candles_mode.drivers import drivers, driver_names | ||
|
||
|
||
def get_exchange_supported_symbols(exchange: str) -> JSONResponse: | ||
arr = [] | ||
|
||
try: | ||
driver: CandleExchange = drivers[exchange]() | ||
except KeyError: | ||
raise ValueError(f'{exchange} is not a supported exchange. Supported exchanges are: {driver_names}') | ||
|
||
try: | ||
arr = driver.get_available_symbols() | ||
except Exception as e: | ||
return JSONResponse({ | ||
'error': str(e) | ||
}, status_code=500) | ||
|
||
return JSONResponse({ | ||
'data': arr | ||
}, status_code=200) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
from collections import namedtuple | ||
|
||
from .wma import wma | ||
from .ema import ema | ||
import numpy as np | ||
from jesse.helpers import get_candle_source, slice_candles | ||
|
||
HullSuit = namedtuple('HullSuit', ['s_hull', 'm_hull', 'signal']) | ||
|
||
|
||
def hull_suit(candles: np.ndarray, mode_switch: str = 'Hma', length: int = 55, length_mult: float = 1.0, source_type: str = 'close', sequential: bool = False) -> HullSuit: | ||
""" | ||
@author InSilico | ||
credits: https://www.tradingview.com/script/hg92pFwS-Hull-Suite/ | ||
HullSuit - Hull Suit | ||
:param candles: np.ndarray | ||
:param mode_switch: str - default: 'Hma' | ||
:param length: int - default: 55 | ||
:param length_mult: float - default: 1.0 | ||
:param source_type: str - default: "closes" | ||
:param sequential: bool - default=False | ||
:return: float | np.ndarray | ||
""" | ||
if len(candles.shape) == 1: | ||
source = candles | ||
else: | ||
candles = slice_candles(candles, sequential) | ||
source = get_candle_source(candles, source_type=source_type) | ||
|
||
mode_len = int(length * length_mult) | ||
if mode_switch == 'Hma': | ||
mode = wma(2*wma(source, mode_len / 2, sequential=True) - wma(source, | ||
mode_len, sequential=True), round(mode_len ** 0.5), sequential=True) | ||
elif mode_switch == 'Ehma': | ||
mode = ema(2*ema(source, mode_len / 2, sequential=True) - ema(source, | ||
mode_len, sequential=True), round(mode_len ** 0.5), sequential=True) | ||
elif mode_switch == 'Thma': | ||
mode = wma(3*wma(source, mode_len / 6, sequential=True) - wma(source, mode_len / 4, sequential=True) - | ||
wma(source, mode_len / 2, sequential=True), mode_len / 2, sequential=True) | ||
|
||
s_hull = [] | ||
m_hull = [] | ||
signal = [] | ||
for i in range(len(mode)): | ||
if i > 1: | ||
s_hull.append(mode[i - 2]) | ||
m_hull.append(mode[i]) | ||
signal.append('buy' if mode[i - 2] < mode[i] else 'sell') | ||
else: | ||
s_hull.append(None) | ||
m_hull.append(None) | ||
signal.append(None) | ||
|
||
if sequential: | ||
return HullSuit(s_hull, m_hull, signal) | ||
else: | ||
return HullSuit(s_hull[-1], m_hull[-1], signal[-1]) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
from collections import namedtuple | ||
|
||
from .bollinger_bands import bollinger_bands | ||
from .sma import sma | ||
from .trange import trange | ||
from .linearreg import linearreg | ||
from .stddev import stddev | ||
import numpy as np | ||
|
||
SqueezeMomentum = namedtuple('SqueezeMomentum', ['squeeze', 'momentum', 'momentum_signal']) | ||
|
||
|
||
def squeeze_momentum(candles: np.ndarray, length: int = 20, mult: float = 2.0, length_kc: int = 20, mult_kc: float = 1.5, sequential: bool = True) -> SqueezeMomentum: | ||
""" | ||
@author lazyBear | ||
credits: https://www.tradingview.com/script/nqQ1DT5a-Squeeze-Momentum-Indicator-LazyBear/ | ||
squeeze_momentum | ||
:param candles: np.ndarray | ||
:length: int - default: 20 | ||
:mult: float - default: 2.0 | ||
:length_kc: float - default: 2.0 | ||
:mult_kc: float - default: 1.5 | ||
:sequential: bool - default: True | ||
:return: SqueezeMomentum(squeeze, momentum, momentum_signal) | ||
""" | ||
# calculate bollinger bands | ||
basis = sma(candles, length, sequential=True) | ||
dev = mult_kc * stddev(candles, length, sequential=True) | ||
upper_bb = basis + dev | ||
lower_bb = basis - dev | ||
|
||
# calculate KC | ||
ma = sma(candles, length_kc, sequential=True) | ||
range_ma = sma(trange(candles, sequential=True), period=length_kc, sequential=True) | ||
upper_kc = ma + range_ma * mult_kc | ||
lower_kc = ma - range_ma * mult_kc | ||
|
||
sqz = [] | ||
for i in range(len(lower_bb)): | ||
sqz_on = (lower_bb[i] > lower_kc[i]) and (upper_bb[i] < upper_kc[i]) | ||
sqz_off = (lower_bb[i] < lower_kc[i]) and (upper_bb[i] > upper_kc[i]) | ||
noSqz = (sqz_on == False) and (sqz_off == False) | ||
sqz.append(0 if noSqz else (-1 if sqz_on else 1)) | ||
|
||
highs = np.nan_to_num(_highest(candles[:, 3], length_kc), 0) | ||
lows = np.nan_to_num(_lowest(candles[:, 4], length_kc), 0) | ||
sma_arr = np.nan_to_num(sma(candles, period=length_kc, sequential=True)) | ||
|
||
momentum = [] | ||
for i in range(len(highs)): | ||
momentum.append(candles[:, 2][i] - ((highs[i] + lows[i]) / 2 + sma_arr[i]) / 2) | ||
|
||
momentum = linearreg(np.array(momentum), period=length_kc, sequential=True) | ||
|
||
momentum_signal = [] | ||
for i in range(len(momentum) - 1): | ||
if momentum[i + 1] > 0: | ||
momentum_signal.append(1 if momentum[i + 1] > momentum[i] else 2) | ||
else: | ||
momentum_signal.append(-1 if momentum[i + 1] < momentum[i] else -2) | ||
|
||
if sequential: | ||
return SqueezeMomentum(sqz, momentum, momentum_signal) | ||
else: | ||
return SqueezeMomentum(sqz[-1], momentum[-1], momentum_signal[-1]) | ||
|
||
|
||
def _highest(values, length): | ||
# Ensure values is a NumPy array for efficient computation | ||
values = np.asarray(values) | ||
# Initialize an array to hold the highest values | ||
highest_values = np.full(values.shape, np.nan) | ||
# Compute the highest value for each window | ||
for i in range(length - 1, len(values)): | ||
highest_values[i] = np.max(values[i - length + 1:i + 1]) | ||
return highest_values | ||
|
||
|
||
def _lowest(values, length): | ||
# Ensure values is a NumPy array for efficient computation | ||
values = np.asarray(values) | ||
# Initialize an array to hold the lowest values | ||
lowest_values = np.full(values.shape, np.nan) | ||
# Compute the lowest value for each window | ||
for i in range(length - 1, len(values)): | ||
lowest_values[i] = np.min(values[i - length + 1:i + 1]) | ||
return lowest_values |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import json | ||
import peewee | ||
from jesse.services.db import database | ||
|
||
if database.is_closed(): | ||
database.open_connection() | ||
|
||
|
||
class ExchangeApiKeys(peewee.Model): | ||
id = peewee.UUIDField(primary_key=True) | ||
exchange_name = peewee.CharField() | ||
name = peewee.CharField(unique=True) | ||
api_key = peewee.CharField() | ||
api_secret = peewee.CharField() | ||
additional_fields = peewee.TextField() | ||
created_at = peewee.DateTimeField() | ||
|
||
class Meta: | ||
from jesse.services.db import database | ||
|
||
database = database.db | ||
|
||
def __init__(self, attributes=None, **kwargs) -> None: | ||
peewee.Model.__init__(self, attributes=attributes, **kwargs) | ||
|
||
if attributes is None: | ||
attributes = {} | ||
|
||
for a in attributes: | ||
setattr(self, a, attributes[a]) | ||
|
||
def get_additional_fields(self) -> dict: | ||
return json.loads(self.additional_fields) | ||
|
||
|
||
# if database is open, create the table | ||
if database.is_open(): | ||
ExchangeApiKeys.create_table() |
Oops, something went wrong.