Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge changes from rd-mg #62

Open
wants to merge 75 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
75 commits
Select commit Hold shift + click to select a range
d838d87
Update README.md
rd-mg Jun 30, 2022
d01fb1a
Update README.md
rd-mg Jun 30, 2022
5153b7d
LRSI computes now as tradingview
Jul 20, 2022
e06cafb
Added uptrend.py and Uptrend definitions as duplicated from crossovers
Jul 20, 2022
4efae60
Uptrend signal working
Jul 21, 2022
fc6ec91
Readme and config .md updated
Jul 21, 2022
b97c965
Readme and config .md updated
Jul 21, 2022
78eb8da
notification.py fix list out of index ['values']
Jul 22, 2022
d8d323d
notification.py fix list out of index ['values'] line 696
Jul 22, 2022
ca46fac
Merge pull request #1 from rd-mg/uptrend
rd-mg Jul 22, 2022
95e63b4
readme updated
Jul 27, 2022
d30b45b
macd_cross macdhist added
Nov 2, 2022
0cf79fc
ROC added, bbp middle band remove
Nov 9, 2022
9473704
ROC added
Nov 9, 2022
b3e7dc4
add roc to defaults
Nov 9, 2022
86fd10d
bbp mid_band needed
Nov 9, 2022
c3c4efe
NATR 14 added
Nov 9, 2022
d65aead
natr added
Nov 9, 2022
682a97b
natr init added
Nov 9, 2022
31e0321
typo
Nov 9, 2022
59cb356
added bbwidth to bollinger bands method
Nov 9, 2022
3e45f47
add.
Nov 9, 2022
c44d2df
bbwidth formula changed
Nov 9, 2022
cdaa12c
setCopywarning solution
Nov 9, 2022
7cfff14
bbp origanl method returned warning still happends
Nov 9, 2022
1f01c4c
aded hot cold previous to add informants
Nov 10, 2022
fc7f8a4
informants added to messages
Nov 10, 2022
8261e37
dataframe return
Nov 10, 2022
d9f4d29
change natr to indicators
Nov 10, 2022
a74b061
natr
Nov 10, 2022
0797ac2
natr moved
Nov 10, 2022
7594971
changed roc bb to indicators
Nov 10, 2022
47e739a
Readme mod
Nov 10, 2022
8d5d8f6
pandas-ta and ifish
Nov 14, 2022
a4a8758
ifish added updated
Nov 15, 2022
65d7929
Stoch_rsi changed to pandas-ta
Nov 15, 2022
d0fb8f2
stochrsi_cross changed to pandas-ta
Nov 15, 2022
52d442d
default max_periods changed to 24
Nov 15, 2022
d78b535
max_periods changed to 50
Nov 15, 2022
481b1ce
parameters updated
Nov 15, 2022
96762b0
updated ifish coldtresh
Nov 15, 2022
9e2f660
print commented
Nov 15, 2022
310308a
bbp warning solved
Nov 15, 2022
07a726c
ifish smooth 9
Nov 15, 2022
7a95cae
wma length 9
Nov 15, 2022
cc4f351
updated periods
Nov 16, 2022
1ef325d
updated periods
Nov 16, 2022
39721bd
indices error
Nov 16, 2022
68d5adf
indicators conditions updated
Nov 16, 2022
b1154f7
condition updated
Nov 16, 2022
599af5d
parameters updated
Nov 16, 2022
626887b
fix: app/requirements-step-1.txt to reduce vulnerabilities
snyk-bot Nov 18, 2022
81b5a15
iiv volume compute reformulated
Nov 19, 2022
6849cec
change to close to detect pump dump
Nov 19, 2022
73852a1
condition mod
Nov 19, 2022
399556d
fix
Nov 19, 2022
c3c1f7d
IIV returned to original code, IIP created
Nov 21, 2022
7159c5a
iip indicator added
Nov 21, 2022
ed42339
compute modified
Nov 25, 2022
0ab3d6b
debug print removed
Nov 25, 2022
9ad1208
avoid not send message to telegram chat because message is blank
Nov 26, 2022
ed7e812
undone
Nov 26, 2022
3f94120
fail to ban
Dec 8, 2022
d7ea2fa
-y
Dec 8, 2022
0b23e33
Merge pull request #8 from rd-mg/snyk-fix-a51ebfe14d45b6023d09214a2eb…
rd-mg Dec 8, 2022
fe0087a
requiremets update
Dec 8, 2022
a1711ad
ifish version
Jan 13, 2023
703613f
main bk
rd-mg Nov 22, 2023
5c63925
fix conflict due to update compatibility issues
rd-mg Nov 22, 2023
1c43c86
fix bbp iloc imp roc jinja2 downgraded
rd-mg Nov 23, 2023
fef2a60
fix roc coldtresh
rd-mg Nov 23, 2023
5f3b928
added ham stochhma avgrsi
rd-mg Feb 3, 2024
ef4caf1
pandas fixed
rd-mg Feb 3, 2024
fdbfe1b
fix operator
rd-mg Feb 3, 2024
43f84ec
fixed std crossed over indicator
rd-mg Feb 3, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Empty file modified .github/ISSUE_TEMPLATE/bug_report.md
100644 → 100755
Empty file.
Empty file modified .github/ISSUE_TEMPLATE/feature_request.md
100644 → 100755
Empty file.
Empty file modified .gitignore
100644 → 100755
Empty file.
5 changes: 4 additions & 1 deletion Dockerfile
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM python:latest
FROM python:3.9

# TA-lib is required by the python TA-lib wrapper. This provides analysis.
COPY lib/ta-lib-0.4.0-src.tar.gz /tmp/ta-lib-0.4.0-src.tar.gz
Expand All @@ -14,6 +14,9 @@ COPY ./app /app

WORKDIR /app

RUN apt update && apt upgrade -y
RUN apt install -y fail2ban

RUN pip install --upgrade pip
RUN pip install -r requirements-step-1.txt
RUN pip install -r requirements-step-2.txt
Expand Down
Empty file modified LICENSE
100644 → 100755
Empty file.
Empty file modified Makefile
100644 → 100755
Empty file.
23 changes: 17 additions & 6 deletions README.md
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ Development branch to testing new features. This develop version has a lot of im
## Notable Changes
- It creates candle bar charts with MAs, RSI and MACD. These images can be sent as part of a Telegram notification or a Webhook call.
- It allows to include prices as part of the notification message.
- New configuration to easily add many coins. Check bellow for "all_pairs".
- New configuration to easily add many coins. Check bellow for "all_pairs".
- New config var to use a custom "indicator_label" for each configured indicator and crossovers. Mainly useful for std_crossover.
- New indicator iiv (Increase In Volume) to try to identify a pump/dump.
- New indicator MA Ribbon
Expand All @@ -16,7 +16,14 @@ Development branch to testing new features. This develop version has a lot of im
- New indicator StochRSI Cross
- New indicator Sqzmon - Squeeze Momentum Indicator
- New option to customize ichimoku strategies and added chikou span

- Uptrend evaluation for a signal, it compares two signal candles to determine uptrend
- Changed Bollinger bands indicator type from informant to indicator to send message status to telegram
- Adde Bollinger bands width to Bollinger bands indicator
- New Indicator NATR
- New Indicator ROC
- New indicator IFish Stoch
- Added pandas-ta and dependencies in requirements
- New indicator IIP (price)

## Installing And Running
The commands listed below are intended to be run in a terminal.
Expand All @@ -25,13 +32,17 @@ Be sure you have git installed in your system.

1. Clone this repo `git clone https://github.com/w1ld3r/crypto-signal.git`

1. Enter to cripto-signal folder `cd crypto-signal`
2. Enter to cripto-signal folder `cd crypto-signal`

1. Switch to develop branch `git checkout develop`
3. Switch to develop branch `git checkout develop`

1. Create a config.yml file and put it into "app" folder.
4. Create a config.yml file and put it into "app" folder.

5. Build and run the docker container: `docker-compose up --build`

6. For testing and debugging run docker with "-t" option `docker run --rm -ti -v $PWD/app:/app crypto-signal_app:latest`

1. Build and run the docker container: `docker-compose up --build`
7. For production run in daemon mode using "-d" option `docker run --rm -di -v $PWD/app:/app crypto-signal_app:latest`


### Configuring config.yml
Expand Down
Empty file modified app/.gitignore
100644 → 100755
Empty file.
Empty file modified app/__init__.py
100644 → 100755
Empty file.
27 changes: 24 additions & 3 deletions app/analysis.py
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ def indicator_dispatcher(self):
'momentum': momentum.Momentum().analyze,
'mfi': mfi.MFI().analyze,
'stoch_rsi': stoch_rsi.StochasticRSI().analyze,
'stoch_hma_avg_rsi': stoch_hma_avg_rsi.StochHMAAVGRSI().analyze,
'stoch_hma': stoch_hma.StochHMA().analyze,
'obv': obv.OBV().analyze,
'iiv': iiv.IIV().analyze,
'ma_ribbon': ma_ribbon.MARibbon().analyze,
Expand All @@ -47,7 +49,13 @@ def indicator_dispatcher(self):
'bbp': bbp.BBP().analyze,
'macd_cross': macd_cross.MACDCross().analyze,
'stochrsi_cross': stochrsi_cross.StochRSICross().analyze,
'sqzmom': sqzmom.SQZMOM().analyze
'sqzmom': sqzmom.SQZMOM().analyze,
'natr': natr.NATR().analyze,
'bollinger_bands': bollinger_bands.Bollinger().analyze,
'roc': roc.ROC().analyze,
'ifish_stoch': ifish_stoch.IFISH_STOCH().analyze,
'iip': iip.IIP().analyze

}

return dispatcher
Expand All @@ -63,9 +71,9 @@ def informant_dispatcher(self):
'sma': sma.SMA().analyze,
'ema': ema.EMA().analyze,
'vwap': vwap.VWAP().analyze,
'bollinger_bands': bollinger_bands.Bollinger().analyze,
'ohlcv': ohlcv.OHLCV().analyze,
'lrsi': lrsi.LRSI().analyze
'lrsi': lrsi.LRSI().analyze,
'hma': hma.HMA().analyze,
}

return dispatcher
Expand All @@ -82,3 +90,16 @@ def crossover_dispatcher(self):
}

return dispatcher

def uptrend_dispatcher(self):
"""Returns a pandas.DataFrame for dynamic uptrend selector

Returns:
dictionary: A dictionary of functions to serve as a dynamic uptrend selector.
"""

dispatcher = {
'std_uptrend': uptrend.UpTrend().analyze
}

return dispatcher
2 changes: 1 addition & 1 deletion app/analyzers/__init__.py
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__all__ = ['crossover']
__all__ = ['crossover', 'uptrend']
30 changes: 16 additions & 14 deletions app/analyzers/crossover.py
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,30 +1,23 @@
""" Crossover analysis indicator
"""

import numpy
import pandas
from talib import abstract

import pandas as pd
from analyzers.utils import IndicatorUtils


class CrossOver(IndicatorUtils):
def analyze(self, key_indicator, key_signal, key_indicator_index,
crossed_indicator, crossed_signal, crossed_indicator_index):
""" Tests for key_indicator crossing over the crossed_indicator.

Args:
key_indicator (pandas.DataFrame): A dataframe containing the results of the analysis
key_indicator (pd.DataFrame): A dataframe containing the results of the analysis
for the selected key indicator.
key_signal (str): The name of the key indicator.
key_indicator_index (int): The configuration index of the key indicator to use.
crossed_indicator (pandas.DataFrame): A dataframe containing the results of the
crossed_indicator (pd.DataFrame): A dataframe containing the results of the
analysis for the selected indicator to test for a cross.
crossed_signal (str): The name of the indicator expecting to be crossed.
crossed_indicator_index (int): The configuration index of the crossed indicator to use.

Returns:
pandas.DataFrame: A dataframe containing the indicators and hot/cold values.
pd.DataFrame: A dataframe containing the indicators and hot/cold values.
"""

key_indicator_name = '{}_{}'.format(key_signal, key_indicator_index)
Expand All @@ -39,10 +32,19 @@ def analyze(self, key_indicator, key_signal, key_indicator_index,
column_indexed_name = '{}_{}'.format(column, crossed_indicator_index)
new_crossed_indicator.rename(columns={column: column_indexed_name}, inplace=True)

combined_data = pandas.concat([new_key_indicator, new_crossed_indicator], axis=1)
combined_data = pd.concat([new_key_indicator, new_crossed_indicator], axis=1)
combined_data.dropna(how='any', inplace=True)

combined_data['is_hot'] = combined_data[key_indicator_name] > combined_data[crossed_indicator_name]
combined_data['is_cold'] = combined_data[key_indicator_name] < combined_data[crossed_indicator_name]
# Check if the key indicator crossed above the crossed indicator
combined_data['is_hot'] = (
(combined_data[key_indicator_name].shift() < combined_data[crossed_indicator_name].shift()) &
(combined_data[key_indicator_name] > combined_data[crossed_indicator_name])
)

# Check if the key indicator crossed below the crossed indicator
combined_data['is_cold'] = (
(combined_data[key_indicator_name].shift() > combined_data[crossed_indicator_name].shift()) &
(combined_data[key_indicator_name] < combined_data[crossed_indicator_name])
)

return combined_data
9 changes: 8 additions & 1 deletion app/analyzers/indicators/__init__.py
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
'momentum',
'rsi',
'stoch_rsi',
'stoch_hma_avg_rsi',
'stoch_hma',
'mfi',
'obv',
'iiv',
Expand All @@ -17,5 +19,10 @@
'bbp',
'macd_cross',
'stochrsi_cross',
'sqzmom'
'sqzmom',
'natr',
'bollinger_bands',
'roc',
'ifish_stoch',
'iip'
]
Empty file modified app/analyzers/indicators/adx.py
100644 → 100755
Empty file.
Empty file modified app/analyzers/indicators/aroon_oscillator.py
100644 → 100755
Empty file.
11 changes: 6 additions & 5 deletions app/analyzers/indicators/bbp.py
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,14 @@

import pandas
from talib import BBANDS, abstract
import numpy as np

from analyzers.utils import IndicatorUtils


class BBP(IndicatorUtils):

def analyze(self, historical_data, signal=['bbp'], hot_thresh=0, cold_thresh=0.8, period_count=20, std_dev=2):
def analyze(self, historical_data, signal=['bbp'], hot_thresh=0.3, cold_thresh=0.8, period_count=20, std_dev=2):
"""Check when close price cross the Upper/Lower bands.

Args:
Expand Down Expand Up @@ -47,8 +48,8 @@ def analyze(self, historical_data, signal=['bbp'], hot_thresh=0, cold_thresh=0.8

bollinger['is_hot'] = False
bollinger['is_cold'] = False

bollinger['is_hot'] = bollinger['bbp'] <= hot_thresh
bollinger['is_cold'] = bollinger['bbp'] >= cold_thresh

bollinger['is_hot'].iloc[-1] = bollinger['bbp'].iloc[-2] <= hot_thresh and bollinger['bbp'].iloc[-2] < bollinger['bbp'].iloc[-1]
bollinger['is_cold'].iloc[-1] = bollinger['bbp'].iloc[-1] >= cold_thresh

return bollinger
return bollinger
Empty file modified app/analyzers/indicators/bollinger.py
100644 → 100755
Empty file.
16 changes: 10 additions & 6 deletions app/analyzers/informants/bollinger_bands.py → app/analyzers/indicators/bollinger_bands.py
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@


class Bollinger(IndicatorUtils):
def analyze(self, historical_data, period_count=21):
def analyze(self, historical_data, signal=['bbwidth'], hot_thresh=None, cold_thresh=None, period_count=21):
"""Performs a bollinger band analysis on the historical data

Args:
Expand All @@ -28,7 +28,8 @@ def analyze(self, historical_data, period_count=21):
bb_columns = {
'upperband': [numpy.nan] * dataframe.index.shape[0],
'middleband': [numpy.nan] * dataframe.index.shape[0],
'lowerband': [numpy.nan] * dataframe.index.shape[0]
'lowerband': [numpy.nan] * dataframe.index.shape[0],
'bbwidth': [numpy.nan] * dataframe.index.shape[0]
}

bb_values = pandas.DataFrame(
Expand All @@ -44,10 +45,13 @@ def analyze(self, historical_data, period_count=21):

for index in range(period_count, bb_df_size):
data_index = index - period_count
bb_values['lowerband'][index] = bb_data[0][data_index]
bb_values['middleband'][index] = bb_data[1][data_index]
bb_values['upperband'][index] = bb_data[2][data_index]

bb_values['lowerband'].iloc[index] = bb_data[0][data_index]
bb_values['middleband'].iloc[index] = bb_data[1][data_index]
bb_values['upperband'].iloc[index] = bb_data[2][data_index]
bb_values['bbwidth'].iloc[index] = (bb_data[2][data_index] - bb_data[0][data_index]) / bb_data[1][data_index]

bb_values['is_hot'] = True
bb_values['is_cold'] = False
bb_values.dropna(how='all', inplace=True)

return bb_values
Empty file modified app/analyzers/indicators/candle_recognition.py
100644 → 100755
Empty file.
Empty file modified app/analyzers/indicators/ichimoku.py
100644 → 100755
Empty file.
40 changes: 40 additions & 0 deletions app/analyzers/indicators/ifish_stoch.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@

"""
IFISH STOCHATIC RSI indicator
"""

import pandas as pd
import talib
import numpy as np
import pandas_ta as ta

from analyzers.utils import IndicatorUtils


class IFISH_STOCH(IndicatorUtils):
def analyze(self, historical_data, signal="ifish_stoch", hot_thresh=-0.9, cold_thresh=0.9, period_count=5):
"""
Calculates the Ifish Stoch indicator using the inverse of the Fisher transform
:param df: Dataframe with close prices
:param n: Period for Stochastic oscillator
:param m: Period for the momentum indicator
:param r: Harmonic ratio for the Fisher transform
:return: Dataframe with Ifish Stoch values
"""
# Calculate Stochastic oscillator
df = pd.DataFrame()
df = self.convert_to_dataframe(historical_data)
# Calcular la transformada de Fisher estocástica
df.ta.fisher(length= period_count, signal = 9, append= True)
print(df.tail())

# Calcular la inversa de la transformada de Fisher estocástica
df["ifish_stoch"] = np.log((1-df["FISHERT_5_9"])/df["FISHERT_5_9"])
print(df.tail())


df["is_hot"] = (df["ifish_stoch"] < hot_thresh) & (
df["ifish_stoch"] > df["ifish_stoch"].shift(1))
df["is_cold"] = (df["ifish_stoch"] > cold_thresh) | (
df["ifish_stoch"] < df["ifish_stoch"].shift(1))
return df
39 changes: 39 additions & 0 deletions app/analyzers/indicators/iip.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
""" Custom Indicator Increase In Volume
"""

import numpy as np
from scipy import stats
import pandas_ta as pta


from analyzers.utils import IndicatorUtils


class IIP(IndicatorUtils):
def analyze(self, historical_data, signal=['iip'], hot_thresh=2, cold_thresh=0, period_count=9):
"""Performs an analysis about the increase in price to detect pump dump on the historical data

Args:
historical_data (list): A matrix of historical OHCLV data.
signal (list, optional): Defaults to iip. The indicator line to check hot against.
hot_thresh (float, optional): Defaults to 10.
cold_thresh: below hot+thresh


Returns:
pandas.DataFrame: A dataframe containing the indicator and hot/cold values.
"""

dataframe = self.convert_to_dataframe(historical_data)

dataframe['candle_length'] = np.abs(dataframe['close']*100000 - dataframe['open']*100000)
dataframe.ta.zscore(close= dataframe['candle_length'], length=period_count, std=hot_thresh, append=True)
dataframe['iip'] = np.abs(dataframe[f"ZS_{period_count}"])
dataframe.dropna(how='all', inplace=True)

dataframe['is_hot'] = False
dataframe['is_cold'] = False
dataframe['is_hot'] = (dataframe["iip"] >= hot_thresh) & (dataframe['close'] > dataframe['open'])
dataframe['is_cold'] = (dataframe["iip"] >= hot_thresh) & (dataframe['close'] < dataframe['open'])

return dataframe
Empty file modified app/analyzers/indicators/iiv.py
100644 → 100755
Empty file.
Empty file modified app/analyzers/indicators/klinger_oscillator.py
100644 → 100755
Empty file.
Empty file modified app/analyzers/indicators/ma_crossover.py
100644 → 100755
Empty file.
Empty file modified app/analyzers/indicators/ma_ribbon.py
100644 → 100755
Empty file.
Empty file modified app/analyzers/indicators/macd.py
100644 → 100755
Empty file.
4 changes: 2 additions & 2 deletions app/analyzers/indicators/macd_cross.py
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ def analyze(self, historical_data, signal=['macd'], hot_thresh=None, cold_thresh
macd, macdsignal, macdhist = talib.MACD(
dataframe['close'], fastperiod=12, slowperiod=26, signalperiod=9)

macd_values = pandas.DataFrame([macd, macdsignal]).T.rename(
columns={0: "macd", 1: "signal"})
macd_values = pandas.DataFrame([macd, macdsignal, macdhist]).T.rename(
columns={0: "macd", 1: "signal", 2: "macdhist"})

macd_cross = pandas.concat([dataframe, macd_values], axis=1)
macd_cross.dropna(how='all', inplace=True)
Expand Down
Empty file modified app/analyzers/indicators/mfi.py
100644 → 100755
Empty file.
Empty file modified app/analyzers/indicators/momentum.py
100644 → 100755
Empty file.
32 changes: 32 additions & 0 deletions app/analyzers/indicators/natr.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
""" NATR Indicator
"""

import math

import pandas
from talib import abstract

from analyzers.utils import IndicatorUtils


class NATR(IndicatorUtils):
def analyze(self, historical_data, signal=['natr'], hot_thresh=None, cold_thresh=None, period_count=14):
"""Performs an NATR analysis on the historical data

Args:
historical_data (list): A matrix of historical OHCLV data.
period_count (int, optional): Defaults to 14. The number of data points to consider for
our exponential moving average.

Returns:
pandas.DataFrame: A dataframe containing the indicators and hot/cold values.
"""

dataframe = self.convert_to_dataframe(historical_data)
natr_values = abstract.NATR(dataframe, period_count).to_frame()
natr_values.dropna(how='all', inplace=True)
natr_values.rename(columns={0: 'natr'}, inplace=True)
natr_values['is_hot'] = True
natr_values['is_cold'] = False

return natr_values
Empty file modified app/analyzers/indicators/obv.py
100644 → 100755
Empty file.
Loading