├── user_data ├── strategies │ ├── nfi │ │ ├── .gitignore │ │ └── BB_RPB_TSL_RNG.py │ ├── flawless_victory_v1.py │ ├── ElliotV3.py │ ├── SMAOffsetProtectOptV1.py │ ├── SMAOffsetProtectOpt.py │ ├── Obelisk_3EMA_StochRSI_ATR.py │ ├── NostalgiaForInfinityV1.py │ ├── Elliot.py │ ├── Obelisk_Ichimoku_Slow_v1_3.py │ ├── NostalgiaForInfinityV2.py │ ├── Obelisk_Ichimoku_ZEMA_v1.py │ └── CombinedBinHClucAndMADV6.py ├── pairlist │ ├── blacklist-ftx.json │ ├── blacklist-binance.json │ ├── blacklist-kucoin.json │ ├── pairlist-volume-binance-usdt.json │ ├── pairlist-volume-kucoin-usdt.json │ ├── pairlist-volume-binance-busd.json │ ├── kucoin-usdt-static.json │ ├── Combined_NFIv6_SMA-static-pairlist.json │ ├── SMAOffsetProtectOpt-static-pairlist.json │ ├── ElliotV7-static-pairlist.json │ ├── BinClucMadSMADevelop-static-pairlist.json │ ├── ElliotV3-static-pairlist.json │ ├── binclucmaddevelop-static-pairlist.json │ ├── binance-usdt-static.json │ ├── Binance-USDT-All.json │ └── Binance-BTC-All.json ├── config-private.json.example ├── hyperopts │ ├── sample_hyperopt_loss.py │ ├── sample_hyperopt.py │ └── sample_hyperopt_advanced.py ├── config.json.example └── notebooks │ └── strategy_analysis_example.ipynb ├── .env.example ├── docker ├── Dockerfile.stable └── Dockerfile.custom ├── docker-compose.yml.example ├── README.md ├── .gitignore └── MULTIPLEBOT.md /user_data/strategies/nfi/.gitignore: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /.env.example: -------------------------------------------------------------------------------- 1 | STRATEGY=BinClucMadSMAv2 2 | PAIRLIST=binance-static-usdt 3 | EXCHANGE=binance 4 | PORT=8080 5 | CONTAINER_NAME=ftbot 6 | CURRENCY=usdt 7 | MODE=dry 8 | -------------------------------------------------------------------------------- /docker/Dockerfile.stable: -------------------------------------------------------------------------------- 1 | FROM freqtradeorg/freqtrade:stable_plot 2 | 3 | # Switch user to root if you must install something from apt 4 | # Don't forget to switch the user back below! 5 | # USER root 6 | RUN pip install --user ta --no-cache-dir 7 | RUN pip install --user finta --no-cache-dir 8 | RUN pip install --user pandas-ta --no-cache-dir 9 | 10 | # USER ftuser 11 | -------------------------------------------------------------------------------- /docker/Dockerfile.custom: -------------------------------------------------------------------------------- 1 | FROM freqtradeorg/freqtrade:develop_plot 2 | 3 | # Switch user to root if you must install something from apt 4 | # Don't forget to switch the user back below! 5 | # USER root 6 | 7 | RUN pip install --user ta --no-cache-dir 8 | RUN pip install --user finta --no-cache-dir 9 | RUN pip install --user pandas-ta --no-cache-dir 10 | 11 | # USER ftuser 12 | -------------------------------------------------------------------------------- /user_data/pairlist/blacklist-ftx.json: -------------------------------------------------------------------------------- 1 | { 2 | "exchange": { 3 | "pair_blacklist": [ 4 | // Exchange Tokens 5 | "FTT/.*", 6 | // Major Crypto 7 | "(BTC|ETH)/.*", 8 | // Leverage tokens 9 | ".*(BULL|BEAR|HALF|HEDGE|-PERP)/.*", 10 | "(BVOL|IBVOL)/.*", 11 | // Fiat 12 | "(AUD|EUR|GBP|CHF|CAD|JPY)/.*", 13 | // Stable tokens 14 | "(BUSD|USDT|TUSD|USDC|CUSDT)/.*", 15 | // FAN Tokens 16 | "(ACM|AFA|ALA|ALL|APL|ASR|ATM|BAR|CAI|CITY|FOR|GAL|GOZ|IBFK|JUV|LEG|LOCK-1|NAVI|NMR|NOV|OG|PFL|PSG|ROUSH|STV|TH|TRA|UCH|UFC|YBO)/.*", 17 | // Other Coins 18 | "(CHZ|CTXC|HBAR|NMR|SHIB|SLP|XVS)/.*" 19 | ] 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /user_data/pairlist/blacklist-binance.json: -------------------------------------------------------------------------------- 1 | { 2 | "exchange": { 3 | "pair_blacklist": [ 4 | // Exchange 5 | "(BNB)/.*", 6 | // Leverage 7 | ".*(_PREMIUM|BEAR|BULL|DOWN|HALF|HEDGE|UP|[1235][SL])/.*", 8 | // Fiat 9 | "(AUD|BRZ|CAD|CHF|EUR|GBP|HKD|IDRT|JPY|NGN|RUB|SGD|TRY|UAH|USD|ZAR)/.*", 10 | // Stable 11 | "(BUSD|CUSDT|DAI|PAXG|SUSD|TUSD|USDC|USDP|USDT|VAI)/.*", 12 | // FAN 13 | "(ACM|AFA|ALA|ALL|APL|ASR|ATM|BAR|CAI|CITY|FOR|GAL|GOZ|IBFK|JUV|LEG|LOCK-1|NAVI|NMR|NOV|OG|PFL|PSG|ROUSH|STV|TH|TRA|UCH|UFC|YBO)/.*", 14 | // Others 15 | "(CHZ|CTXC|HBAR|NMR|SHIB|SLP|XVS|ONG|ARDR)/.*", 16 | // My strategy blacklist 17 | "(ANKR|YGG|BAT|ENJ)/.*" 18 | 19 | ] 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /user_data/pairlist/blacklist-kucoin.json: -------------------------------------------------------------------------------- 1 | 2 | { 3 | "exchange": { 4 | "pair_blacklist": [ 5 | // Exchange Tokens 6 | "KCS/.*", 7 | // Leverage tokens 8 | ".*(3|3L|3S)/.*", 9 | // Fiat 10 | "(AUD|EUR|GBP|CHF|CAD|JPY)/.*", 11 | // Stable tokens 12 | "(BUSD|USDT|TUSD|USDC|CUSDT|DAI|USDN|CUSD)/.*", 13 | // FAN Tokens 14 | "(ACM|AFA|ALA|ALL|APL|ASR|ATM|BAR|CAI|CITY|FOR|GAL|GOZ|IBFK|JUV|LEG|LOCK-1|NAVI|NMR|NOV|OG|PFL|PSG|ROUSH|STV|TH|TRA|UCH|UFC|YBO)/.*", 15 | // Other Coins 16 | "(CHZ|SLP|XVS|MEM|AMPL|XYM|POLX|CARR|SKEY|MASK|KLV|TLOS)/.*", 17 | // kucoin for bcmsma strategy 18 | // "(JAR|XDB|YGG|ZORT|COMB|LTX|MASK|ONE|POL|CGG|MHC)/.*", 19 | // kucoin for nfiv7 strategies 20 | "(QRDO|VELO|SOUL|MLN|XAVA|CIX100|RFOX|YOP|SOLVE|KRL|SUN|LPT|TARA|CIRUS|NKN|AAVE|LAYER|GENS|STORJ|ANKR|IDEA)/.*", 21 | ] 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /user_data/pairlist/pairlist-volume-binance-usdt.json: -------------------------------------------------------------------------------- 1 | { 2 | "pairlists":[ 3 | { 4 | "method":"VolumePairList", 5 | "number_assets":80, 6 | "sort_key":"quoteVolume", 7 | "refresh_period":1800 8 | }, 9 | { 10 | "method":"AgeFilter", 11 | "min_days_listed":14 12 | }, 13 | { 14 | "method":"SpreadFilter", 15 | "max_spread_ratio":0.005 16 | }, 17 | { 18 | "method":"RangeStabilityFilter", 19 | "lookback_days":3, 20 | "min_rate_of_change":0.05, 21 | "refresh_period":1800 22 | }, 23 | { 24 | "method":"VolatilityFilter", 25 | "lookback_days":3, 26 | "min_volatility":0.02, 27 | "max_volatility":0.75, 28 | "refresh_period":43200 29 | }, 30 | { 31 | "method":"ShuffleFilter" 32 | } 33 | ] 34 | } 35 | -------------------------------------------------------------------------------- /user_data/pairlist/pairlist-volume-kucoin-usdt.json: -------------------------------------------------------------------------------- 1 | { 2 | "pairlists":[ 3 | { 4 | "method":"VolumePairList", 5 | "number_assets":75, 6 | "sort_key":"quoteVolume", 7 | "refresh_period":1800 8 | }, 9 | { 10 | "method":"AgeFilter", 11 | "min_days_listed":14 12 | }, 13 | { 14 | "method":"SpreadFilter", 15 | "max_spread_ratio":0.006 16 | }, 17 | { 18 | "method":"RangeStabilityFilter", 19 | "lookback_days":3, 20 | "min_rate_of_change":0.05, 21 | "refresh_period":1800 22 | }, 23 | { 24 | "method":"VolatilityFilter", 25 | "lookback_days":3, 26 | "min_volatility":0.02, 27 | "max_volatility":0.75, 28 | "refresh_period":43200 29 | }, 30 | { 31 | "method":"ShuffleFilter" 32 | } 33 | ] 34 | } 35 | -------------------------------------------------------------------------------- /user_data/pairlist/pairlist-volume-binance-busd.json: -------------------------------------------------------------------------------- 1 | { 2 | "pairlists":[ 3 | { 4 | "method":"VolumePairList", 5 | "number_assets":80, 6 | "sort_key":"quoteVolume", 7 | "refresh_period":1800 8 | }, 9 | { 10 | "method":"AgeFilter", 11 | "min_days_listed":14 12 | }, 13 | { 14 | "method":"SpreadFilter", 15 | "max_spread_ratio":0.005 16 | }, 17 | { 18 | "method":"RangeStabilityFilter", 19 | "lookback_days":3, 20 | "min_rate_of_change":0.05, 21 | "refresh_period":1800 22 | }, 23 | { 24 | "method":"VolatilityFilter", 25 | "lookback_days":3, 26 | "min_volatility":0.02, 27 | "max_volatility":0.75, 28 | "refresh_period":43200 29 | }, 30 | 31 | { 32 | "method":"ShuffleFilter" 33 | } 34 | ] 35 | } 36 | -------------------------------------------------------------------------------- /docker-compose.yml.example: -------------------------------------------------------------------------------- 1 | --- 2 | version: '3' 3 | services: 4 | freqtrade: 5 | image: minulislam/freqtrade:develop 6 | # image: freqtradeorg/freqtrade:develop 7 | build: 8 | context: . 9 | dockerfile: "./docker/Dockerfile.custom" 10 | restart: unless-stopped 11 | container_name: ${CONTAINER_NAME:-ftbot}-${STRATEGY:-BinClucMadSMADevelop} 12 | volumes: 13 | - "./user_data:/freqtrade/user_data" 14 | # Expose api on port 8080 (localhost only) 15 | # Please read the https://www.freqtrade.io/en/latest/rest-api/ documentation 16 | # before enabling this. 17 | ports: 18 | - "0.0.0.0:${PORT:-8080}:${PORT:-8080}" 19 | # Default command used when running `docker compose up` 20 | command: > 21 | trade 22 | --logfile /freqtrade/user_data/logs/freqtrade.log 23 | --db-url sqlite:////freqtrade/user_data/${STRATEGY:-BinClucMadSMADevelop}.${MODE:-live}.sqlite 24 | --config /freqtrade/user_data/config.json 25 | --config /freqtrade/user_data/config-private.json 26 | --config /freqtrade/user_data/pairlist/${PAIRLIST:-binance-usdt-static}.json 27 | --strategy ${STRATEGY:-BinClucMadSMADevelop} 28 | -------------------------------------------------------------------------------- /user_data/config-private.json.example: -------------------------------------------------------------------------------- 1 | { 2 | "bot_name": "Freqtrade - TradingBot", 3 | "fiat_display_currency": "USD", 4 | "exchange": { 5 | "name": "binance", 6 | "key": "", 7 | "secret": "" 8 | }, 9 | "telegram": { 10 | "enabled": false, 11 | "token": "", 12 | "chat_id": "" 13 | }, 14 | 15 | 16 | "edge": { 17 | "enabled": false, 18 | "process_throttle_secs": 3600, 19 | "calculate_since_number_of_days": 7, 20 | "allowed_risk": 0.01, 21 | "stoploss_range_min": -0.01, 22 | "stoploss_range_max": -0.1, 23 | "stoploss_range_step": -0.01, 24 | "minimum_winrate": 0.60, 25 | "minimum_expectancy": 0.20, 26 | "min_trade_number": 10, 27 | "max_trade_duration_minute": 1440, 28 | "remove_pumps": false 29 | }, 30 | "api_server": { 31 | "enabled": true, 32 | "listen_ip_address": "0.0.0.0", 33 | "listen_port": 8080, 34 | "verbosity": "error", 35 | "enable_openapi": false, 36 | "jwt_secret_key": "689d6177cb2e4911095db656dbede7197ec2346dcbdc0016cb0b790f1436cd08", 37 | "CORS_origins": [], 38 | "username": "freqtrader", 39 | "password": "freqtrader" 40 | }, 41 | } 42 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Must change .env values for port strategy 2 | container name and pairlist 3 | All configured by default just change the value 4 | 5 | NOTE: for updating config.json better always use config-private.json file 6 | 7 | clone the repo 8 | 9 | ```bash 10 | git clone https://github.com/minulislam/freqtrade-strategies.git 11 | 12 | 13 | ```bash 14 | 15 | cp user_data/config.json.example user_data/config.json 16 | cp user_data/config-private.json.example user_data/config-private.json 17 | cp docker-compose.yml.example docker-compose.yml 18 | cp .env.example .env 19 | 20 | ``` 21 | update .env with your chosen strategy 22 | update config-private.json for your exchange key secret and telegram 23 | 24 | ```bash 25 | docker-compose run --rm freqtrade create-userdir --userdir user_data 26 | 27 | ``` 28 | 29 | config-private.json format 30 | ```json 31 | { 32 | "bot_name": "Freqtrade - TradingBot", 33 | "fiat_display_currency": "USD", 34 | "exchange": { 35 | "name": "binance", 36 | "key": "", 37 | "secret": "" 38 | }, 39 | "telegram": { 40 | "enabled": false, 41 | "token": "", 42 | "chat_id": "" 43 | }, 44 | "api_server": { 45 | "enabled": true, 46 | "listen_ip_address": "0.0.0.0", 47 | "listen_port": 8070, 48 | "verbosity": "info", 49 | "jwt_secret_key": "", 50 | "CORS_origins": [], 51 | "username": "freqtrader", 52 | "password": "freqtrader" 53 | } 54 | } 55 | 56 | ''' 57 | -------------------------------------------------------------------------------- /user_data/hyperopts/sample_hyperopt_loss.py: -------------------------------------------------------------------------------- 1 | from datetime import datetime 2 | from math import exp 3 | from typing import Dict 4 | 5 | from pandas import DataFrame 6 | 7 | from freqtrade.optimize.hyperopt import IHyperOptLoss 8 | 9 | 10 | # Define some constants: 11 | 12 | # set TARGET_TRADES to suit your number concurrent trades so its realistic 13 | # to the number of days 14 | TARGET_TRADES = 600 15 | # This is assumed to be expected avg profit * expected trade count. 16 | # For example, for 0.35% avg per trade (or 0.0035 as ratio) and 1100 trades, 17 | # self.expected_max_profit = 3.85 18 | # Check that the reported Σ% values do not exceed this! 19 | # Note, this is ratio. 3.85 stated above means 385Σ%. 20 | EXPECTED_MAX_PROFIT = 3.0 21 | 22 | # max average trade duration in minutes 23 | # if eval ends with higher value, we consider it a failed eval 24 | MAX_ACCEPTED_TRADE_DURATION = 300 25 | 26 | 27 | class SampleHyperOptLoss(IHyperOptLoss): 28 | """ 29 | Defines the default loss function for hyperopt 30 | This is intended to give you some inspiration for your own loss function. 31 | 32 | The Function needs to return a number (float) - which becomes smaller for better backtest 33 | results. 34 | """ 35 | 36 | @staticmethod 37 | def hyperopt_loss_function(results: DataFrame, trade_count: int, 38 | min_date: datetime, max_date: datetime, 39 | config: Dict, processed: Dict[str, DataFrame], 40 | *args, **kwargs) -> float: 41 | """ 42 | Objective function, returns smaller number for better results 43 | """ 44 | total_profit = results['profit_ratio'].sum() 45 | trade_duration = results['trade_duration'].mean() 46 | 47 | trade_loss = 1 - 0.25 * exp(-(trade_count - TARGET_TRADES) ** 2 / 10 ** 5.8) 48 | profit_loss = max(0, 1 - total_profit / EXPECTED_MAX_PROFIT) 49 | duration_loss = 0.4 * min(trade_duration / MAX_ACCEPTED_TRADE_DURATION, 1) 50 | result = trade_loss + profit_loss + duration_loss 51 | return result 52 | -------------------------------------------------------------------------------- /user_data/pairlist/kucoin-usdt-static.json: -------------------------------------------------------------------------------- 1 | { 2 | "exchange": { 3 | "name": "kucoin", 4 | "pair_whitelist": [ 5 | "BTC/USDT", 6 | "ETH/USDT", 7 | "LUNA/USDT", 8 | "XRP/USDT", 9 | "ADA/USDT", 10 | "DOT/USDT", 11 | "TEL/USDT", 12 | "KCS/USDT", 13 | "VET/USDT", 14 | "DOGE/USDT", 15 | "DAG/USDT", 16 | "LTC/USDT", 17 | "LINK/USDT", 18 | "VRA/USDT", 19 | "BEPRO/USDT", 20 | "XLM/USDT", 21 | "ENJ/USDT", 22 | "THETA/USDT", 23 | "HTR/USDT", 24 | "AAVE/USDT", 25 | "EOS/USDT", 26 | "CHR/USDT", 27 | "TRX/USDT", 28 | "ATOM/USDT", 29 | "BCH/USDT", 30 | "FTM/USDT", 31 | "GRT/USDT", 32 | "SUSHI/USDT", 33 | "DASH/USDT", 34 | "BSV/USDT", 35 | "KSM/USDT", 36 | "UNI/USDT", 37 | "BTC3L/USDT", 38 | "VELO/USDT", 39 | "SHA/USDT", 40 | "SAND/USDT", 41 | "BTT/USDT", 42 | "ALGO/USDT", 43 | "ZEC/USDT", 44 | "TRIAS/USDT", 45 | "ETH3L/USDT", 46 | "SXP/USDT", 47 | "XMR/USDT", 48 | "COTI/USDT", 49 | "SNX/USDT", 50 | "BTC3S/USDT", 51 | "NANO/USDT", 52 | "AMPL/USDT", 53 | "COMP/USDT", 54 | "LTX/USDT", 55 | "XTZ/USDT", 56 | "ORN/USDT", 57 | "ZIL/USDT", 58 | "ONE/USDT", 59 | "ETC/USDT", 60 | "MANA/USDT", 61 | "MIR/USDT", 62 | "DEGO/USDT", 63 | "API3/USDT", 64 | "IDEA/USDT", 65 | "CAKE/USDT", 66 | "KLV/USDT", 67 | "POL/USDT", 68 | "1INCH/USDT", 69 | "WAXP/USDT", 70 | "SKEY/USDT", 71 | "ARPA/USDT", 72 | "PDEX/USDT", 73 | "FRM/USDT", 74 | "AVAX/USDT", 75 | "CRV/USDT", 76 | "SHR/USDT", 77 | "FIL/USDT", 78 | "BOSON/USDT", 79 | "BOA/USDT", 80 | "ANKR/USDT", 81 | "NEO/USDT", 82 | "TOKO/USDT", 83 | "EWT/USDT", 84 | "ROSE/USDT", 85 | "DODO/USDT", 86 | "CHZ/USDT", 87 | "RLY/USDT", 88 | "XEM/USDT", 89 | "SYLO/USDT", 90 | "WIN/USDT", 91 | "HYDRA/USDT", 92 | "MKR/USDT" 93 | ] 94 | 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .env 2 | *.env 3 | user_data/data/* 4 | user_data/*.sqlite 5 | user_data/config*.json 6 | user_data/hyperopt.lock 7 | user_data/notebooks/.ipynb_checkpoints 8 | user_data/strategies/.ipynb_checkpoints 9 | docker-compose.yml 10 | 11 | # Don't commit candle data 12 | user_data/data/*.json 13 | user_data/data/*/*.json 14 | user_data/backtest_results/* 15 | user_data/hyperopt_results/* 16 | user_data/logs/* 17 | user_data/plot/* 18 | # Byte-compiled / optimized / DLL files 19 | __pycache__/ 20 | *.py[cod] 21 | *$py.class 22 | 23 | # C extensions 24 | *.so 25 | 26 | # Distribution / packaging 27 | .Python 28 | build/ 29 | develop-eggs/ 30 | dist/ 31 | downloads/ 32 | eggs/ 33 | .eggs/ 34 | lib/ 35 | lib64/ 36 | parts/ 37 | sdist/ 38 | var/ 39 | wheels/ 40 | pip-wheel-metadata/ 41 | share/python-wheels/ 42 | *.egg-info/ 43 | .installed.cfg 44 | *.egg 45 | MANIFEST 46 | 47 | # PyInstaller 48 | # Usually these files are written by a python script from a template 49 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 50 | *.manifest 51 | *.spec 52 | 53 | # Installer logs 54 | pip-log.txt 55 | pip-delete-this-directory.txt 56 | 57 | # Unit test / coverage reports 58 | htmlcov/ 59 | .tox/ 60 | .nox/ 61 | .coverage 62 | .coverage.* 63 | .cache 64 | nosetests.xml 65 | coverage.xml 66 | *.cover 67 | *.py,cover 68 | .hypothesis/ 69 | .pytest_cache/ 70 | 71 | # Translations 72 | *.mo 73 | *.pot 74 | 75 | # Django stuff: 76 | *.log 77 | local_settings.py 78 | db.sqlite3 79 | db.sqlite3-journal 80 | 81 | # Flask stuff: 82 | instance/ 83 | .webassets-cache 84 | 85 | # Scrapy stuff: 86 | .scrapy 87 | 88 | # Sphinx documentation 89 | docs/_build/ 90 | 91 | # PyBuilder 92 | target/ 93 | 94 | # Jupyter Notebook 95 | .ipynb_checkpoints 96 | 97 | # IPython 98 | profile_default/ 99 | ipython_config.py 100 | 101 | # pyenv 102 | .python-version 103 | 104 | # pipenv 105 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 106 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 107 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 108 | # install all needed dependencies. 109 | #Pipfile.lock 110 | 111 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 112 | __pypackages__/ 113 | 114 | # Celery stuff 115 | celerybeat-schedule 116 | celerybeat.pid 117 | 118 | # SageMath parsed files 119 | *.sage.py 120 | 121 | # Environments 122 | .env 123 | .venv 124 | env/ 125 | venv/ 126 | ENV/ 127 | env.bak/ 128 | venv.bak/ 129 | 130 | # Spyder project settings 131 | .spyderproject 132 | .spyproject 133 | 134 | # Rope project settings 135 | .ropeproject 136 | 137 | # mkdocs documentation 138 | /site 139 | 140 | # mypy 141 | .mypy_cache/ 142 | .dmypy.json 143 | dmypy.json 144 | 145 | # Pyre type checker 146 | .pyre/ 147 | 148 | 149 | # IntelliJ 150 | .idea 151 | -------------------------------------------------------------------------------- /user_data/pairlist/Combined_NFIv6_SMA-static-pairlist.json: -------------------------------------------------------------------------------- 1 | { 2 | "exchange": 3 | { 4 | "name": "binance", 5 | "pair_whitelist": 6 | [ 7 | "AAVE/USDT", 8 | "ACM/USDT", 9 | "ADA/USDT", 10 | "ALICE/USDT", 11 | "ALPHA/USDT", 12 | "ANKR/USDT", 13 | "AR/USDT", 14 | "ASR/USDT", 15 | "ATM/USDT", 16 | "ATOM/USDT", 17 | "AUDIO/USDT", 18 | "AXS/USDT", 19 | "BAKE/USDT", 20 | "BCH/USDT", 21 | "BTC/USDT", 22 | "BTG/USDT", 23 | "BURGER/USDT", 24 | "CAKE/USDT", 25 | "CELO/USDT", 26 | "CELR/USDT", 27 | "CHR/USDT", 28 | "CHZ/USDT", 29 | "COCOS/USDT", 30 | "CRV/USDT", 31 | "CTSI/USDT", 32 | "DASH/USDT", 33 | "DATA/USDT", 34 | "DEGO/USDT", 35 | "DENT/USDT", 36 | "DOCK/USDT", 37 | "DODO/USDT", 38 | "DOGE/USDT", 39 | "DOT/USDT", 40 | "EGLD/USDT", 41 | "ENJ/USDT", 42 | "EOS/USDT", 43 | "ETC/USDT", 44 | "ETH/USDT", 45 | "FIL/USDT", 46 | "GRT/USDT", 47 | "GTO/USDT", 48 | "GXS/USDT", 49 | "HARD/USDT", 50 | "HBAR/USDT", 51 | "HNT/USDT", 52 | "HOT/USDT", 53 | "IOST/USDT", 54 | "IOTX/USDT", 55 | "JUV/USDT", 56 | "KSM/USDT", 57 | "LINK/USDT", 58 | "LTC/USDT", 59 | "LUNA/USDT", 60 | "MATIC/USDT", 61 | "MKR/USDT", 62 | "MTL/USDT", 63 | "NEAR/USDT", 64 | "NEO/USDT", 65 | "NMR/USDT", 66 | "OGN/USDT", 67 | "OM/USDT", 68 | "OMG/USDT", 69 | "ONT/USDT", 70 | "PERL/USDT", 71 | "PNT/USDT", 72 | "POLS/USDT", 73 | "POND/USDT", 74 | "PSG/USDT", 75 | "QTUM/USDT", 76 | "RLC/USDT", 77 | "RUNE/USDT", 78 | "RVN/USDT", 79 | "SKL/USDT", 80 | "SLP/USDT", 81 | "SNX/USDT", 82 | "SOL/USDT", 83 | "STMX/USDT", 84 | "STPT/USDT", 85 | "STRAX/USDT", 86 | "SXP/USDT", 87 | "TFUEL/USDT", 88 | "TKO/USDT", 89 | "TLM/USDT", 90 | "TRU/USDT", 91 | "TRX/USDT", 92 | "TWT/USDT", 93 | "UNI/USDT", 94 | "WAVES/USDT", 95 | "WIN/USDT", 96 | "WRX/USDT", 97 | "XEM/USDT", 98 | "XLM/USDT", 99 | "XMR/USDT", 100 | "XRP/USDT", 101 | "XTZ/USDT", 102 | "YFI/USDT", 103 | "ZEC/USDT", 104 | "ZEN/USDT", 105 | "ZIL/USDT", 106 | "ZRX/USDT" 107 | ] 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /user_data/config.json.example: -------------------------------------------------------------------------------- 1 | { 2 | "dry_run": true, 3 | "forcebuy_enable": false, 4 | "max_open_trades": 5, 5 | "stake_currency": "USDT", 6 | "stake_amount": "unlimited", 7 | // "available_capital": 1000, 8 | "tradable_balance_ratio": 0.99, 9 | "fiat_display_currency": "USD", 10 | "timeframe": "5m", 11 | "cancel_open_orders_on_exit": false, 12 | "unfilledtimeout": { 13 | "buy": 10, 14 | "sell": 30, 15 | "unit": "minutes" 16 | }, 17 | "bid_strategy": { 18 | "price_side": "ask", 19 | "ask_last_balance": 0.0, 20 | "use_order_book": false, 21 | "order_book_top": 1, 22 | "check_depth_of_market": { 23 | "enabled": false, 24 | "bids_to_ask_delta": 1 25 | } 26 | }, 27 | "ask_strategy": { 28 | "price_side": "bid", 29 | "use_order_book": false, 30 | "order_book_top": 1 31 | }, 32 | 33 | "order_types": { 34 | "buy": "market", 35 | "sell": "market", 36 | "forcesell": "market", 37 | "emergencysell": "market", 38 | "stoploss": "market", 39 | "stoploss_on_exchange": false, 40 | "stoploss_on_exchange_interval": 60 41 | }, 42 | 43 | 44 | "exchange": { 45 | "name": "binance", 46 | "key": "", 47 | "secret": "", 48 | "ccxt_config": {}, 49 | "ccxt_async_config": {}, 50 | "pair_whitelist": [ 51 | ], 52 | "pair_blacklist": [ 53 | "BNB/.*", 54 | ".*(AUD|BRZ|CAD|CHF|DAI|EUR|GBP|HKD|IDRT|JPY|NGN|PAX|PAXG|RUB|SGD|SUSD|TRY|TUSD|UAH|USD|USDC|VAI|ZAR)/.*", 55 | ".*(_PREMIUM|BEAR|BULL|DOWN|HALF|HEDGE|UP|[1235][SL]).*/.*", 56 | 57 | ] 58 | }, 59 | 60 | "_pairlists": [ 61 | {"method": "StaticPairList"} 62 | ], 63 | "pairlists": [ 64 | { 65 | "method": "VolumePairList", 66 | "number_assets": 80, 67 | "sort_key": "quoteVolume", 68 | "refresh_period": 1800 69 | }, 70 | {"method": "AgeFilter", "min_days_listed": 3}, 71 | {"method": "SpreadFilter", "max_spread_ratio": 0.005}, 72 | {"method": "PriceFilter", "min_price": 0.0001}, 73 | { 74 | "method": "RangeStabilityFilter", 75 | "lookback_days": 3, 76 | "min_rate_of_change": 0.05, 77 | "refresh_period": 1440 78 | }, 79 | { 80 | "method": "VolatilityFilter", 81 | "lookback_days": 3, 82 | "min_volatility": 0.01, 83 | "max_volatility": 0.75, 84 | "refresh_period": 43400 85 | }, 86 | { 87 | "method": "PerformanceFilter", 88 | "minutes": 1440, 89 | "min_profit": 0.01 90 | } 91 | 92 | 93 | ], 94 | 95 | "initial_state": "running", 96 | "internals": { 97 | "process_throttle_secs": 5, 98 | 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /user_data/pairlist/SMAOffsetProtectOpt-static-pairlist.json: -------------------------------------------------------------------------------- 1 | { 2 | "exchange": 3 | { 4 | "name": "binance", 5 | "pair_whitelist": 6 | [ 7 | "AAVE/USDT", 8 | "ACM/USDT", 9 | "AION/USDT", 10 | "ALGO/USDT", 11 | "ALICE/USDT", 12 | "ANKR/USDT", 13 | "AR/USDT", 14 | "ATM/USDT", 15 | "ATOM/USDT", 16 | "AUDIO/USDT", 17 | "AVAX/USDT", 18 | "AXS/USDT", 19 | "BAKE/USDT", 20 | "BAT/USDT", 21 | "BCH/USDT", 22 | "BTC/USDT", 23 | "BTCST/USDT", 24 | "BTG/USDT", 25 | "BTT/USDT", 26 | "BURGER/USDT", 27 | "CAKE/USDT", 28 | "CELO/USDT", 29 | "CELR/USDT", 30 | "CHR/USDT", 31 | "CKB/USDT", 32 | "COCOS/USDT", 33 | "COMP/USDT", 34 | "CRV/USDT", 35 | "DASH/USDT", 36 | "DATA/USDT", 37 | "DEGO/USDT", 38 | "DENT/USDT", 39 | "DGB/USDT", 40 | "DNT/USDT", 41 | "DOCK/USDT", 42 | "DODO/USDT", 43 | "DOT/USDT", 44 | "EGLD/USDT", 45 | "EOS/USDT", 46 | "ETH/USDT", 47 | "FIL/USDT", 48 | "FTM/USDT", 49 | "GRT/USDT", 50 | "GTO/USDT", 51 | "HARD/USDT", 52 | "HBAR/USDT", 53 | "HNT/USDT", 54 | "HOT/USDT", 55 | "IOST/USDT", 56 | "IOTA/USDT", 57 | "JUV/USDT", 58 | "KAVA/USDT", 59 | "KSM/USDT", 60 | "LPT/USDT", 61 | "LTC/USDT", 62 | "LUNA/USDT", 63 | "MASK/USDT", 64 | "MATIC/USDT", 65 | "MITH/USDT", 66 | "NEAR/USDT", 67 | "NEO/USDT", 68 | "NKN/USDT", 69 | "NMR/USDT", 70 | "OGN/USDT", 71 | "OM/USDT", 72 | "OMG/USDT", 73 | "ONT/USDT", 74 | "OXT/USDT", 75 | "PERL/USDT", 76 | "PNT/USDT", 77 | "POLS/USDT", 78 | "POND/USDT", 79 | "QTUM/USDT", 80 | "RLC/USDT", 81 | "RUNE/USDT", 82 | "RVN/USDT", 83 | "SC/USDT", 84 | "SKL/USDT", 85 | "SLP/USDT", 86 | "SOL/USDT", 87 | "STPT/USDT", 88 | "STX/USDT", 89 | "SUSHI/USDT", 90 | "SXP/USDT", 91 | "TFUEL/USDT", 92 | "THETA/USDT", 93 | "TKO/USDT", 94 | "TLM/USDT", 95 | "TRU/USDT", 96 | "TRX/USDT", 97 | "TWT/USDT", 98 | "UNI/USDT", 99 | "VET/USDT", 100 | "WAVES/USDT", 101 | "WRX/USDT", 102 | "XEM/USDT", 103 | "XLM/USDT", 104 | "XRP/USDT", 105 | "XTZ/USDT", 106 | "YFI/USDT", 107 | "ZEC/USDT", 108 | "ZEN/USDT", 109 | "ZIL/USDT", 110 | "ZRX/USDT" 111 | ] 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /user_data/pairlist/ElliotV7-static-pairlist.json: -------------------------------------------------------------------------------- 1 | { 2 | "exchange": 3 | { 4 | "name": "binance", 5 | "pair_whitelist": 6 | [ 7 | "AAVE/USDT", 8 | "ACM/USDT", 9 | "ADA/USDT", 10 | "ALGO/USDT", 11 | "ALICE/USDT", 12 | "AR/USDT", 13 | "ASR/USDT", 14 | "ATM/USDT", 15 | "ATOM/USDT", 16 | "AUDIO/USDT", 17 | "AVA/USDT", 18 | "AXS/USDT", 19 | "BAKE/USDT", 20 | "BAT/USDT", 21 | "BCH/USDT", 22 | "BTCST/USDT", 23 | "BTG/USDT", 24 | "BURGER/USDT", 25 | "CAKE/USDT", 26 | "CELO/USDT", 27 | "CELR/USDT", 28 | "CHR/USDT", 29 | "CHZ/USDT", 30 | "CKB/USDT", 31 | "COCOS/USDT", 32 | "COMP/USDT", 33 | "CRV/USDT", 34 | "CTSI/USDT", 35 | "DATA/USDT", 36 | "DEGO/USDT", 37 | "DENT/USDT", 38 | "DGB/USDT", 39 | "DNT/USDT", 40 | "DOCK/USDT", 41 | "DODO/USDT", 42 | "DOGE/USDT", 43 | "EGLD/USDT", 44 | "ENJ/USDT", 45 | "EOS/USDT", 46 | "ETC/USDT", 47 | "ETH/USDT", 48 | "FIL/USDT", 49 | "GTO/USDT", 50 | "GXS/USDT", 51 | "HARD/USDT", 52 | "HBAR/USDT", 53 | "HNT/USDT", 54 | "HOT/USDT", 55 | "IOST/USDT", 56 | "IOTA/USDT", 57 | "KAVA/USDT", 58 | "KSM/USDT", 59 | "LPT/USDT", 60 | "LTC/USDT", 61 | "LUNA/USDT", 62 | "MANA/USDT", 63 | "MASK/USDT", 64 | "MATIC/USDT", 65 | "MITH/USDT", 66 | "MTL/USDT", 67 | "NEO/USDT", 68 | "NKN/USDT", 69 | "NMR/USDT", 70 | "OGN/USDT", 71 | "OM/USDT", 72 | "OMG/USDT", 73 | "ONE/USDT", 74 | "ONG/USDT", 75 | "ONT/USDT", 76 | "PERL/USDT", 77 | "PNT/USDT", 78 | "POND/USDT", 79 | "PSG/USDT", 80 | "REEF/USDT", 81 | "RLC/USDT", 82 | "RUNE/USDT", 83 | "RVN/USDT", 84 | "SAND/USDT", 85 | "SC/USDT", 86 | "SKL/USDT", 87 | "SLP/USDT", 88 | "SNX/USDT", 89 | "SOL/USDT", 90 | "STRAX/USDT", 91 | "STX/USDT", 92 | "TFUEL/USDT", 93 | "THETA/USDT", 94 | "TKO/USDT", 95 | "TLM/USDT", 96 | "TRU/USDT", 97 | "TRX/USDT", 98 | "TWT/USDT", 99 | "UNI/USDT", 100 | "VET/USDT", 101 | "WAVES/USDT", 102 | "WIN/USDT", 103 | "WING/USDT", 104 | "WRX/USDT", 105 | "XEM/USDT", 106 | "XLM/USDT", 107 | "XRP/USDT", 108 | "XTZ/USDT", 109 | "YFI/USDT", 110 | "ZEC/USDT", 111 | "ZEN/USDT", 112 | "ZRX/USDT" 113 | ] 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /user_data/pairlist/BinClucMadSMADevelop-static-pairlist.json: -------------------------------------------------------------------------------- 1 | { 2 | "exchange": 3 | { 4 | "name": "binance", 5 | "pair_whitelist": 6 | [ 7 | "AAVE/USDT", 8 | "ACM/USDT", 9 | "AION/USDT", 10 | "ALGO/USDT", 11 | "ALICE/USDT", 12 | "ALPHA/USDT", 13 | "AR/USDT", 14 | "ASR/USDT", 15 | "ATM/USDT", 16 | "ATOM/USDT", 17 | "AUDIO/USDT", 18 | "AVA/USDT", 19 | "AVAX/USDT", 20 | "AXS/USDT", 21 | "BAKE/USDT", 22 | "BAT/USDT", 23 | "BCH/USDT", 24 | "BTC/USDT", 25 | "BTCST/USDT", 26 | "BTG/USDT", 27 | "BTT/USDT", 28 | "BURGER/USDT", 29 | "CELO/USDT", 30 | "CELR/USDT", 31 | "CHR/USDT", 32 | "CHZ/USDT", 33 | "CKB/USDT", 34 | "COCOS/USDT", 35 | "COMP/USDT", 36 | "CRV/USDT", 37 | "CTSI/USDT", 38 | "DATA/USDT", 39 | "DEGO/USDT", 40 | "DGB/USDT", 41 | "DNT/USDT", 42 | "DOCK/USDT", 43 | "DODO/USDT", 44 | "DOGE/USDT", 45 | "DOT/USDT", 46 | "EGLD/USDT", 47 | "ENJ/USDT", 48 | "EOS/USDT", 49 | "ETH/USDT", 50 | "FIL/USDT", 51 | "FTM/USDT", 52 | "GTO/USDT", 53 | "GXS/USDT", 54 | "HARD/USDT", 55 | "HNT/USDT", 56 | "HOT/USDT", 57 | "IOST/USDT", 58 | "IOTA/USDT", 59 | "JUV/USDT", 60 | "KAVA/USDT", 61 | "KSM/USDT", 62 | "LINK/USDT", 63 | "LPT/USDT", 64 | "LTC/USDT", 65 | "LUNA/USDT", 66 | "MANA/USDT", 67 | "MASK/USDT", 68 | "MATIC/USDT", 69 | "MBL/USDT", 70 | "MITH/USDT", 71 | "MKR/USDT", 72 | "MTL/USDT", 73 | "NEO/USDT", 74 | "NMR/USDT", 75 | "OGN/USDT", 76 | "OM/USDT", 77 | "OMG/USDT", 78 | "ONG/USDT", 79 | "ONT/USDT", 80 | "OXT/USDT", 81 | "PERL/USDT", 82 | "PNT/USDT", 83 | "POND/USDT", 84 | "RUNE/USDT", 85 | "RVN/USDT", 86 | "SAND/USDT", 87 | "SKL/USDT", 88 | "SLP/USDT", 89 | "SOL/USDT", 90 | "STMX/USDT", 91 | "STPT/USDT", 92 | "SUSHI/USDT", 93 | "SXP/USDT", 94 | "TFUEL/USDT", 95 | "THETA/USDT", 96 | "TKO/USDT", 97 | "TLM/USDT", 98 | "TRU/USDT", 99 | "TRX/USDT", 100 | "VET/USDT", 101 | "WAVES/USDT", 102 | "WIN/USDT", 103 | "WING/USDT", 104 | "WRX/USDT", 105 | "XEM/USDT", 106 | "XLM/USDT", 107 | "XMR/USDT", 108 | "XRP/USDT", 109 | "XTZ/USDT", 110 | "YFI/USDT", 111 | "ZEN/USDT", 112 | "ZIL/USDT" 113 | ] 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /user_data/pairlist/ElliotV3-static-pairlist.json: -------------------------------------------------------------------------------- 1 | { 2 | "exchange": 3 | { 4 | "name": "binance", 5 | "pair_whitelist": 6 | [ 7 | "AAVE/USDT", 8 | "ACM/USDT", 9 | "ADA/USDT", 10 | "AION/USDT", 11 | "ALGO/USDT", 12 | "ALICE/USDT", 13 | "ALPHA/USDT", 14 | "AR/USDT", 15 | "ATOM/USDT", 16 | "AUDIO/USDT", 17 | "AVA/USDT", 18 | "AVAX/USDT", 19 | "AXS/USDT", 20 | "BAKE/USDT", 21 | "BAT/USDT", 22 | "BCH/USDT", 23 | "BTC/USDT", 24 | "BTCST/USDT", 25 | "BTG/USDT", 26 | "BURGER/USDT", 27 | "CAKE/USDT", 28 | "CELO/USDT", 29 | "CELR/USDT", 30 | "CHR/USDT", 31 | "CHZ/USDT", 32 | "CKB/USDT", 33 | "COCOS/USDT", 34 | "COMP/USDT", 35 | "CRV/USDT", 36 | "CTSI/USDT", 37 | "DATA/USDT", 38 | "DEGO/USDT", 39 | "DGB/USDT", 40 | "DNT/USDT", 41 | "DOCK/USDT", 42 | "DOGE/USDT", 43 | "DOT/USDT", 44 | "EGLD/USDT", 45 | "ENJ/USDT", 46 | "EOS/USDT", 47 | "ETC/USDT", 48 | "ETH/USDT", 49 | "FIL/USDT", 50 | "GTO/USDT", 51 | "HARD/USDT", 52 | "HBAR/USDT", 53 | "HNT/USDT", 54 | "IOST/USDT", 55 | "IOTA/USDT", 56 | "IOTX/USDT", 57 | "JUV/USDT", 58 | "KAVA/USDT", 59 | "KSM/USDT", 60 | "LPT/USDT", 61 | "LTC/USDT", 62 | "LUNA/USDT", 63 | "MANA/USDT", 64 | "MASK/USDT", 65 | "MATIC/USDT", 66 | "MBL/USDT", 67 | "MITH/USDT", 68 | "MKR/USDT", 69 | "MTL/USDT", 70 | "NEAR/USDT", 71 | "NEO/USDT", 72 | "NKN/USDT", 73 | "NMR/USDT", 74 | "OM/USDT", 75 | "ONG/USDT", 76 | "ONT/USDT", 77 | "PERL/USDT", 78 | "PERP/USDT", 79 | "POLS/USDT", 80 | "POND/USDT", 81 | "PSG/USDT", 82 | "RUNE/USDT", 83 | "RVN/USDT", 84 | "SAND/USDT", 85 | "SC/USDT", 86 | "SKL/USDT", 87 | "SLP/USDT", 88 | "SNX/USDT", 89 | "SOL/USDT", 90 | "STPT/USDT", 91 | "STX/USDT", 92 | "SUPER/USDT", 93 | "SUSHI/USDT", 94 | "SXP/USDT", 95 | "TFUEL/USDT", 96 | "THETA/USDT", 97 | "TKO/USDT", 98 | "TLM/USDT", 99 | "TRU/USDT", 100 | "TRX/USDT", 101 | "TWT/USDT", 102 | "VET/USDT", 103 | "WIN/USDT", 104 | "WING/USDT", 105 | "WRX/USDT", 106 | "XEM/USDT", 107 | "XLM/USDT", 108 | "XRP/USDT", 109 | "XTZ/USDT", 110 | "YFI/USDT", 111 | "ZEN/USDT", 112 | "ZIL/USDT", 113 | "ZRX/USDT" 114 | ] 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /user_data/pairlist/binclucmaddevelop-static-pairlist.json: -------------------------------------------------------------------------------- 1 | { 2 | "exchange": 3 | { 4 | "name": "binance", 5 | "pair_whitelist": 6 | [ 7 | "AAVE/USDT", 8 | "ACM/USDT", 9 | "ADA/USDT", 10 | "AION/USDT", 11 | "ALGO/USDT", 12 | "ALICE/USDT", 13 | "ALPHA/USDT", 14 | "ANKR/USDT", 15 | "AR/USDT", 16 | "ASR/USDT", 17 | "ATM/USDT", 18 | "ATOM/USDT", 19 | "AUDIO/USDT", 20 | "AVA/USDT", 21 | "AVAX/USDT", 22 | "AXS/USDT", 23 | "BAKE/USDT", 24 | "BAT/USDT", 25 | "BTC/USDT", 26 | "BTG/USDT", 27 | "BTT/USDT", 28 | "BURGER/USDT", 29 | "CAKE/USDT", 30 | "CELO/USDT", 31 | "CELR/USDT", 32 | "CHR/USDT", 33 | "CHZ/USDT", 34 | "CKB/USDT", 35 | "COCOS/USDT", 36 | "COMP/USDT", 37 | "CRV/USDT", 38 | "CTSI/USDT", 39 | "DATA/USDT", 40 | "DEGO/USDT", 41 | "DGB/USDT", 42 | "DNT/USDT", 43 | "DOCK/USDT", 44 | "DODO/USDT", 45 | "DOGE/USDT", 46 | "DOT/USDT", 47 | "ENJ/USDT", 48 | "EOS/USDT", 49 | "ETC/USDT", 50 | "ETH/USDT", 51 | "FIL/USDT", 52 | "GTO/USDT", 53 | "GXS/USDT", 54 | "HARD/USDT", 55 | "HNT/USDT", 56 | "HOT/USDT", 57 | "IOST/USDT", 58 | "IOTA/USDT", 59 | "KAVA/USDT", 60 | "KSM/USDT", 61 | "LINK/USDT", 62 | "LPT/USDT", 63 | "LTC/USDT", 64 | "MANA/USDT", 65 | "MASK/USDT", 66 | "MATIC/USDT", 67 | "MBL/USDT", 68 | "MITH/USDT", 69 | "MTL/USDT", 70 | "NEAR/USDT", 71 | "NEO/USDT", 72 | "NKN/USDT", 73 | "NMR/USDT", 74 | "OGN/USDT", 75 | "OM/USDT", 76 | "OMG/USDT", 77 | "ONG/USDT", 78 | "OXT/USDT", 79 | "PERL/USDT", 80 | "PERP/USDT", 81 | "PNT/USDT", 82 | "POND/USDT", 83 | "PSG/USDT", 84 | "QTUM/USDT", 85 | "RLC/USDT", 86 | "RUNE/USDT", 87 | "RVN/USDT", 88 | "SAND/USDT", 89 | "SKL/USDT", 90 | "SLP/USDT", 91 | "SNX/USDT", 92 | "SOL/USDT", 93 | "STPT/USDT", 94 | "STRAX/USDT", 95 | "SUSHI/USDT", 96 | "SXP/USDT", 97 | "TFUEL/USDT", 98 | "THETA/USDT", 99 | "TKO/USDT", 100 | "TLM/USDT", 101 | "TRU/USDT", 102 | "TRX/USDT", 103 | "VET/USDT", 104 | "WIN/USDT", 105 | "WING/USDT", 106 | "WRX/USDT", 107 | "XEM/USDT", 108 | "XLM/USDT", 109 | "XMR/USDT", 110 | "XRP/USDT", 111 | "XTZ/USDT", 112 | "YFI/USDT", 113 | "ZEN/USDT", 114 | "ZIL/USDT", 115 | "ZRX/USDT" 116 | ] 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /MULTIPLEBOT.md: -------------------------------------------------------------------------------- 1 | ```yml 2 | 3 | --- 4 | version: '3' 5 | services: 6 | freqtrade1: 7 | image: minulislam/freqtrade:stable 8 | # image: freqtradeorg/freqtrade:develop 9 | build: 10 | context: . 11 | dockerfile: "./docker/Dockerfile.stable" 12 | restart: unless-stopped 13 | container_name: BinClucMadSMAv1 14 | volumes: 15 | - "./user_data:/freqtrade/user_data" 16 | ports: 17 | - "0.0.0.0:${PORT:-8080}:${PORT:-8080}" 18 | # Default command used when running `docker compose up` 19 | command: > 20 | trade 21 | --logfile /freqtrade/user_data/logs/freqtrade1.log 22 | --db-url sqlite:////freqtrade/user_data/tradesv3_freqtrade1.sqlite 23 | --config /freqtrade/user_data/config.json 24 | --config /freqtrade/user_data/config-private.json 25 | --config /freqtrade/user_data/config-telegram.json 26 | --config /freqtrade/user_data/pairlist/${PAIRLIST:-binance-usdt-static}.json 27 | --config /freqtrade/user_data/pairlist/blacklist-binance.json 28 | --strategy BinClucMadSMAv1 29 | env_file: 30 | - freqtrade1.env 31 | 32 | 33 | 34 | 35 | freqtrade3: 36 | image: minulislam/freqtrade:stable 37 | # image: freqtradeorg/freqtrade:develop 38 | build: 39 | context: . 40 | dockerfile: "./docker/Dockerfile.stable" 41 | restart: unless-stopped 42 | container_name: Obelisk_Ichimoku_Slow_v1_3 43 | volumes: 44 | - "./user_data:/freqtrade/user_data" 45 | ports: 46 | - "0.0.0.0:${PORT3:-8080}:${PORT:-8080}" 47 | # Default command used when running `docker compose up` 48 | command: > 49 | trade 50 | --logfile /freqtrade/user_data/logs/freqtrade3.log 51 | --db-url sqlite:////freqtrade/user_data/tradesv3_freqtrade3.sqlite 52 | --config /freqtrade/user_data/config.json 53 | --config /freqtrade/user_data/config-private.json 54 | --config /freqtrade/user_data/pairlist/${PAIRLIST3:-binance-usdt-static}.json 55 | --config /freqtrade/user_data/pairlist/blacklist-binance.json 56 | --strategy Obelisk_Ichimoku_Slow_v1_3 57 | # environment: 58 | # - FREQTRADE__MAX_OPEN_TRADES=5 59 | # - FREQTRADE__AVAILABLE_CAPTITAL=1000 60 | env_file: 61 | - freqtrade3.env 62 | 63 | 64 | freqtrade4: 65 | image: minulislam/freqtrade:stable 66 | # image: freqtradeorg/freqtrade:develop 67 | build: 68 | context: . 69 | dockerfile: "./docker/Dockerfile.stable" 70 | restart: unless-stopped 71 | container_name: Combined_NFIv7_SMA 72 | volumes: 73 | - "./user_data:/freqtrade/user_data" 74 | # Expose api on port 8080 (localhost only) 75 | # Please read the https://www.freqtrade.io/en/latest/rest-api/ documentation 76 | # before enabling this. 77 | ports: 78 | - "0.0.0.0:${PORT4:-8080}:${PORT:-8080}" 79 | # Default command used when running `docker compose up` 80 | command: > 81 | trade 82 | --logfile /freqtrade/user_data/logs/freqtrade4.log 83 | --db-url sqlite:////freqtrade/user_data/tradesv3_freqtrade4.sqlite 84 | --config /freqtrade/user_data/config.json 85 | --config /freqtrade/user_data/config-private.json 86 | --config /freqtrade/user_data/pairlist/${PAIRLIST4:-binance-usdt-static}.json 87 | --config /freqtrade/user_data/pairlist/blacklist-binance.json 88 | --strategy Combined_NFIv7_SMA 89 | env_file: 90 | - freqtrade4.env 91 | 92 | 93 | ``` 94 | 95 | ```env 96 | FREQTRADE__MAX_OPEN_TRADES=10 97 | FREQTRADE__AVAILABLE_CAPTITAL=1000 98 | 99 | 100 | 101 | ``` 102 | -------------------------------------------------------------------------------- /user_data/pairlist/binance-usdt-static.json: -------------------------------------------------------------------------------- 1 | { 2 | "exchange": 3 | { 4 | "name": "binance", 5 | "pair_whitelist": 6 | [ 7 | "AAVE/USDT", 8 | "ACM/USDT", 9 | "ADA/USDT", 10 | "AION/USDT", 11 | "ALGO/USDT", 12 | "ALICE/USDT", 13 | "ALPHA/USDT", 14 | "ANKR/USDT", 15 | "AR/USDT", 16 | "ASR/USDT", 17 | "ATM/USDT", 18 | "ATOM/USDT", 19 | "AUDIO/USDT", 20 | "AVA/USDT", 21 | "AVAX/USDT", 22 | "AXS/USDT", 23 | "BAKE/USDT", 24 | "BAT/USDT", 25 | "BCH/USDT", 26 | "BTC/USDT", 27 | "BTCST/USDT", 28 | "BTG/USDT", 29 | "BTT/USDT", 30 | "BURGER/USDT", 31 | "CAKE/USDT", 32 | "CELO/USDT", 33 | "CELR/USDT", 34 | "CHR/USDT", 35 | "CHZ/USDT", 36 | "CKB/USDT", 37 | "COTI/USDT", 38 | "COCOS/USDT", 39 | "COMP/USDT", 40 | "CRV/USDT", 41 | "CTSI/USDT", 42 | "DASH/USDT", 43 | "DATA/USDT", 44 | "DEGO/USDT", 45 | "DENT/USDT", 46 | "DGB/USDT", 47 | "DNT/USDT", 48 | "DOCK/USDT", 49 | "DODO/USDT", 50 | "DOGE/USDT", 51 | "DOT/USDT", 52 | "EGLD/USDT", 53 | "ELF/USDT", 54 | "ENJ/USDT", 55 | "EOS/USDT", 56 | "ETC/USDT", 57 | "ETH/USDT", 58 | "FIL/USDT", 59 | "FOR/USDT", 60 | "FTM/USDT", 61 | "GRT/USDT", 62 | "GTO/USDT", 63 | "GXS/USDT", 64 | "HARD/USDT", 65 | "HBAR/USDT", 66 | "HNT/USDT", 67 | "HOT/USDT", 68 | "IOST/USDT", 69 | "IOTA/USDT", 70 | "IOTX/USDT", 71 | "JUV/USDT", 72 | "KAVA/USDT", 73 | "KSM/USDT", 74 | "LINK/USDT", 75 | "LPT/USDT", 76 | "LTC/USDT", 77 | "LUNA/USDT", 78 | "MANA/USDT", 79 | "MASK/USDT", 80 | "MATIC/USDT", 81 | "MBL/USDT", 82 | "MITH/USDT", 83 | "MINA/USDT", 84 | "MKR/USDT", 85 | "MTL/USDT", 86 | "NEAR/USDT", 87 | "NEO/USDT", 88 | "NKN/USDT", 89 | "NMR/USDT", 90 | "OGN/USDT", 91 | "OM/USDT", 92 | "OMG/USDT", 93 | "ONE/USDT", 94 | "ONG/USDT", 95 | "ONT/USDT", 96 | "OXT/USDT", 97 | "PERL/USDT", 98 | "PERP/USDT", 99 | "PNT/USDT", 100 | "POLS/USDT", 101 | "POND/USDT", 102 | "PSG/USDT", 103 | "QTUM/USDT", 104 | "REEF/USDT", 105 | "RLC/USDT", 106 | "RUNE/USDT", 107 | "RVN/USDT", 108 | "SAND/USDT", 109 | "SC/USDT", 110 | "SKL/USDT", 111 | "SLP/USDT", 112 | "SNX/USDT", 113 | "SOL/USDT", 114 | "STMX/USDT", 115 | "STPT/USDT", 116 | "STRAX/USDT", 117 | "STX/USDT", 118 | "SUPER/USDT", 119 | "SUSHI/USDT", 120 | "SXP/USDT", 121 | "TFUEL/USDT", 122 | "THETA/USDT", 123 | "TKO/USDT", 124 | "TLM/USDT", 125 | "TRU/USDT", 126 | "TRX/USDT", 127 | "TWT/USDT", 128 | "UNI/USDT", 129 | "VET/USDT", 130 | "WAVES/USDT", 131 | "WIN/USDT", 132 | "WING/USDT", 133 | "WRX/USDT", 134 | "XEM/USDT", 135 | "XEC/USDT", 136 | "XLM/USDT", 137 | "XMR/USDT", 138 | "XRP/USDT", 139 | "XTZ/USDT", 140 | "XVS/USDT", 141 | "YFI/USDT", 142 | "ZEC/USDT", 143 | "ZEN/USDT", 144 | "ZIL/USDT", 145 | "ZRX/USDT" 146 | ] 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /user_data/strategies/flawless_victory_v1.py: -------------------------------------------------------------------------------- 1 | # pragma pylint: disable=missing-docstring, invalid-name, pointless-string-statement 2 | # flake8: noqa: F401 3 | # isort: skip_file 4 | # --- Do not remove these libs --- 5 | import math 6 | 7 | import numpy as np # noqa 8 | import pandas as pd # noqa 9 | from pandas import DataFrame 10 | 11 | from freqtrade.strategy import IStrategy 12 | 13 | # -------------------------------- 14 | # Add your lib to import here 15 | import talib.abstract as ta 16 | import freqtrade.vendor.qtpylib.indicators as qtpylib 17 | from freqtrade.strategy import IntParameter 18 | 19 | 20 | def optimize(space: str): 21 | def fn(val: int): 22 | perc = 0.5 23 | 24 | low = math.floor(val * (1 - perc)) 25 | high = math.floor(val * (1 + perc)) 26 | 27 | return IntParameter(default=val, low=low, high=high, space=space, 28 | optimize=True, load=True) 29 | 30 | return fn 31 | 32 | 33 | # This strategy is based on https://www.tradingview.com/script/i3Uc79fF-Flawless-Victory-Strategy-15min-BTC-Machine-Learning-Strategy/ 34 | # Author of the original Pinescript strategy: Robert Roman (https://github.com/TreborNamor) 35 | class FlawlessVictory(IStrategy): 36 | buyOptimize = optimize('buy') 37 | sellOptimize = optimize('sell') 38 | 39 | buy_rsi_length = buyOptimize(14) 40 | buy_bb_window = buyOptimize(20) 41 | buy_rsi_lower = buyOptimize(43) 42 | 43 | sell_rsi_length = sellOptimize(14) 44 | sell_bb_window = sellOptimize(20) 45 | sell_rsi_upper = sellOptimize(70) 46 | 47 | # Strategy interface version - allow new iterations of the strategy interface. 48 | # Check the documentation or the Sample strategy to get the latest version. 49 | INTERFACE_VERSION = 2 50 | 51 | stoploss = -999999 52 | 53 | # Optimal timeframe for the strategy. 54 | timeframe = '15m' 55 | 56 | # Run "populate_indicators()" only for new candle. 57 | process_only_new_candles = False 58 | 59 | # These values can be overridden in the "ask_strategy" section in the config. 60 | use_sell_signal = True 61 | sell_profit_only = False 62 | ignore_roi_if_buy_signal = False 63 | 64 | # Number of candles the strategy requires before producing valid signals 65 | startup_candle_count: int = 50 66 | 67 | # Optional order type mapping. 68 | order_types = { 69 | 'buy': 'limit', 70 | 'sell': 'limit', 71 | 'stoploss': 'market', 72 | 'stoploss_on_exchange': False 73 | } 74 | 75 | # Optional order time in force. 76 | order_time_in_force = { 77 | 'buy': 'gtc', 78 | 'sell': 'gtc' 79 | } 80 | 81 | plot_config = { 82 | 'main_plot': { 83 | 'bb_upperband': {'color': 'blue'}, 84 | 'bb_lowerband': {'color': 'blue'} 85 | }, 86 | 'subplots': { 87 | "RSI": { 88 | 'rsi': {'color': 'purple'}, 89 | 'rsi_lower': {'color': 'black'}, 90 | 'rsi_upper': {'color': 'black'} 91 | } 92 | } 93 | } 94 | 95 | def informative_pairs(self): 96 | return [] 97 | 98 | def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: 99 | return dataframe 100 | 101 | def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: 102 | dataframe['rsi'] = ta.RSI(dataframe['close'], int(self.buy_rsi_length.value)) 103 | 104 | dataframe['rsi_lower'] = int(self.buy_rsi_lower.value) 105 | 106 | bollinger = qtpylib.bollinger_bands( 107 | dataframe['close'], window=int(self.buy_bb_window.value), stds=1 108 | ) 109 | 110 | dataframe['bb_lowerband'] = bollinger['lower'] 111 | 112 | bb_long = dataframe['close'] < dataframe['bb_lowerband'] 113 | rsi_long = dataframe['rsi'] > dataframe['rsi_lower'] 114 | 115 | dataframe['buy'] = bb_long & rsi_long 116 | return dataframe 117 | 118 | def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: 119 | dataframe['rsi'] = ta.RSI(dataframe['close'], int(self.sell_rsi_length.value)) 120 | 121 | dataframe['rsi_upper'] = int(self.sell_rsi_upper.value) 122 | 123 | bollinger = qtpylib.bollinger_bands( 124 | dataframe['close'], window=int(self.sell_bb_window.value), stds=1 125 | ) 126 | 127 | dataframe['bb_upperband'] = bollinger['upper'] 128 | 129 | bb_short = dataframe['close'] > dataframe['bb_upperband'] 130 | rsi_short = dataframe['rsi'] > dataframe['rsi_upper'] 131 | 132 | dataframe['sell'] = bb_short & rsi_short 133 | return dataframe 134 | -------------------------------------------------------------------------------- /user_data/pairlist/Binance-USDT-All.json: -------------------------------------------------------------------------------- 1 | { 2 | "exchange": { 3 | "pair_whitelist": [ 4 | "1INCH/USDT", 5 | "AAVE/USDT", 6 | "ACM/USDT", 7 | "ADA/USDT", 8 | "AION/USDT", 9 | "AKRO/USDT", 10 | "ALGO/USDT", 11 | "ALICE/USDT", 12 | "ALPHA/USDT", 13 | "ANKR/USDT", 14 | "ANT/USDT", 15 | "AR/USDT", 16 | "ARDR/USDT", 17 | "ARPA/USDT", 18 | "ASR/USDT", 19 | "ATA/USDT", 20 | "ATM/USDT", 21 | "ATOM/USDT", 22 | "AUD/USDT", 23 | "AUDIO/USDT", 24 | "AUTO/USDT", 25 | "AVA/USDT", 26 | "AVAX/USDT", 27 | "AXS/USDT", 28 | "BADGER/USDT", 29 | "BAKE/USDT", 30 | "BAL/USDT", 31 | "BAND/USDT", 32 | "BAR/USDT", 33 | "BAT/USDT", 34 | "BCH/USDT", 35 | "BEAM/USDT", 36 | "BEL/USDT", 37 | "BLZ/USDT", 38 | "BNB/USDT", 39 | "BNT/USDT", 40 | "BTC/USDT", 41 | "BTCST/USDT", 42 | "BTG/USDT", 43 | "BTS/USDT", 44 | "BTT/USDT", 45 | "BURGER/USDT", 46 | "BUSD/USDT", 47 | "BZRX/USDT", 48 | "CAKE/USDT", 49 | "CELO/USDT", 50 | "CELR/USDT", 51 | "CFX/USDT", 52 | "CHR/USDT", 53 | "CHZ/USDT", 54 | "CKB/USDT", 55 | "COCOS/USDT", 56 | "COMP/USDT", 57 | "COS/USDT", 58 | "COTI/USDT", 59 | "CRV/USDT", 60 | "CTK/USDT", 61 | "CTSI/USDT", 62 | "CTXC/USDT", 63 | "CVC/USDT", 64 | "DASH/USDT", 65 | "DATA/USDT", 66 | "DCR/USDT", 67 | "DEGO/USDT", 68 | "DENT/USDT", 69 | "DGB/USDT", 70 | "DIA/USDT", 71 | "DNT/USDT", 72 | "DOCK/USDT", 73 | "DODO/USDT", 74 | "DOGE/USDT", 75 | "DOT/USDT", 76 | "DREP/USDT", 77 | "DUSK/USDT", 78 | "EGLD/USDT", 79 | "ENJ/USDT", 80 | "EOS/USDT", 81 | "EPS/USDT", 82 | "ETC/USDT", 83 | "ETH/USDT", 84 | "EUR/USDT", 85 | "FET/USDT", 86 | "FIL/USDT", 87 | "FIO/USDT", 88 | "FIRO/USDT", 89 | "FIS/USDT", 90 | "FLM/USDT", 91 | "FORTH/USDT", 92 | "FTM/USDT", 93 | "FTT/USDT", 94 | "FUN/USDT", 95 | "GBP/USDT", 96 | "GRT/USDT", 97 | "GTC/USDT", 98 | "GTO/USDT", 99 | "GXS/USDT", 100 | "HARD/USDT", 101 | "HBAR/USDT", 102 | "HIVE/USDT", 103 | "HNT/USDT", 104 | "HOT/USDT", 105 | "ICP/USDT", 106 | "ICX/USDT", 107 | "INJ/USDT", 108 | "IOST/USDT", 109 | "IOTA/USDT", 110 | "IOTX/USDT", 111 | "IRIS/USDT", 112 | "JST/USDT", 113 | "JUV/USDT", 114 | "KAVA/USDT", 115 | "KEY/USDT", 116 | "KMD/USDT", 117 | "KNC/USDT", 118 | "KSM/USDT", 119 | "LINA/USDT", 120 | "LINK/USDT", 121 | "LIT/USDT", 122 | "LPT/USDT", 123 | "LRC/USDT", 124 | "LSK/USDT", 125 | "LTC/USDT", 126 | "LTO/USDT", 127 | "LUNA/USDT", 128 | "MANA/USDT", 129 | "MASK/USDT", 130 | "MATIC/USDT", 131 | "MBL/USDT", 132 | "MDT/USDT", 133 | "MDX/USDT", 134 | "MFT/USDT", 135 | "MIR/USDT", 136 | "MITH/USDT", 137 | "MKR/USDT", 138 | "MTL/USDT", 139 | "NANO/USDT", 140 | "NBS/USDT", 141 | "NEAR/USDT", 142 | "NEO/USDT", 143 | "NKN/USDT", 144 | "NMR/USDT", 145 | "NU/USDT", 146 | "NULS/USDT", 147 | "OCEAN/USDT", 148 | "OG/USDT", 149 | "OGN/USDT", 150 | "OM/USDT", 151 | "OMG/USDT", 152 | "ONE/USDT", 153 | "ONG/USDT", 154 | "ONT/USDT", 155 | "ORN/USDT", 156 | "OXT/USDT", 157 | "PAX/USDT", 158 | "PAXG/USDT", 159 | "PERL/USDT", 160 | "PERP/USDT", 161 | "PNT/USDT", 162 | "POLS/USDT", 163 | "POND/USDT", 164 | "PSG/USDT", 165 | "PUNDIX/USDT", 166 | "QTUM/USDT", 167 | "RAMP/USDT", 168 | "REEF/USDT", 169 | "REN/USDT", 170 | "REP/USDT", 171 | "RIF/USDT", 172 | "RLC/USDT", 173 | "ROSE/USDT", 174 | "RSR/USDT", 175 | "RUNE/USDT", 176 | "RVN/USDT", 177 | "SAND/USDT", 178 | "SC/USDT", 179 | "SFP/USDT", 180 | "SHIB/USDT", 181 | "SKL/USDT", 182 | "SLP/USDT", 183 | "SNX/USDT", 184 | "SOL/USDT", 185 | "SRM/USDT", 186 | "STMX/USDT", 187 | "STORJ/USDT", 188 | "STPT/USDT", 189 | "STRAX/USDT", 190 | "STX/USDT", 191 | "SUN/USDT", 192 | "SUPER/USDT", 193 | "SUSD/USDT", 194 | "SUSHI/USDT", 195 | "SXP/USDT", 196 | "TCT/USDT", 197 | "TFUEL/USDT", 198 | "THETA/USDT", 199 | "TKO/USDT", 200 | "TLM/USDT", 201 | "TOMO/USDT", 202 | "TORN/USDT", 203 | "TRB/USDT", 204 | "TROY/USDT", 205 | "TRU/USDT", 206 | "TRX/USDT", 207 | "TUSD/USDT", 208 | "TWT/USDT", 209 | "UMA/USDT", 210 | "UNFI/USDT", 211 | "UNI/USDT", 212 | "USDC/USDT", 213 | "UTK/USDT", 214 | "VET/USDT", 215 | "VITE/USDT", 216 | "VTHO/USDT", 217 | "WAN/USDT", 218 | "WAVES/USDT", 219 | "WIN/USDT", 220 | "WING/USDT", 221 | "WNXM/USDT", 222 | "WRX/USDT", 223 | "WTC/USDT", 224 | "XEM/USDT", 225 | "XLM/USDT", 226 | "XMR/USDT", 227 | "XRP/USDT", 228 | "XTZ/USDT", 229 | "XVG/USDT", 230 | "XVS/USDT", 231 | "YFI/USDT", 232 | "YFII/USDT", 233 | "ZEC/USDT", 234 | "ZEN/USDT", 235 | "ZIL/USDT", 236 | "ZRX/USDT" 237 | ] 238 | } 239 | } 240 | -------------------------------------------------------------------------------- /user_data/pairlist/Binance-BTC-All.json: -------------------------------------------------------------------------------- 1 | { 2 | "exchange": { 3 | "pair_whitelist": [ 4 | "1INCH/BTC", 5 | "AAVE/BTC", 6 | "ACM/BTC", 7 | "ADA/BTC", 8 | "ADX/BTC", 9 | "AERGO/BTC", 10 | "AGIX/BTC", 11 | "AION/BTC", 12 | "AKRO/BTC", 13 | "ALGO/BTC", 14 | "ALICE/BTC", 15 | "ALPHA/BTC", 16 | "AMB/BTC", 17 | "ANKR/BTC", 18 | "ANT/BTC", 19 | "APPC/BTC", 20 | "AR/BTC", 21 | "ARDR/BTC", 22 | "ARK/BTC", 23 | "ARPA/BTC", 24 | "ASR/BTC", 25 | "AST/BTC", 26 | "ATA/BTC", 27 | "ATM/BTC", 28 | "ATOM/BTC", 29 | "AUCTION/BTC", 30 | "AUDIO/BTC", 31 | "AUTO/BTC", 32 | "AVA/BTC", 33 | "AVAX/BTC", 34 | "AXS/BTC", 35 | "BADGER/BTC", 36 | "BAKE/BTC", 37 | "BAL/BTC", 38 | "BAND/BTC", 39 | "BAR/BTC", 40 | "BAT/BTC", 41 | "BCD/BTC", 42 | "BCH/BTC", 43 | "BEAM/BTC", 44 | "BEL/BTC", 45 | "BLZ/BTC", 46 | "BNB/BTC", 47 | "BNT/BTC", 48 | "BQX/BTC", 49 | "BRD/BTC", 50 | "BTCST/BTC", 51 | "BTG/BTC", 52 | "BTS/BTC", 53 | "BZRX/BTC", 54 | "CAKE/BTC", 55 | "CDT/BTC", 56 | "CELO/BTC", 57 | "CELR/BTC", 58 | "CFX/BTC", 59 | "CHR/BTC", 60 | "CHZ/BTC", 61 | "CKB/BTC", 62 | "CND/BTC", 63 | "COMP/BTC", 64 | "COS/BTC", 65 | "COTI/BTC", 66 | "CRV/BTC", 67 | "CTK/BTC", 68 | "CTSI/BTC", 69 | "CTXC/BTC", 70 | "CVC/BTC", 71 | "DASH/BTC", 72 | "DATA/BTC", 73 | "DCR/BTC", 74 | "DEGO/BTC", 75 | "DGB/BTC", 76 | "DIA/BTC", 77 | "DLT/BTC", 78 | "DNT/BTC", 79 | "DOCK/BTC", 80 | "DODO/BTC", 81 | "DOGE/BTC", 82 | "DOT/BTC", 83 | "DREP/BTC", 84 | "DUSK/BTC", 85 | "EGLD/BTC", 86 | "ELF/BTC", 87 | "ENJ/BTC", 88 | "EOS/BTC", 89 | "EPS/BTC", 90 | "ETC/BTC", 91 | "ETH/BTC", 92 | "EVX/BTC", 93 | "EZ/BTC", 94 | "FET/BTC", 95 | "FIL/BTC", 96 | "FIO/BTC", 97 | "FIRO/BTC", 98 | "FIS/BTC", 99 | "FLM/BTC", 100 | "FOR/BTC", 101 | "FORTH/BTC", 102 | "FRONT/BTC", 103 | "FTM/BTC", 104 | "FTT/BTC", 105 | "FUN/BTC", 106 | "FXS/BTC", 107 | "GAS/BTC", 108 | "GLM/BTC", 109 | "GO/BTC", 110 | "GRS/BTC", 111 | "GRT/BTC", 112 | "GTC/BTC", 113 | "GTO/BTC", 114 | "GVT/BTC", 115 | "GXS/BTC", 116 | "HARD/BTC", 117 | "HBAR/BTC", 118 | "HIVE/BTC", 119 | "HNT/BTC", 120 | "ICP/BTC", 121 | "ICX/BTC", 122 | "IDEX/BTC", 123 | "INJ/BTC", 124 | "IOST/BTC", 125 | "IOTA/BTC", 126 | "IOTX/BTC", 127 | "IRIS/BTC", 128 | "JST/BTC", 129 | "JUV/BTC", 130 | "KAVA/BTC", 131 | "KMD/BTC", 132 | "KNC/BTC", 133 | "KSM/BTC", 134 | "LINA/BTC", 135 | "LINK/BTC", 136 | "LIT/BTC", 137 | "LOOM/BTC", 138 | "LPT/BTC", 139 | "LRC/BTC", 140 | "LSK/BTC", 141 | "LTC/BTC", 142 | "LTO/BTC", 143 | "LUNA/BTC", 144 | "MANA/BTC", 145 | "MATIC/BTC", 146 | "MDA/BTC", 147 | "MDT/BTC", 148 | "MDX/BTC", 149 | "MIR/BTC", 150 | "MITH/BTC", 151 | "MKR/BTC", 152 | "MTH/BTC", 153 | "MTL/BTC", 154 | "NANO/BTC", 155 | "NAS/BTC", 156 | "NAV/BTC", 157 | "NBS/BTC", 158 | "NEAR/BTC", 159 | "NEBL/BTC", 160 | "NEO/BTC", 161 | "NKN/BTC", 162 | "NMR/BTC", 163 | "NU/BTC", 164 | "NULS/BTC", 165 | "NXS/BTC", 166 | "OAX/BTC", 167 | "OCEAN/BTC", 168 | "OG/BTC", 169 | "OGN/BTC", 170 | "OM/BTC", 171 | "OMG/BTC", 172 | "ONE/BTC", 173 | "ONG/BTC", 174 | "ONT/BTC", 175 | "ORN/BTC", 176 | "OST/BTC", 177 | "OXT/BTC", 178 | "PAXG/BTC", 179 | "PERL/BTC", 180 | "PERP/BTC", 181 | "PHA/BTC", 182 | "PHB/BTC", 183 | "PIVX/BTC", 184 | "PNT/BTC", 185 | "POA/BTC", 186 | "POLS/BTC", 187 | "POLY/BTC", 188 | "POND/BTC", 189 | "POWR/BTC", 190 | "PPT/BTC", 191 | "PSG/BTC", 192 | "QKC/BTC", 193 | "QLC/BTC", 194 | "QSP/BTC", 195 | "QTUM/BTC", 196 | "RAMP/BTC", 197 | "RCN/BTC", 198 | "RDN/BTC", 199 | "REEF/BTC", 200 | "REN/BTC", 201 | "RENBTC/BTC", 202 | "REP/BTC", 203 | "REQ/BTC", 204 | "RIF/BTC", 205 | "RLC/BTC", 206 | "ROSE/BTC", 207 | "RSR/BTC", 208 | "RUNE/BTC", 209 | "RVN/BTC", 210 | "SAND/BTC", 211 | "SC/BTC", 212 | "SCRT/BTC", 213 | "SFP/BTC", 214 | "SKL/BTC", 215 | "SKY/BTC", 216 | "SNGLS/BTC", 217 | "SNM/BTC", 218 | "SNT/BTC", 219 | "SNX/BTC", 220 | "SOL/BTC", 221 | "SRM/BTC", 222 | "STEEM/BTC", 223 | "STMX/BTC", 224 | "STORJ/BTC", 225 | "STPT/BTC", 226 | "STRAX/BTC", 227 | "STX/BTC", 228 | "SUN/BTC", 229 | "SUPER/BTC", 230 | "SUSD/BTC", 231 | "SUSHI/BTC", 232 | "SXP/BTC", 233 | "SYS/BTC", 234 | "TCT/BTC", 235 | "TFUEL/BTC", 236 | "THETA/BTC", 237 | "TKO/BTC", 238 | "TLM/BTC", 239 | "TOMO/BTC", 240 | "TORN/BTC", 241 | "TRB/BTC", 242 | "TROY/BTC", 243 | "TRU/BTC", 244 | "TRX/BTC", 245 | "TVK/BTC", 246 | "TWT/BTC", 247 | "UMA/BTC", 248 | "UNFI/BTC", 249 | "UNI/BTC", 250 | "UTK/BTC", 251 | "VET/BTC", 252 | "VIA/BTC", 253 | "VIB/BTC", 254 | "VIDT/BTC", 255 | "VITE/BTC", 256 | "WABI/BTC", 257 | "WAN/BTC", 258 | "WAVES/BTC", 259 | "WBTC/BTC", 260 | "WING/BTC", 261 | "WNXM/BTC", 262 | "WPR/BTC", 263 | "WRX/BTC", 264 | "WTC/BTC", 265 | "XEM/BTC", 266 | "XLM/BTC", 267 | "XMR/BTC", 268 | "XRP/BTC", 269 | "XTZ/BTC", 270 | "XVG/BTC", 271 | "XVS/BTC", 272 | "YFI/BTC", 273 | "YFII/BTC", 274 | "YOYO/BTC", 275 | "ZEC/BTC", 276 | "ZEN/BTC", 277 | "ZIL/BTC", 278 | "ZRX/BTC" 279 | ] 280 | } 281 | } 282 | -------------------------------------------------------------------------------- /user_data/strategies/ElliotV3.py: -------------------------------------------------------------------------------- 1 | # --- Do not remove these libs --- 2 | from freqtrade.strategy.interface import IStrategy 3 | from typing import Dict, List 4 | from functools import reduce 5 | from pandas import DataFrame 6 | # -------------------------------- 7 | import talib.abstract as ta 8 | import numpy as np 9 | import freqtrade.vendor.qtpylib.indicators as qtpylib 10 | import datetime 11 | from technical.util import resample_to_interval, resampled_merge 12 | from datetime import datetime, timedelta 13 | from freqtrade.persistence import Trade 14 | from freqtrade.strategy import stoploss_from_open, merge_informative_pair, DecimalParameter, IntParameter, CategoricalParameter 15 | import technical.indicators as ftt 16 | 17 | # Buy hyperspace params: 18 | buy_params = { 19 | "base_nb_candles_buy": 21, 20 | "ewo_high": 3.904, 21 | "ewo_low": -19.306, 22 | "low_offset": 0.976, 23 | "rsi_buy": 41 24 | } 25 | 26 | # Sell hyperspace params: 27 | sell_params = { 28 | "base_nb_candles_sell": 69, 29 | "high_offset": 1.014 30 | } 31 | 32 | class ElliotV3(IStrategy): 33 | INTERFACE_VERSION = 2 34 | 35 | # ROI table: 36 | minimal_roi = { 37 | "0": 0.259, 38 | "20": 0.087, 39 | "64": 0.038, 40 | "168": 0 41 | } 42 | 43 | # Stoploss: 44 | stoploss = -0.274 45 | 46 | # SMAOffset 47 | base_nb_candles_buy = IntParameter( 48 | 5, 80, default=buy_params['base_nb_candles_buy'], space='buy', optimize=True) 49 | base_nb_candles_sell = IntParameter( 50 | 5, 80, default=sell_params['base_nb_candles_sell'], space='sell', optimize=True) 51 | low_offset = DecimalParameter( 52 | 0.9, 0.99, default=buy_params['low_offset'], space='buy', optimize=True) 53 | high_offset = DecimalParameter( 54 | 0.99, 1.1, default=sell_params['high_offset'], space='sell', optimize=True) 55 | 56 | # Protection 57 | fast_ewo = 50 58 | slow_ewo = 200 59 | ewo_low = DecimalParameter(-20.0, -8.0, 60 | default=buy_params['ewo_low'], space='buy', optimize=True) 61 | ewo_high = DecimalParameter( 62 | 2.0, 12.0, default=buy_params['ewo_high'], space='buy', optimize=True) 63 | rsi_buy = IntParameter(30, 70, default=buy_params['rsi_buy'], space='buy', optimize=True) 64 | 65 | # Trailing stop: 66 | trailing_stop = True 67 | trailing_stop_positive = 0.01 68 | trailing_stop_positive_offset = 0.049 69 | trailing_only_offset_is_reached = True 70 | 71 | # Sell signal 72 | use_sell_signal = True 73 | sell_profit_only = False 74 | sell_profit_offset = 0.01 75 | ignore_roi_if_buy_signal = True 76 | 77 | ## Optional order time in force. 78 | order_time_in_force = { 79 | 'buy': 'gtc', 80 | 'sell': 'ioc' 81 | } 82 | 83 | # Optimal timeframe for the strategy 84 | timeframe = '5m' 85 | informative_timeframe = '1h' 86 | 87 | process_only_new_candles = True 88 | startup_candle_count = 39 89 | 90 | plot_config = { 91 | 'main_plot': { 92 | 'ma_buy': {'color': 'orange'}, 93 | 'ma_sell': {'color': 'orange'}, 94 | }, 95 | } 96 | 97 | use_custom_stoploss = False 98 | 99 | def informative_pairs(self): 100 | 101 | pairs = self.dp.current_whitelist() 102 | informative_pairs = [(pair, self.informative_timeframe) for pair in pairs] 103 | 104 | return informative_pairs 105 | 106 | def get_informative_indicators(self, metadata: dict): 107 | 108 | dataframe = self.dp.get_pair_dataframe( 109 | pair=metadata['pair'], timeframe=self.informative_timeframe) 110 | 111 | return dataframe 112 | 113 | def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: 114 | 115 | # Calculate all ma_buy values 116 | for val in self.base_nb_candles_buy.range: 117 | dataframe[f'ma_buy_{val}'] = ta.EMA(dataframe, timeperiod=val) 118 | 119 | # Calculate all ma_sell values 120 | for val in self.base_nb_candles_sell.range: 121 | dataframe[f'ma_sell_{val}'] = ta.EMA(dataframe, timeperiod=val) 122 | 123 | # Elliot 124 | dataframe['EWO'] = EWO(dataframe, self.fast_ewo, self.slow_ewo) 125 | 126 | # RSI 127 | dataframe['rsi'] = ta.RSI(dataframe, timeperiod=14) 128 | 129 | return dataframe 130 | 131 | def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: 132 | conditions = [] 133 | 134 | conditions.append( 135 | ( 136 | (dataframe['close'] < (dataframe[f'ma_buy_{self.base_nb_candles_buy.value}'] * self.low_offset.value)) & 137 | (dataframe['EWO'] > self.ewo_high.value) & 138 | (dataframe['rsi'] < self.rsi_buy.value) & 139 | (dataframe['volume'] > 0) 140 | ) 141 | ) 142 | 143 | conditions.append( 144 | ( 145 | (dataframe['close'] < (dataframe[f'ma_buy_{self.base_nb_candles_buy.value}'] * self.low_offset.value)) & 146 | (dataframe['EWO'] < self.ewo_low.value) & 147 | (dataframe['volume'] > 0) 148 | ) 149 | ) 150 | 151 | if conditions: 152 | dataframe.loc[ 153 | reduce(lambda x, y: x | y, conditions), 154 | 'buy' 155 | ]=1 156 | 157 | return dataframe 158 | 159 | def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: 160 | conditions = [] 161 | 162 | conditions.append( 163 | ( 164 | (dataframe['close'] > (dataframe[f'ma_sell_{self.base_nb_candles_sell.value}'] * self.high_offset.value)) & 165 | (dataframe['volume'] > 0) 166 | ) 167 | ) 168 | 169 | if conditions: 170 | dataframe.loc[ 171 | reduce(lambda x, y: x | y, conditions), 172 | 'sell' 173 | ]=1 174 | 175 | return dataframe 176 | 177 | def EWO(dataframe, ema_length=5, ema2_length=35): 178 | df = dataframe.copy() 179 | ema1 = ta.EMA(df, timeperiod=ema_length) 180 | ema2 = ta.EMA(df, timeperiod=ema2_length) 181 | emadif = (ema1 - ema2) / df['close'] * 100 182 | return emadif 183 | 184 | -------------------------------------------------------------------------------- /user_data/strategies/SMAOffsetProtectOptV1.py: -------------------------------------------------------------------------------- 1 | # --- Do not remove these libs --- 2 | from freqtrade.strategy.interface import IStrategy 3 | from typing import Dict, List 4 | from functools import reduce 5 | from pandas import DataFrame 6 | # -------------------------------- 7 | 8 | import talib.abstract as ta 9 | import numpy as np 10 | import freqtrade.vendor.qtpylib.indicators as qtpylib 11 | import datetime 12 | from technical.util import resample_to_interval, resampled_merge 13 | from datetime import datetime, timedelta 14 | from freqtrade.persistence import Trade 15 | from freqtrade.strategy import stoploss_from_open, merge_informative_pair, DecimalParameter, IntParameter, CategoricalParameter 16 | import technical.indicators as ftt 17 | 18 | # Buy hyperspace params: 19 | buy_params = { 20 | "base_nb_candles_buy": 16, 21 | "ewo_high": 5.638, 22 | "ewo_low": -19.993, 23 | "low_offset": 0.978, 24 | "rsi_buy": 61, 25 | } 26 | 27 | # Sell hyperspace params: 28 | sell_params = { 29 | "base_nb_candles_sell": 49, 30 | "high_offset": 1.006, 31 | } 32 | 33 | def EWO(dataframe, ema_length=5, ema2_length=35): 34 | df = dataframe.copy() 35 | ema1 = ta.EMA(df, timeperiod=ema_length) 36 | ema2 = ta.EMA(df, timeperiod=ema2_length) 37 | emadif = (ema1 - ema2) / df['close'] * 100 38 | return emadif 39 | 40 | 41 | class SMAOffsetProtectOptV1(IStrategy): 42 | INTERFACE_VERSION = 2 43 | 44 | # ROI table: 45 | minimal_roi = { 46 | "0": 0.01 47 | } 48 | 49 | # Stoploss: 50 | stoploss = -0.5 51 | 52 | # SMAOffset 53 | base_nb_candles_buy = IntParameter( 54 | 5, 80, default=buy_params['base_nb_candles_buy'], space='buy', optimize=True) 55 | base_nb_candles_sell = IntParameter( 56 | 5, 80, default=sell_params['base_nb_candles_sell'], space='sell', optimize=True) 57 | low_offset = DecimalParameter( 58 | 0.9, 0.99, default=buy_params['low_offset'], space='buy', optimize=True) 59 | high_offset = DecimalParameter( 60 | 0.99, 1.1, default=sell_params['high_offset'], space='sell', optimize=True) 61 | 62 | # Protection 63 | fast_ewo = 50 64 | slow_ewo = 200 65 | ewo_low = DecimalParameter(-20.0, -8.0, 66 | default=buy_params['ewo_low'], space='buy', optimize=True) 67 | ewo_high = DecimalParameter( 68 | 2.0, 12.0, default=buy_params['ewo_high'], space='buy', optimize=True) 69 | rsi_buy = IntParameter(30, 70, default=buy_params['rsi_buy'], space='buy', optimize=True) 70 | 71 | 72 | # Trailing stop: 73 | trailing_stop = False 74 | trailing_stop_positive = 0.001 75 | trailing_stop_positive_offset = 0.01 76 | trailing_only_offset_is_reached = True 77 | 78 | # Sell signal 79 | use_sell_signal = True 80 | sell_profit_only = False 81 | sell_profit_offset = 0.01 82 | ignore_roi_if_buy_signal = True 83 | 84 | # Optimal timeframe for the strategy 85 | timeframe = '5m' 86 | informative_timeframe = '1h' 87 | 88 | process_only_new_candles = True 89 | startup_candle_count = 49 90 | 91 | plot_config = { 92 | 'main_plot': { 93 | 'ma_buy_16': { 94 | 'color': 'green' 95 | }, 96 | 'ma_sell_49': { 97 | 'color': 'red' 98 | } 99 | }, 100 | 'subplots': { 101 | 'RSI': { 102 | 'rsi': { 103 | 'color': '#fe2e34', 104 | 'type': 'line' 105 | } 106 | }, 107 | 'EWO': { 108 | 'EWO': { 109 | 'color': '#c7d729', 110 | 'type': 'line' 111 | } 112 | } 113 | } 114 | } 115 | 116 | 117 | use_custom_stoploss = False 118 | 119 | def informative_pairs(self): 120 | 121 | pairs = self.dp.current_whitelist() 122 | informative_pairs = [(pair, self.informative_timeframe) for pair in pairs] 123 | 124 | return informative_pairs 125 | 126 | def get_informative_indicators(self, metadata: dict): 127 | 128 | dataframe = self.dp.get_pair_dataframe( 129 | pair=metadata['pair'], timeframe=self.informative_timeframe) 130 | 131 | return dataframe 132 | 133 | def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: 134 | 135 | # Calculate all ma_buy values 136 | for val in self.base_nb_candles_buy.range: 137 | dataframe[f'ma_buy_{val}'] = ta.EMA(dataframe, timeperiod=val) 138 | 139 | # Calculate all ma_sell values 140 | for val in self.base_nb_candles_sell.range: 141 | dataframe[f'ma_sell_{val}'] = ta.EMA(dataframe, timeperiod=val) 142 | 143 | # Elliot 144 | dataframe['EWO'] = EWO(dataframe, self.fast_ewo, self.slow_ewo) 145 | 146 | # RSI 147 | dataframe['rsi'] = ta.RSI(dataframe, timeperiod=14) 148 | 149 | return dataframe 150 | 151 | def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: 152 | conditions = [] 153 | 154 | conditions.append( 155 | ( 156 | (dataframe['close'] < (dataframe[f'ma_buy_{self.base_nb_candles_buy.value}'] * self.low_offset.value)) & 157 | (dataframe['EWO'] > self.ewo_high.value) & 158 | (dataframe['rsi'] < self.rsi_buy.value) & 159 | (dataframe['volume'] > 0) 160 | ) 161 | ) 162 | 163 | conditions.append( 164 | ( 165 | (dataframe['close'] < (dataframe[f'ma_buy_{self.base_nb_candles_buy.value}'] * self.low_offset.value)) & 166 | (dataframe['EWO'] < self.ewo_low.value) & 167 | (dataframe['volume'] > 0) 168 | ) 169 | ) 170 | 171 | if conditions: 172 | dataframe.loc[ 173 | reduce(lambda x, y: x | y, conditions), 174 | 'buy' 175 | ]=1 176 | 177 | return dataframe 178 | 179 | def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: 180 | conditions = [] 181 | 182 | conditions.append( 183 | ( 184 | (dataframe['close'] > (dataframe[f'ma_sell_{self.base_nb_candles_sell.value}'] * self.high_offset.value)) & 185 | (dataframe['volume'] > 0) 186 | ) 187 | ) 188 | 189 | if conditions: 190 | dataframe.loc[ 191 | reduce(lambda x, y: x | y, conditions), 192 | 'sell' 193 | ]=1 194 | 195 | return dataframe 196 | -------------------------------------------------------------------------------- /user_data/hyperopts/sample_hyperopt.py: -------------------------------------------------------------------------------- 1 | # pragma pylint: disable=missing-docstring, invalid-name, pointless-string-statement 2 | # isort: skip_file 3 | 4 | # --- Do not remove these libs --- 5 | from functools import reduce 6 | from typing import Any, Callable, Dict, List 7 | 8 | import numpy as np # noqa 9 | import pandas as pd # noqa 10 | from pandas import DataFrame 11 | from skopt.space import Categorical, Dimension, Integer, Real # noqa 12 | 13 | from freqtrade.optimize.hyperopt_interface import IHyperOpt 14 | 15 | # -------------------------------- 16 | # Add your lib to import here 17 | import talib.abstract as ta # noqa 18 | import freqtrade.vendor.qtpylib.indicators as qtpylib 19 | 20 | 21 | class SampleHyperOpt(IHyperOpt): 22 | """ 23 | This is a sample Hyperopt to inspire you. 24 | 25 | More information in the documentation: https://www.freqtrade.io/en/latest/hyperopt/ 26 | 27 | You should: 28 | - Rename the class name to some unique name. 29 | - Add any methods you want to build your hyperopt. 30 | - Add any lib you need to build your hyperopt. 31 | 32 | An easier way to get a new hyperopt file is by using 33 | `freqtrade new-hyperopt --hyperopt MyCoolHyperopt`. 34 | 35 | You must keep: 36 | - The prototypes for the methods: populate_indicators, indicator_space, buy_strategy_generator. 37 | 38 | The methods roi_space, generate_roi_table and stoploss_space are not required 39 | and are provided by default. 40 | However, you may override them if you need 'roi' and 'stoploss' spaces that 41 | differ from the defaults offered by Freqtrade. 42 | Sample implementation of these methods will be copied to `user_data/hyperopts` when 43 | creating the user-data directory using `freqtrade create-userdir --userdir user_data`, 44 | or is available online under the following URL: 45 | https://github.com/freqtrade/freqtrade/blob/develop/freqtrade/templates/sample_hyperopt_advanced.py. 46 | """ 47 | 48 | @staticmethod 49 | def indicator_space() -> List[Dimension]: 50 | """ 51 | Define your Hyperopt space for searching buy strategy parameters. 52 | """ 53 | return [ 54 | Integer(10, 25, name='mfi-value'), 55 | Integer(15, 45, name='fastd-value'), 56 | Integer(20, 50, name='adx-value'), 57 | Integer(20, 40, name='rsi-value'), 58 | Categorical([True, False], name='mfi-enabled'), 59 | Categorical([True, False], name='fastd-enabled'), 60 | Categorical([True, False], name='adx-enabled'), 61 | Categorical([True, False], name='rsi-enabled'), 62 | Categorical(['bb_lower', 'macd_cross_signal', 'sar_reversal'], name='trigger') 63 | ] 64 | 65 | @staticmethod 66 | def buy_strategy_generator(params: Dict[str, Any]) -> Callable: 67 | """ 68 | Define the buy strategy parameters to be used by Hyperopt. 69 | """ 70 | def populate_buy_trend(dataframe: DataFrame, metadata: dict) -> DataFrame: 71 | """ 72 | Buy strategy Hyperopt will build and use. 73 | """ 74 | conditions = [] 75 | 76 | # GUARDS AND TRENDS 77 | if 'mfi-enabled' in params and params['mfi-enabled']: 78 | conditions.append(dataframe['mfi'] < params['mfi-value']) 79 | if 'fastd-enabled' in params and params['fastd-enabled']: 80 | conditions.append(dataframe['fastd'] < params['fastd-value']) 81 | if 'adx-enabled' in params and params['adx-enabled']: 82 | conditions.append(dataframe['adx'] > params['adx-value']) 83 | if 'rsi-enabled' in params and params['rsi-enabled']: 84 | conditions.append(dataframe['rsi'] < params['rsi-value']) 85 | 86 | # TRIGGERS 87 | if 'trigger' in params: 88 | if params['trigger'] == 'bb_lower': 89 | conditions.append(dataframe['close'] < dataframe['bb_lowerband']) 90 | if params['trigger'] == 'macd_cross_signal': 91 | conditions.append(qtpylib.crossed_above( 92 | dataframe['macd'], dataframe['macdsignal'] 93 | )) 94 | if params['trigger'] == 'sar_reversal': 95 | conditions.append(qtpylib.crossed_above( 96 | dataframe['close'], dataframe['sar'] 97 | )) 98 | 99 | # Check that volume is not 0 100 | conditions.append(dataframe['volume'] > 0) 101 | 102 | if conditions: 103 | dataframe.loc[ 104 | reduce(lambda x, y: x & y, conditions), 105 | 'buy'] = 1 106 | 107 | return dataframe 108 | 109 | return populate_buy_trend 110 | 111 | @staticmethod 112 | def sell_indicator_space() -> List[Dimension]: 113 | """ 114 | Define your Hyperopt space for searching sell strategy parameters. 115 | """ 116 | return [ 117 | Integer(75, 100, name='sell-mfi-value'), 118 | Integer(50, 100, name='sell-fastd-value'), 119 | Integer(50, 100, name='sell-adx-value'), 120 | Integer(60, 100, name='sell-rsi-value'), 121 | Categorical([True, False], name='sell-mfi-enabled'), 122 | Categorical([True, False], name='sell-fastd-enabled'), 123 | Categorical([True, False], name='sell-adx-enabled'), 124 | Categorical([True, False], name='sell-rsi-enabled'), 125 | Categorical(['sell-bb_upper', 126 | 'sell-macd_cross_signal', 127 | 'sell-sar_reversal'], name='sell-trigger') 128 | ] 129 | 130 | @staticmethod 131 | def sell_strategy_generator(params: Dict[str, Any]) -> Callable: 132 | """ 133 | Define the sell strategy parameters to be used by Hyperopt. 134 | """ 135 | def populate_sell_trend(dataframe: DataFrame, metadata: dict) -> DataFrame: 136 | """ 137 | Sell strategy Hyperopt will build and use. 138 | """ 139 | conditions = [] 140 | 141 | # GUARDS AND TRENDS 142 | if 'sell-mfi-enabled' in params and params['sell-mfi-enabled']: 143 | conditions.append(dataframe['mfi'] > params['sell-mfi-value']) 144 | if 'sell-fastd-enabled' in params and params['sell-fastd-enabled']: 145 | conditions.append(dataframe['fastd'] > params['sell-fastd-value']) 146 | if 'sell-adx-enabled' in params and params['sell-adx-enabled']: 147 | conditions.append(dataframe['adx'] < params['sell-adx-value']) 148 | if 'sell-rsi-enabled' in params and params['sell-rsi-enabled']: 149 | conditions.append(dataframe['rsi'] > params['sell-rsi-value']) 150 | 151 | # TRIGGERS 152 | if 'sell-trigger' in params: 153 | if params['sell-trigger'] == 'sell-bb_upper': 154 | conditions.append(dataframe['close'] > dataframe['bb_upperband']) 155 | if params['sell-trigger'] == 'sell-macd_cross_signal': 156 | conditions.append(qtpylib.crossed_above( 157 | dataframe['macdsignal'], dataframe['macd'] 158 | )) 159 | if params['sell-trigger'] == 'sell-sar_reversal': 160 | conditions.append(qtpylib.crossed_above( 161 | dataframe['sar'], dataframe['close'] 162 | )) 163 | 164 | # Check that volume is not 0 165 | conditions.append(dataframe['volume'] > 0) 166 | 167 | if conditions: 168 | dataframe.loc[ 169 | reduce(lambda x, y: x & y, conditions), 170 | 'sell'] = 1 171 | 172 | return dataframe 173 | 174 | return populate_sell_trend 175 | -------------------------------------------------------------------------------- /user_data/strategies/SMAOffsetProtectOpt.py: -------------------------------------------------------------------------------- 1 | # --- Do not remove these libs --- 2 | from freqtrade.strategy.interface import IStrategy 3 | from typing import Dict, List 4 | from functools import reduce 5 | from pandas import DataFrame 6 | 7 | # -------------------------------- 8 | 9 | import talib.abstract as ta 10 | import numpy as np 11 | import freqtrade.vendor.qtpylib.indicators as qtpylib 12 | import datetime 13 | from technical.util import resample_to_interval, resampled_merge 14 | from datetime import datetime, timedelta 15 | from freqtrade.persistence import Trade 16 | from freqtrade.strategy import ( 17 | stoploss_from_open, 18 | merge_informative_pair, 19 | DecimalParameter, 20 | IntParameter, 21 | CategoricalParameter, 22 | ) 23 | import technical.indicators as ftt 24 | 25 | # Buy hyperspace params: orginal 26 | # buy_params = { 27 | # "base_nb_candles_buy": 16, 28 | # "ewo_high": 5.638, 29 | # "ewo_low": -19.993, 30 | # "low_offset": 0.978, 31 | # "rsi_buy": 61, 32 | # "fast_ewo": 50, # value loaded from strategy 33 | # "slow_ewo": 200, # value loaded from strategy 34 | # } 35 | # Buy hyperspace params: from v0 36 | buy_params = { 37 | "base_nb_candles_buy": 20, 38 | "ewo_high": 5.499, 39 | "ewo_low": -19.881, 40 | "low_offset": 0.975, 41 | "rsi_buy": 50, 42 | "fast_ewo": 50, # value loaded from strategy 43 | "slow_ewo": 200, # value loaded from strategy 44 | } 45 | # Sell hyperspace params:orginal 46 | # sell_params = { 47 | # "base_nb_candles_sell": 49, 48 | # "high_offset": 1.006, 49 | # } 50 | # Sell hyperspace params: from v0 51 | sell_params = { 52 | "base_nb_candles_sell": 24, 53 | "high_offset": 1.012, 54 | } 55 | 56 | 57 | def EWO(dataframe, ema_length=5, ema2_length=35): 58 | df = dataframe.copy() 59 | ema1 = ta.EMA(df, timeperiod=ema_length) 60 | ema2 = ta.EMA(df, timeperiod=ema2_length) 61 | emadif = (ema1 - ema2) / df["close"] * 100 62 | return emadif 63 | 64 | 65 | class SMAOffsetProtectOpt(IStrategy): 66 | INTERFACE_VERSION = 2 67 | 68 | # ROI table: 69 | minimal_roi = {"0": 0.20, "38": 0.074, "78": 0.025, "194": 0} 70 | 71 | # Stoploss: 72 | stoploss = -0.228 73 | 74 | # SMAOffset 75 | base_nb_candles_buy = IntParameter( 76 | 5, 80, default=buy_params["base_nb_candles_buy"], space="buy", optimize=True 77 | ) 78 | base_nb_candles_sell = IntParameter( 79 | 5, 80, default=sell_params["base_nb_candles_sell"], space="sell", optimize=True 80 | ) 81 | low_offset = DecimalParameter( 82 | 0.9, 0.99, default=buy_params["low_offset"], space="buy", optimize=True 83 | ) 84 | high_offset = DecimalParameter( 85 | 0.99, 1.1, default=sell_params["high_offset"], space="sell", optimize=True 86 | ) 87 | 88 | # Protection 89 | fast_ewo = IntParameter( 90 | 10, 50, default=buy_params["fast_ewo"], space="buy", optimize=False 91 | ) 92 | slow_ewo = IntParameter( 93 | 100, 200, default=buy_params["slow_ewo"], space="buy", optimize=False 94 | ) 95 | # fast_ewo = 50 96 | # slow_ewo = 200 97 | ewo_low = DecimalParameter( 98 | -20.0, -8.0, default=buy_params["ewo_low"], space="buy", optimize=True 99 | ) 100 | ewo_high = DecimalParameter( 101 | 2.0, 12.0, default=buy_params["ewo_high"], space="buy", optimize=True 102 | ) 103 | rsi_buy = IntParameter( 104 | 30, 70, default=buy_params["rsi_buy"], space="buy", optimize=True 105 | ) 106 | 107 | # Trailing stop: 108 | trailing_stop = True 109 | trailing_stop_positive = 0.01 110 | trailing_stop_positive_offset = 0.049 111 | trailing_only_offset_is_reached = True 112 | 113 | # Sell signal 114 | use_sell_signal = True 115 | sell_profit_only = False 116 | sell_profit_offset = 0.01 117 | ignore_roi_if_buy_signal = True 118 | 119 | ## Optional order time in force. 120 | order_time_in_force = {"buy": "gtc", "sell": "ioc"} 121 | 122 | 123 | # Optimal timeframe for the strategy 124 | timeframe = "5m" 125 | informative_timeframe = "1h" 126 | 127 | process_only_new_candles = True 128 | startup_candle_count = 50 129 | 130 | plot_config = { 131 | 'main_plot': { 132 | 'ma_buy': { 133 | 'color': 'green' 134 | }, 135 | 'ma_sell': { 136 | 'color': 'red' 137 | } 138 | }, 139 | 'subplots': { 140 | 'RSI': { 141 | 'rsi': { 142 | 'color': '#fe2e34', 143 | 'type': 'line' 144 | } 145 | }, 146 | 'EWO': { 147 | 'EWO': { 148 | 'color': '#c7d729', 149 | 'type': 'line' 150 | } 151 | } 152 | } 153 | } 154 | 155 | use_custom_stoploss = False 156 | 157 | def informative_pairs(self): 158 | 159 | pairs = self.dp.current_whitelist() 160 | informative_pairs = [(pair, self.informative_timeframe) for pair in pairs] 161 | 162 | return informative_pairs 163 | 164 | def get_informative_indicators(self, metadata: dict): 165 | 166 | dataframe = self.dp.get_pair_dataframe( 167 | pair=metadata["pair"], timeframe=self.informative_timeframe 168 | ) 169 | 170 | return dataframe 171 | 172 | def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: 173 | 174 | # Calculate all ma_buy values 175 | for val in self.base_nb_candles_buy.range: 176 | dataframe[f"ma_buy_{val}"] = ta.EMA(dataframe, timeperiod=val) 177 | 178 | # Calculate all ma_sell values 179 | for val in self.base_nb_candles_sell.range: 180 | dataframe[f"ma_sell_{val}"] = ta.EMA(dataframe, timeperiod=val) 181 | 182 | # Elliot 183 | dataframe["EWO"] = EWO(dataframe, self.fast_ewo.value, self.slow_ewo.value) 184 | 185 | # RSI 186 | dataframe["rsi"] = ta.RSI(dataframe, timeperiod=14) 187 | 188 | return dataframe 189 | 190 | def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: 191 | conditions = [] 192 | dataframe["ma_buy"] = ( 193 | dataframe[f"ma_buy_{self.base_nb_candles_buy.value}"] 194 | * self.low_offset.value 195 | ) 196 | 197 | conditions.append( 198 | ( 199 | # (dataframe['close'].shift(1) < dataframe['ma_buy']) & 200 | # (dataframe['low'] < dataframe['ma_buy']) & 201 | # (dataframe['close'] > dataframe['ma_buy']) & 202 | # (qtpylib.crossed_above(dataframe['close'], dataframe['ma_buy'])) & 203 | (dataframe["close"] < dataframe["ma_buy"]) 204 | & (dataframe["EWO"] > self.ewo_high.value) 205 | & (dataframe["rsi"] < self.rsi_buy.value) 206 | & (dataframe["volume"] > 0) 207 | ) 208 | ) 209 | 210 | conditions.append( 211 | ( 212 | # (dataframe['close'].shift(1) < dataframe['ma_buy']) & 213 | # (dataframe['low'] < dataframe['ma_buy']) & 214 | # (dataframe['close'] > dataframe['ma_buy']) & 215 | # (qtpylib.crossed_above(dataframe['close'], dataframe['ma_buy'])) & 216 | (dataframe["close"] < dataframe["ma_buy"]) 217 | & (dataframe["EWO"] < self.ewo_low.value) 218 | & (dataframe["volume"] > 0) 219 | ) 220 | ) 221 | 222 | if conditions: 223 | dataframe.loc[reduce(lambda x, y: x | y, conditions), "buy"] = 1 224 | 225 | return dataframe 226 | 227 | def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: 228 | conditions = [] 229 | dataframe["ma_sell"] = ( 230 | dataframe[f"ma_sell_{self.base_nb_candles_sell.value}"] 231 | * self.high_offset.value 232 | ) 233 | conditions.append( 234 | ( 235 | # (dataframe['close'] > (dataframe[f'ma_sell_{self.base_nb_candles_sell.value}'] * self.high_offset.value)) & 236 | (qtpylib.crossed_below(dataframe["close"], dataframe["ma_sell"])) 237 | & (dataframe["volume"] > 0) 238 | ) 239 | ) 240 | 241 | if conditions: 242 | dataframe.loc[reduce(lambda x, y: x | y, conditions), "sell"] = 1 243 | 244 | return dataframe 245 | -------------------------------------------------------------------------------- /user_data/strategies/Obelisk_3EMA_StochRSI_ATR.py: -------------------------------------------------------------------------------- 1 | # --- Do not remove these libs --- 2 | from freqtrade.strategy import IStrategy, merge_informative_pair 3 | from pandas import DataFrame 4 | import talib.abstract as ta 5 | import freqtrade.vendor.qtpylib.indicators as qtpylib 6 | 7 | # -------------------------------- 8 | import pandas as pd 9 | import numpy as np 10 | import logging 11 | from datetime import datetime, timedelta 12 | import technical.indicators as ftt 13 | from freqtrade.strategy import stoploss_from_open 14 | from freqtrade.exchange import timeframe_to_minutes 15 | 16 | logger = logging.getLogger(__name__) 17 | 18 | # Obelisk_3EMA_StochRSI_ATR - 2021-04-10 19 | # 20 | # by Obelisk 21 | # https://github.com/brookmiles/ 22 | # 23 | # DO NOT RUN LIVE 24 | # 25 | # based on Trade Pro "76% Win Rate Highly Profitable Trading Strategy Proven 100 Trades - 3 EMA + Stochastic RSI + ATR" 26 | # https://www.youtube.com/watch?v=7NM7bR2mL7U 27 | # 28 | # correctness/accuracy not guaranteed 29 | # 30 | # WARNING 31 | # 32 | # While this strategy is designed to be run at 1h, it should be backtested at 5m (or 1m). 33 | # This is done to avoid misleading results produced using trailing stops and roi values at longer timeframes. 34 | # 35 | # When running at 5m, an informative pair at 1h will be used to generate signals equivalent to running at 1h. 36 | # 37 | # live / dryrun: use 1h 38 | # backtest / hyperopt: use 5m or 1m 39 | 40 | class Obelisk_3EMA_StochRSI_ATR(IStrategy): 41 | 42 | # Backtest or hyperopt at this timeframe 43 | timeframe = '5m' 44 | 45 | # Live or Dry-run at this timeframe 46 | informative_timeframe = '1h' 47 | 48 | startup_candle_count = 500 49 | 50 | # NOTE: this strat only uses candle information, so processing between 51 | # new candles is a waste of resources as nothing will change 52 | process_only_new_candles = True 53 | 54 | minimal_roi = { 55 | "0": 1, 56 | } 57 | 58 | stoploss = -0.99 59 | use_custom_stoploss = True 60 | 61 | custom_info = {} 62 | 63 | def informative_pairs(self): 64 | pairs = self.dp.current_whitelist() 65 | informative_pairs = [(pair, self.informative_timeframe) for pair in pairs] 66 | return informative_pairs 67 | 68 | def do_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: 69 | 70 | dataframe['ema8'] = ta.EMA(dataframe, timeperiod=8) 71 | dataframe['ema14'] = ta.EMA(dataframe, timeperiod=14) 72 | dataframe['ema50'] = ta.EMA(dataframe, timeperiod=50) 73 | 74 | dataframe['atr'] = ta.ATR(dataframe, timeperiod=14) 75 | 76 | #RSI 77 | dataframe['rsi'] = ta.RSI(dataframe, timeperiod=14) 78 | 79 | #StochRSI 80 | period = 14 81 | smoothD = 3 82 | SmoothK = 3 83 | stochrsi = (dataframe['rsi'] - dataframe['rsi'].rolling(period).min()) / (dataframe['rsi'].rolling(period).max() - dataframe['rsi'].rolling(period).min()) 84 | dataframe['srsi_k'] = stochrsi.rolling(SmoothK).mean() * 100 85 | dataframe['srsi_d'] = dataframe['srsi_k'].rolling(smoothD).mean() 86 | 87 | dataframe.loc[ 88 | (dataframe['ema8'] > dataframe['ema14']) & 89 | (dataframe['ema14'] > dataframe['ema50']) & 90 | qtpylib.crossed_above(dataframe['srsi_k'], dataframe['srsi_d']) 91 | , 92 | 'go_long'] = 1 93 | dataframe['go_long'].fillna(0, inplace=True) 94 | 95 | dataframe.loc[ 96 | qtpylib.crossed_above(dataframe['go_long'], 0), 97 | 'take_profit'] = dataframe['close'] + dataframe['atr'] * 2 98 | dataframe['take_profit'].fillna(method='ffill', inplace=True) 99 | 100 | dataframe.loc[ 101 | qtpylib.crossed_above(dataframe['go_long'], 0), 102 | 'stop_loss'] = dataframe['close'] - dataframe['atr'] * 3 103 | dataframe['stop_loss'].fillna(method='ffill', inplace=True) 104 | 105 | dataframe.loc[ 106 | qtpylib.crossed_above(dataframe['go_long'], 0), 107 | 'stop_pct'] = (dataframe['atr'] * 3) / dataframe['close'] 108 | dataframe['stop_pct'].fillna(method='ffill', inplace=True) 109 | 110 | # add indicator mapped to correct DatetimeIndex to custom_info 111 | self.custom_info[metadata['pair']] = dataframe[['date', 'stop_pct', 'take_profit']].copy().set_index('date') 112 | 113 | return dataframe 114 | 115 | def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: 116 | 117 | if self.config['runmode'].value in ('backtest', 'hyperopt'): 118 | assert (timeframe_to_minutes(self.timeframe) <= 5), "Backtest this strategy in 5m or 1m timeframe." 119 | 120 | if self.timeframe == self.informative_timeframe: 121 | dataframe = self.do_indicators(dataframe, metadata) 122 | else: 123 | if not self.dp: 124 | return dataframe 125 | 126 | informative = self.dp.get_pair_dataframe(pair=metadata['pair'], timeframe=self.informative_timeframe) 127 | 128 | informative = self.do_indicators(informative.copy(), metadata) 129 | 130 | dataframe = merge_informative_pair(dataframe, informative, self.timeframe, self.informative_timeframe, ffill=True) 131 | # don't overwrite the base dataframe's OHLCV information 132 | skip_columns = [(s + "_" + self.informative_timeframe) for s in ['date', 'open', 'high', 'low', 'close', 'volume']] 133 | dataframe.rename(columns=lambda s: s.replace("_{}".format(self.informative_timeframe), "") if (not s in skip_columns) else s, inplace=True) 134 | 135 | return dataframe 136 | 137 | def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: 138 | 139 | dataframe.loc[ 140 | qtpylib.crossed_above(dataframe['go_long'], 0) 141 | , 142 | 'buy'] = 1 143 | 144 | return dataframe 145 | 146 | def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: 147 | 148 | dataframe['sell'] = 0 149 | 150 | return dataframe 151 | 152 | def custom_stoploss(self, pair: str, trade: 'Trade', current_time: datetime, 153 | current_rate: float, current_profit: float, **kwargs) -> float: 154 | 155 | result = 1 156 | 157 | custom_info_pair = self.custom_info[pair] 158 | if custom_info_pair is not None: 159 | # using current_time/open_date directly will only work in backtesting/hyperopt. 160 | # in live / dry-run, we have to search for nearest row before 161 | tz = custom_info_pair.index.tz 162 | open_date = trade.open_date_utc if hasattr(trade, 'open_date_utc') else trade.open_date.replace(tzinfo=custom_info_pair.index.tz) 163 | open_date_mask = custom_info_pair.index.unique().get_loc(open_date, method='ffill') 164 | open_df = custom_info_pair.iloc[open_date_mask] 165 | 166 | # trade might be open too long for us to find opening candle 167 | if(open_df is None or len(open_df) == 0): 168 | logger.debug("No open_df :(") 169 | return 1 # oh well 170 | 171 | # stop out if we have reached our take profit limit 172 | take_profit = open_df['take_profit'] 173 | if (take_profit is not None): 174 | if current_rate > take_profit: 175 | logger.debug("take_profit={}, current={}".format( 176 | take_profit, 177 | current_rate 178 | )) 179 | return 0.001 180 | 181 | # keep trailing stoploss at -stop_pct from the open price 182 | stop_pct = open_df['stop_pct'] 183 | if (stop_pct is not None): 184 | new_stop = stoploss_from_open(-stop_pct, current_profit) 185 | logger.debug("open={}, current={}, profit={}, stop_pct={}, stop={}".format( 186 | current_rate / (1 + current_profit), 187 | current_rate, 188 | current_profit, 189 | stop_pct, 190 | current_rate * (1 - new_stop))) 191 | if new_stop > 0: 192 | result = new_stop 193 | 194 | return result 195 | 196 | plot_config = { 197 | 'main_plot': { 198 | 'ema50': { 'color': 'orange' }, 199 | 'ema14': { 'color': 'blue' }, 200 | 'ema8': { 'color': 'purple' }, 201 | 'take_profit': { 'color': 'green' }, 202 | 'stop_loss': { 'color': 'red' }, 203 | }, 204 | 'subplots': { 205 | "SRSI": { 206 | 'srsi_k': {'color': 'blue'}, 207 | 'srsi_d': {'color': 'red'}, 208 | }, 209 | "ATR": { 210 | 'atr': {'color': 'blue'}, 211 | }, 212 | } 213 | } 214 | -------------------------------------------------------------------------------- /user_data/strategies/NostalgiaForInfinityV1.py: -------------------------------------------------------------------------------- 1 | import freqtrade.vendor.qtpylib.indicators as qtpylib 2 | import numpy as np 3 | import talib.abstract as ta 4 | from freqtrade.strategy.interface import IStrategy 5 | from pandas import DataFrame 6 | from freqtrade.strategy import merge_informative_pair 7 | from freqtrade.persistence import Trade 8 | 9 | 10 | ########################################################################################################### 11 | ## NostalgiaForInfinityV1 by iterativ ## 12 | ## ## 13 | ## Strategy for Freqtrade https://github.com/freqtrade/freqtrade ## 14 | ## ## 15 | ########################################################################################################### 16 | ## GENERAL RECOMMENDATIONS ## 17 | ## ## 18 | ## For optimal performance, suggested to use between 4 and 6 open trades, with unlimited stake. ## 19 | ## A pairlist with 20 to 60 pairs. Volume pairlist works well. ## 20 | ## Prefer stable coin (USDT, BUSDT etc) pairs, instead of BTC or ETH pairs. ## 21 | ## Highly recommended to blacklist leveraged tokens (*BULL, *BEAR, *UP, *DOWN etc). ## 22 | ## Ensure that you don't override any variables in you config.json. Especially ## 23 | ## the timeframe (must be 5m). ## 24 | ## ## 25 | ########################################################################################################### 26 | ## DONATIONS ## 27 | ## ## 28 | ## Absolutely not required. However, will be accepted as a token of appreciation. ## 29 | ## ## 30 | ## BTC: bc1qvflsvddkmxh7eqhc4jyu5z5k6xcw3ay8jl49sk ## 31 | ## ETH: 0x83D3cFb8001BDC5d2211cBeBB8cB3461E5f7Ec91 ## 32 | ## ## 33 | ########################################################################################################### 34 | 35 | 36 | # SSL Channels 37 | def SSLChannels(dataframe, length = 7): 38 | df = dataframe.copy() 39 | df['ATR'] = ta.ATR(df, timeperiod=14) 40 | df['smaHigh'] = df['high'].rolling(length).mean() + df['ATR'] 41 | df['smaLow'] = df['low'].rolling(length).mean() - df['ATR'] 42 | df['hlv'] = np.where(df['close'] > df['smaHigh'], 1, np.where(df['close'] < df['smaLow'], -1, np.NAN)) 43 | df['hlv'] = df['hlv'].ffill() 44 | df['sslDown'] = np.where(df['hlv'] < 0, df['smaHigh'], df['smaLow']) 45 | df['sslUp'] = np.where(df['hlv'] < 0, df['smaLow'], df['smaHigh']) 46 | return df['sslDown'], df['sslUp'] 47 | 48 | class NostalgiaForInfinityV1(IStrategy): 49 | INTERFACE_VERSION = 2 50 | 51 | minimal_roi = { 52 | "0": 0.25 53 | } 54 | 55 | stoploss = -0.36 56 | 57 | timeframe = '5m' 58 | inf_1h = '1h' 59 | 60 | custom_info = {} 61 | 62 | # Sell signal 63 | use_sell_signal = True 64 | sell_profit_only = False 65 | sell_profit_offset = 0.001 # it doesn't meant anything, just to guarantee there is a minimal profit. 66 | ignore_roi_if_buy_signal = True 67 | 68 | # Trailing stoploss 69 | trailing_stop = True 70 | trailing_only_offset_is_reached = True 71 | trailing_stop_positive = 0.02 72 | trailing_stop_positive_offset = 0.3 73 | 74 | # Custom stoploss 75 | use_custom_stoploss = False 76 | 77 | # Run "populate_indicators()" only for new candle. 78 | process_only_new_candles = False 79 | 80 | # Number of candles the strategy requires before producing valid signals 81 | startup_candle_count: int = 200 82 | 83 | # Optional order type mapping. 84 | order_types = { 85 | 'buy': 'limit', 86 | 'sell': 'limit', 87 | 'stoploss': 'market', 88 | 'stoploss_on_exchange': False 89 | } 90 | 91 | def confirm_trade_exit(self, pair: str, trade: Trade, order_type: str, amount: float, 92 | rate: float, time_in_force: str, sell_reason: str, **kwargs) -> bool: 93 | dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe) 94 | last_candle = dataframe.iloc[-1].squeeze() 95 | # Prevent ROI trigger, if there is more potential, in order to maximize profit 96 | if (sell_reason == 'roi') & (last_candle['rsi'] > 50): 97 | return False 98 | return True 99 | 100 | def informative_pairs(self): 101 | pairs = self.dp.current_whitelist() 102 | informative_pairs = [(pair, '1h') for pair in pairs] 103 | return informative_pairs 104 | 105 | def informative_1h_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: 106 | assert self.dp, "DataProvider is required for multiple timeframes." 107 | # Get the informative pair 108 | informative_1h = self.dp.get_pair_dataframe(pair=metadata['pair'], timeframe=self.inf_1h) 109 | # EMA 110 | informative_1h['ema_20'] = ta.EMA(informative_1h, timeperiod=20) 111 | informative_1h['ema_50'] = ta.EMA(informative_1h, timeperiod=50) 112 | informative_1h['ema_200'] = ta.EMA(informative_1h, timeperiod=200) 113 | # RSI 114 | informative_1h['rsi'] = ta.RSI(informative_1h, timeperiod=14) 115 | # SSL Channels 116 | ssl_down_1h, ssl_up_1h = SSLChannels(informative_1h, 20) 117 | informative_1h['ssl_down'] = ssl_down_1h 118 | informative_1h['ssl_up'] = ssl_up_1h 119 | 120 | return informative_1h 121 | 122 | def normal_tf_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: 123 | bb_40 = qtpylib.bollinger_bands(dataframe['close'], window=40, stds=2) 124 | dataframe['lower'] = bb_40['lower'] 125 | dataframe['mid'] = bb_40['mid'] 126 | dataframe['bbdelta'] = (bb_40['mid'] - dataframe['lower']).abs() 127 | dataframe['closedelta'] = (dataframe['close'] - dataframe['close'].shift()).abs() 128 | dataframe['tail'] = (dataframe['close'] - dataframe['low']).abs() 129 | 130 | bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=2) 131 | dataframe['bb_lowerband'] = bollinger['lower'] 132 | dataframe['bb_middleband'] = bollinger['mid'] 133 | dataframe['bb_upperband'] = bollinger['upper'] 134 | dataframe['ema_slow'] = ta.EMA(dataframe, timeperiod=50) 135 | dataframe['volume_mean_slow'] = dataframe['volume'].rolling(window=30).mean() 136 | 137 | # EMA 138 | dataframe['ema_50'] = ta.EMA(dataframe, timeperiod=50) 139 | dataframe['ema_200'] = ta.EMA(dataframe, timeperiod=200) 140 | 141 | # SMA 142 | dataframe['sma_5'] = ta.EMA(dataframe, timeperiod=5) 143 | dataframe['sma_9'] = ta.EMA(dataframe, timeperiod=9) 144 | 145 | # RSI 146 | dataframe['rsi'] = ta.RSI(dataframe, timeperiod=14) 147 | 148 | return dataframe 149 | 150 | def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: 151 | # The indicators for the 1h informative timeframe 152 | informative_1h = self.informative_1h_indicators(dataframe, metadata) 153 | dataframe = merge_informative_pair(dataframe, informative_1h, self.timeframe, self.inf_1h, ffill=True) 154 | 155 | # The indicators for the normal (5m) timeframe 156 | dataframe = self.normal_tf_indicators(dataframe, metadata) 157 | 158 | return dataframe 159 | 160 | def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: 161 | dataframe.loc[ 162 | ( 163 | (dataframe['close'] < dataframe['sma_9']) & 164 | (dataframe['close'] > dataframe['ema_200_1h']) & 165 | (dataframe['ema_50'] > dataframe['ema_200']) & 166 | (dataframe['ema_50_1h'] > dataframe['ema_200_1h']) & 167 | 168 | dataframe['lower'].shift().gt(0) & 169 | dataframe['bbdelta'].gt(dataframe['close'] * 0.045) & 170 | dataframe['closedelta'].gt(dataframe['close'] * 0.023) & 171 | dataframe['tail'].lt(dataframe['bbdelta'] * 0.266) & 172 | dataframe['close'].lt(dataframe['lower'].shift()) & 173 | dataframe['close'].le(dataframe['close'].shift()) & 174 | (dataframe['volume'] > 0) 175 | ) 176 | | 177 | ( 178 | (dataframe['close'] < dataframe['sma_9']) & 179 | (dataframe['close'] > dataframe['ema_200']) & 180 | (dataframe['close'] > dataframe['ema_200_1h']) & 181 | 182 | (dataframe['close'] < dataframe['ema_slow']) & 183 | (dataframe['close'] < 0.992 * dataframe['bb_lowerband']) & 184 | (dataframe['volume'] < (dataframe['volume_mean_slow'].shift(1) * 34)) 185 | ) 186 | | 187 | ( 188 | (dataframe['close'] < dataframe['sma_5']) & 189 | (dataframe['ssl_up_1h'] > dataframe['ssl_down_1h']) & 190 | (dataframe['ema_50'] > dataframe['ema_200']) & 191 | (dataframe['ema_50_1h'] > dataframe['ema_200_1h']) & 192 | 193 | (dataframe['rsi'] < dataframe['rsi_1h'] - 36.815) & 194 | (dataframe['volume'] > 0) 195 | ) 196 | , 197 | 'buy' 198 | ] = 1 199 | return dataframe 200 | 201 | def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: 202 | dataframe.loc[ 203 | ( 204 | (dataframe['close'] > dataframe['bb_upperband']) & 205 | (dataframe['close'].shift(1) > dataframe['bb_upperband'].shift(1)) & 206 | (dataframe['close'].shift(2) > dataframe['bb_upperband'].shift(2)) & 207 | (dataframe['volume'] > 0) 208 | ) 209 | | 210 | ( 211 | (dataframe['rsi'] > 78) & 212 | (dataframe['volume'] > 0) 213 | ) 214 | | 215 | ( 216 | (dataframe['close'] < dataframe['ema_200']) & 217 | (dataframe['close'] > dataframe['ema_50']) & 218 | (dataframe['rsi'] > 50) & 219 | (dataframe['volume'] > 0) 220 | ) 221 | , 222 | 'sell' 223 | ] = 1 224 | return dataframe 225 | -------------------------------------------------------------------------------- /user_data/strategies/Elliot.py: -------------------------------------------------------------------------------- 1 | # --- Do not remove these libs --- 2 | from freqtrade.strategy.interface import IStrategy 3 | from typing import Dict, List 4 | from functools import reduce 5 | from pandas import DataFrame 6 | 7 | # -------------------------------- 8 | import talib.abstract as ta 9 | import numpy as np 10 | import freqtrade.vendor.qtpylib.indicators as qtpylib 11 | import datetime 12 | from technical.util import resample_to_interval, resampled_merge 13 | from datetime import datetime, timedelta 14 | from freqtrade.persistence import Trade 15 | from freqtrade.strategy import ( 16 | stoploss_from_open, 17 | merge_informative_pair, 18 | DecimalParameter, 19 | IntParameter, 20 | CategoricalParameter, 21 | ) 22 | 23 | import technical.indicators as ftt 24 | 25 | # @Rallipanos 26 | 27 | # Buy hyperspace params: 28 | buy_params = { 29 | "base_nb_candles_buy": 14, 30 | "ewo_high": 2.327, 31 | "ewo_low": -19.988, 32 | "low_offset": 0.975, 33 | "rsi_buy": 69, 34 | } 35 | 36 | # Sell hyperspace params: 37 | sell_params = {"base_nb_candles_sell": 24, "high_offset": 0.991, "high_offset_2": 0.997} 38 | 39 | 40 | def EWO(dataframe, ema_length=5, ema2_length=35): 41 | df = dataframe.copy() 42 | ema1 = ta.EMA(df, timeperiod=ema_length) 43 | ema2 = ta.EMA(df, timeperiod=ema2_length) 44 | emadif = (ema1 - ema2) / df["close"] * 100 45 | return emadif 46 | 47 | 48 | class Elliot(IStrategy): 49 | INTERFACE_VERSION = 2 50 | 51 | # ROI table: 52 | minimal_roi = {"0": 0.051, "10": 0.031, "22": 0.018, "66": 0} 53 | 54 | # Stoploss: 55 | stoploss = -0.32 56 | 57 | # SMAOffset 58 | base_nb_candles_buy = IntParameter( 59 | 5, 80, default=buy_params["base_nb_candles_buy"], space="buy", optimize=True 60 | ) 61 | base_nb_candles_sell = IntParameter( 62 | 5, 80, default=sell_params["base_nb_candles_sell"], space="sell", optimize=True 63 | ) 64 | low_offset = DecimalParameter( 65 | 0.9, 0.99, default=buy_params["low_offset"], space="buy", optimize=True 66 | ) 67 | high_offset = DecimalParameter( 68 | 0.95, 1.1, default=sell_params["high_offset"], space="sell", optimize=True 69 | ) 70 | high_offset_2 = DecimalParameter( 71 | 0.99, 1.5, default=sell_params["high_offset_2"], space="sell", optimize=True 72 | ) 73 | 74 | # Protection 75 | fast_ewo = 50 76 | slow_ewo = 200 77 | ewo_low = DecimalParameter( 78 | -20.0, -8.0, default=buy_params["ewo_low"], space="buy", optimize=True 79 | ) 80 | ewo_high = DecimalParameter( 81 | 2.0, 12.0, default=buy_params["ewo_high"], space="buy", optimize=True 82 | ) 83 | rsi_buy = IntParameter( 84 | 30, 70, default=buy_params["rsi_buy"], space="buy", optimize=True 85 | ) 86 | 87 | # Trailing stop: 88 | trailing_stop = True 89 | trailing_stop_positive = 0.005 90 | trailing_stop_positive_offset = 0.03 91 | trailing_only_offset_is_reached = True 92 | 93 | # Sell signal 94 | use_sell_signal = True 95 | sell_profit_only = False 96 | sell_profit_offset = 0.01 97 | ignore_roi_if_buy_signal = False 98 | 99 | ## Optional order time in force. 100 | order_time_in_force = {"buy": "gtc", "sell": "gtc"} 101 | 102 | # Optimal timeframe for the strategy 103 | timeframe = "5m" 104 | inf_1h = "1h" 105 | 106 | process_only_new_candles = True 107 | startup_candle_count = 39 108 | 109 | plot_config = { 110 | "main_plot": { 111 | "sma_9": {"color": "#736581"}, 112 | "hma_50": {"color": "#a9d"}, 113 | "ma_buy": {"color": "bule"}, 114 | "ma_sell": {"color": "orange"}, 115 | "ma_sell_2": {"color": "red"}, 116 | }, 117 | 118 | 'subplots': { 119 | "EWO": { 120 | 'EWO': {'color': 'blue'}, 121 | }, 122 | "RSI": { 123 | 'rsi': {'color': 'blue'}, 124 | 'rsi_fast': {'color': 'red'}, 125 | 'rsi_slow': {'color': 'orange'}, 126 | }, 127 | 128 | "TREND": { 129 | 'uptrend_1h': {'color': 'blue'}, 130 | }, 131 | 132 | } 133 | 134 | } 135 | 136 | use_custom_stoploss = False 137 | 138 | def custom_stoploss( 139 | self, 140 | pair: str, 141 | trade: "Trade", 142 | current_time: datetime, 143 | current_rate: float, 144 | current_profit: float, 145 | **kwargs, 146 | ) -> float: 147 | 148 | if ( 149 | current_profit < -0.1 150 | and current_time - timedelta(minutes=720) > trade.open_date_utc 151 | ): 152 | return -0.01 153 | 154 | return -0.99 155 | 156 | def informative_pairs(self): 157 | # get access to all pairs available in whitelist. 158 | pairs = self.dp.current_whitelist() 159 | # Assign tf to each pair so they can be downloaded and cached for strategy. 160 | informative_pairs = [(pair, "1h") for pair in pairs] 161 | return informative_pairs 162 | 163 | def informative_1h_indicators( 164 | self, dataframe: DataFrame, metadata: dict 165 | ) -> DataFrame: 166 | assert self.dp, "DataProvider is required for multiple timeframes." 167 | # Get the informative pair 168 | informative_1h = self.dp.get_pair_dataframe( 169 | pair=metadata["pair"], timeframe=self.inf_1h 170 | ) 171 | 172 | informative_1h["ema_fast"] = ta.EMA(informative_1h, timeperiod=20) 173 | informative_1h["ema_slow"] = ta.EMA(informative_1h, timeperiod=25) 174 | 175 | informative_1h["uptrend"] = ( 176 | (informative_1h["ema_fast"] > informative_1h["ema_slow"]) 177 | ).astype("int") 178 | informative_1h["rsi_100"] = ta.RSI(informative_1h, timeperiod=100) 179 | return informative_1h 180 | 181 | def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: 182 | informative_1h = self.informative_1h_indicators(dataframe, metadata) 183 | dataframe = merge_informative_pair( 184 | dataframe, informative_1h, self.timeframe, self.inf_1h, ffill=True 185 | ) 186 | # Calculate all ma_buy values 187 | for val in self.base_nb_candles_buy.range: 188 | dataframe[f"ma_buy_{val}"] = ta.EMA(dataframe, timeperiod=val) 189 | bollinger = qtpylib.bollinger_bands( 190 | qtpylib.typical_price(dataframe), window=20, stds=2 191 | ) 192 | dataframe["bb_upperband"] = bollinger["upper"] 193 | dataframe["bb_lowerband"] = bollinger["lower"] 194 | # Calculate all ma_sell values 195 | for val in self.base_nb_candles_sell.range: 196 | dataframe[f"ma_sell_{val}"] = ta.EMA(dataframe, timeperiod=val) 197 | 198 | dataframe["hma_50"] = qtpylib.hull_moving_average(dataframe["close"], window=50) 199 | 200 | # dataframe['hma_50']=hmao 201 | dataframe["sma_9"] = ta.SMA(dataframe, timeperiod=9) 202 | # Elliot 203 | dataframe["EWO"] = EWO(dataframe, self.fast_ewo, self.slow_ewo) 204 | 205 | macd = ta.MACD(dataframe) 206 | dataframe["macd"] = macd["macd"] 207 | dataframe["macdsignal"] = macd["macdsignal"] 208 | # RSI 209 | dataframe["rsi"] = ta.RSI(dataframe, timeperiod=14) 210 | dataframe["rsi_fast"] = ta.RSI(dataframe, timeperiod=4) 211 | dataframe["rsi_slow"] = ta.RSI(dataframe, timeperiod=20) 212 | dataframe["rsi_100"] = ta.RSI(dataframe, timeperiod=100) 213 | 214 | dataframe["ma_buy"] = ta.EMA(dataframe, int(self.base_nb_candles_buy.value)) * self.low_offset.value 215 | dataframe["ma_sell"] = ta.EMA(dataframe, int(self.base_nb_candles_sell.value)) * self.high_offset.value 216 | dataframe["ma_sell_2"] = ta.EMA(dataframe, int(self.base_nb_candles_sell.value)) * self.high_offset_2.value 217 | 218 | 219 | 220 | 221 | return dataframe 222 | 223 | def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: 224 | conditions = [] 225 | 226 | dataframe.loc[ 227 | ( 228 | (dataframe["uptrend_1h"] > 0) 229 | & (dataframe["rsi_fast"] < 35) 230 | & ( 231 | dataframe["close"] 232 | < ( 233 | dataframe[f"ma_buy_{self.base_nb_candles_buy.value}"] 234 | * self.low_offset.value 235 | ) 236 | ) 237 | & (dataframe["EWO"] > self.ewo_high.value) 238 | & (dataframe["rsi"] < self.rsi_buy.value) 239 | & (dataframe["volume"] > 0) 240 | & ( 241 | dataframe["close"] 242 | < ( 243 | dataframe[f"ma_sell_{self.base_nb_candles_sell.value}"] 244 | * self.high_offset.value 245 | ) 246 | ) 247 | ), 248 | ["buy", "buy_tag"], 249 | ] = (1, "buy_signal_1") 250 | 251 | dataframe.loc[ 252 | ( 253 | (dataframe["uptrend_1h"] > 0) 254 | & (dataframe["rsi_fast"] < 35) 255 | & ( 256 | dataframe["close"] 257 | < ( 258 | dataframe[f"ma_buy_{self.base_nb_candles_buy.value}"] 259 | * self.low_offset.value 260 | ) 261 | ) 262 | & (dataframe["EWO"] < self.ewo_low.value) 263 | & (dataframe["volume"] > 0) 264 | & ( 265 | dataframe["close"] 266 | < ( 267 | dataframe[f"ma_sell_{self.base_nb_candles_sell.value}"] 268 | * self.high_offset.value 269 | ) 270 | ) 271 | ), 272 | ["buy", "buy_tag"], 273 | ] = (1, "buy_signal_2") 274 | 275 | # if conditions: 276 | # dataframe.loc[reduce(lambda x, y: x | y, conditions), "buy"] = 1 277 | 278 | return dataframe 279 | 280 | def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: 281 | conditions = [] 282 | 283 | conditions.append( 284 | ( 285 | (dataframe["sma_9"] > dataframe["hma_50"]) 286 | & ( 287 | dataframe["close"] 288 | > ( 289 | dataframe[f"ma_sell_{self.base_nb_candles_sell.value}"] 290 | * self.high_offset_2.value 291 | ) 292 | ) 293 | & (dataframe["rsi"] > 50) 294 | & (dataframe["volume"] > 0) 295 | & (dataframe["rsi_fast"] > dataframe["rsi_slow"]) 296 | ) 297 | ) 298 | 299 | conditions.append( 300 | ( 301 | (dataframe["sma_9"] < dataframe["hma_50"]) 302 | & ( 303 | dataframe["close"] 304 | > ( 305 | dataframe[f"ma_sell_{self.base_nb_candles_sell.value}"] 306 | * self.high_offset.value 307 | ) 308 | ) 309 | & (dataframe["volume"] > 0) 310 | & (dataframe["rsi_fast"] > dataframe["rsi_slow"]) 311 | ) 312 | ) 313 | 314 | if conditions: 315 | dataframe.loc[reduce(lambda x, y: x | y, conditions), "sell"] = 1 316 | 317 | return dataframe 318 | -------------------------------------------------------------------------------- /user_data/hyperopts/sample_hyperopt_advanced.py: -------------------------------------------------------------------------------- 1 | # pragma pylint: disable=missing-docstring, invalid-name, pointless-string-statement 2 | # isort: skip_file 3 | # --- Do not remove these libs --- 4 | from functools import reduce 5 | from typing import Any, Callable, Dict, List 6 | 7 | import numpy as np # noqa 8 | import pandas as pd # noqa 9 | from pandas import DataFrame 10 | from freqtrade.optimize.space import Categorical, Dimension, Integer, SKDecimal, Real # noqa 11 | 12 | from freqtrade.optimize.hyperopt_interface import IHyperOpt 13 | 14 | # -------------------------------- 15 | # Add your lib to import here 16 | import talib.abstract as ta # noqa 17 | import freqtrade.vendor.qtpylib.indicators as qtpylib 18 | 19 | 20 | class AdvancedSampleHyperOpt(IHyperOpt): 21 | """ 22 | This is a sample hyperopt to inspire you. 23 | Feel free to customize it. 24 | 25 | More information in the documentation: https://www.freqtrade.io/en/latest/hyperopt/ 26 | 27 | You should: 28 | - Rename the class name to some unique name. 29 | - Add any methods you want to build your hyperopt. 30 | - Add any lib you need to build your hyperopt. 31 | 32 | You must keep: 33 | - The prototypes for the methods: populate_indicators, indicator_space, buy_strategy_generator. 34 | 35 | The methods roi_space, generate_roi_table and stoploss_space are not required 36 | and are provided by default. 37 | However, you may override them if you need the 38 | 'roi' and the 'stoploss' spaces that differ from the defaults offered by Freqtrade. 39 | 40 | This sample illustrates how to override these methods. 41 | """ 42 | @staticmethod 43 | def populate_indicators(dataframe: DataFrame, metadata: dict) -> DataFrame: 44 | """ 45 | This method can also be loaded from the strategy, if it doesn't exist in the hyperopt class. 46 | """ 47 | dataframe['adx'] = ta.ADX(dataframe) 48 | macd = ta.MACD(dataframe) 49 | dataframe['macd'] = macd['macd'] 50 | dataframe['macdsignal'] = macd['macdsignal'] 51 | dataframe['mfi'] = ta.MFI(dataframe) 52 | dataframe['rsi'] = ta.RSI(dataframe) 53 | stoch_fast = ta.STOCHF(dataframe) 54 | dataframe['fastd'] = stoch_fast['fastd'] 55 | dataframe['minus_di'] = ta.MINUS_DI(dataframe) 56 | # Bollinger bands 57 | bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=2) 58 | dataframe['bb_lowerband'] = bollinger['lower'] 59 | dataframe['bb_upperband'] = bollinger['upper'] 60 | dataframe['sar'] = ta.SAR(dataframe) 61 | return dataframe 62 | 63 | @staticmethod 64 | def indicator_space() -> List[Dimension]: 65 | """ 66 | Define your Hyperopt space for searching buy strategy parameters. 67 | """ 68 | return [ 69 | Integer(10, 25, name='mfi-value'), 70 | Integer(15, 45, name='fastd-value'), 71 | Integer(20, 50, name='adx-value'), 72 | Integer(20, 40, name='rsi-value'), 73 | Categorical([True, False], name='mfi-enabled'), 74 | Categorical([True, False], name='fastd-enabled'), 75 | Categorical([True, False], name='adx-enabled'), 76 | Categorical([True, False], name='rsi-enabled'), 77 | Categorical(['bb_lower', 'macd_cross_signal', 'sar_reversal'], name='trigger') 78 | ] 79 | 80 | @staticmethod 81 | def buy_strategy_generator(params: Dict[str, Any]) -> Callable: 82 | """ 83 | Define the buy strategy parameters to be used by hyperopt 84 | """ 85 | def populate_buy_trend(dataframe: DataFrame, metadata: dict) -> DataFrame: 86 | """ 87 | Buy strategy Hyperopt will build and use 88 | """ 89 | conditions = [] 90 | # GUARDS AND TRENDS 91 | if 'mfi-enabled' in params and params['mfi-enabled']: 92 | conditions.append(dataframe['mfi'] < params['mfi-value']) 93 | if 'fastd-enabled' in params and params['fastd-enabled']: 94 | conditions.append(dataframe['fastd'] < params['fastd-value']) 95 | if 'adx-enabled' in params and params['adx-enabled']: 96 | conditions.append(dataframe['adx'] > params['adx-value']) 97 | if 'rsi-enabled' in params and params['rsi-enabled']: 98 | conditions.append(dataframe['rsi'] < params['rsi-value']) 99 | 100 | # TRIGGERS 101 | if 'trigger' in params: 102 | if params['trigger'] == 'bb_lower': 103 | conditions.append(dataframe['close'] < dataframe['bb_lowerband']) 104 | if params['trigger'] == 'macd_cross_signal': 105 | conditions.append(qtpylib.crossed_above( 106 | dataframe['macd'], dataframe['macdsignal'] 107 | )) 108 | if params['trigger'] == 'sar_reversal': 109 | conditions.append(qtpylib.crossed_above( 110 | dataframe['close'], dataframe['sar'] 111 | )) 112 | 113 | # Check that volume is not 0 114 | conditions.append(dataframe['volume'] > 0) 115 | 116 | if conditions: 117 | dataframe.loc[ 118 | reduce(lambda x, y: x & y, conditions), 119 | 'buy'] = 1 120 | 121 | return dataframe 122 | 123 | return populate_buy_trend 124 | 125 | @staticmethod 126 | def sell_indicator_space() -> List[Dimension]: 127 | """ 128 | Define your Hyperopt space for searching sell strategy parameters. 129 | """ 130 | return [ 131 | Integer(75, 100, name='sell-mfi-value'), 132 | Integer(50, 100, name='sell-fastd-value'), 133 | Integer(50, 100, name='sell-adx-value'), 134 | Integer(60, 100, name='sell-rsi-value'), 135 | Categorical([True, False], name='sell-mfi-enabled'), 136 | Categorical([True, False], name='sell-fastd-enabled'), 137 | Categorical([True, False], name='sell-adx-enabled'), 138 | Categorical([True, False], name='sell-rsi-enabled'), 139 | Categorical(['sell-bb_upper', 140 | 'sell-macd_cross_signal', 141 | 'sell-sar_reversal'], name='sell-trigger') 142 | ] 143 | 144 | @staticmethod 145 | def sell_strategy_generator(params: Dict[str, Any]) -> Callable: 146 | """ 147 | Define the sell strategy parameters to be used by hyperopt 148 | """ 149 | def populate_sell_trend(dataframe: DataFrame, metadata: dict) -> DataFrame: 150 | """ 151 | Sell strategy Hyperopt will build and use 152 | """ 153 | # print(params) 154 | conditions = [] 155 | # GUARDS AND TRENDS 156 | if 'sell-mfi-enabled' in params and params['sell-mfi-enabled']: 157 | conditions.append(dataframe['mfi'] > params['sell-mfi-value']) 158 | if 'sell-fastd-enabled' in params and params['sell-fastd-enabled']: 159 | conditions.append(dataframe['fastd'] > params['sell-fastd-value']) 160 | if 'sell-adx-enabled' in params and params['sell-adx-enabled']: 161 | conditions.append(dataframe['adx'] < params['sell-adx-value']) 162 | if 'sell-rsi-enabled' in params and params['sell-rsi-enabled']: 163 | conditions.append(dataframe['rsi'] > params['sell-rsi-value']) 164 | 165 | # TRIGGERS 166 | if 'sell-trigger' in params: 167 | if params['sell-trigger'] == 'sell-bb_upper': 168 | conditions.append(dataframe['close'] > dataframe['bb_upperband']) 169 | if params['sell-trigger'] == 'sell-macd_cross_signal': 170 | conditions.append(qtpylib.crossed_above( 171 | dataframe['macdsignal'], dataframe['macd'] 172 | )) 173 | if params['sell-trigger'] == 'sell-sar_reversal': 174 | conditions.append(qtpylib.crossed_above( 175 | dataframe['sar'], dataframe['close'] 176 | )) 177 | 178 | # Check that volume is not 0 179 | conditions.append(dataframe['volume'] > 0) 180 | 181 | if conditions: 182 | dataframe.loc[ 183 | reduce(lambda x, y: x & y, conditions), 184 | 'sell'] = 1 185 | 186 | return dataframe 187 | 188 | return populate_sell_trend 189 | 190 | @staticmethod 191 | def generate_roi_table(params: Dict) -> Dict[int, float]: 192 | """ 193 | Generate the ROI table that will be used by Hyperopt 194 | 195 | This implementation generates the default legacy Freqtrade ROI tables. 196 | 197 | Change it if you need different number of steps in the generated 198 | ROI tables or other structure of the ROI tables. 199 | 200 | Please keep it aligned with parameters in the 'roi' optimization 201 | hyperspace defined by the roi_space method. 202 | """ 203 | roi_table = {} 204 | roi_table[0] = params['roi_p1'] + params['roi_p2'] + params['roi_p3'] 205 | roi_table[params['roi_t3']] = params['roi_p1'] + params['roi_p2'] 206 | roi_table[params['roi_t3'] + params['roi_t2']] = params['roi_p1'] 207 | roi_table[params['roi_t3'] + params['roi_t2'] + params['roi_t1']] = 0 208 | 209 | return roi_table 210 | 211 | @staticmethod 212 | def roi_space() -> List[Dimension]: 213 | """ 214 | Values to search for each ROI steps 215 | 216 | Override it if you need some different ranges for the parameters in the 217 | 'roi' optimization hyperspace. 218 | 219 | Please keep it aligned with the implementation of the 220 | generate_roi_table method. 221 | """ 222 | return [ 223 | Integer(10, 120, name='roi_t1'), 224 | Integer(10, 60, name='roi_t2'), 225 | Integer(10, 40, name='roi_t3'), 226 | SKDecimal(0.01, 0.04, decimals=3, name='roi_p1'), 227 | SKDecimal(0.01, 0.07, decimals=3, name='roi_p2'), 228 | SKDecimal(0.01, 0.20, decimals=3, name='roi_p3'), 229 | ] 230 | 231 | @staticmethod 232 | def stoploss_space() -> List[Dimension]: 233 | """ 234 | Stoploss Value to search 235 | 236 | Override it if you need some different range for the parameter in the 237 | 'stoploss' optimization hyperspace. 238 | """ 239 | return [ 240 | SKDecimal(-0.35, -0.02, decimals=3, name='stoploss'), 241 | ] 242 | 243 | @staticmethod 244 | def trailing_space() -> List[Dimension]: 245 | """ 246 | Create a trailing stoploss space. 247 | 248 | You may override it in your custom Hyperopt class. 249 | """ 250 | return [ 251 | # It was decided to always set trailing_stop is to True if the 'trailing' hyperspace 252 | # is used. Otherwise hyperopt will vary other parameters that won't have effect if 253 | # trailing_stop is set False. 254 | # This parameter is included into the hyperspace dimensions rather than assigning 255 | # it explicitly in the code in order to have it printed in the results along with 256 | # other 'trailing' hyperspace parameters. 257 | Categorical([True], name='trailing_stop'), 258 | 259 | SKDecimal(0.01, 0.35, decimals=3, name='trailing_stop_positive'), 260 | 261 | # 'trailing_stop_positive_offset' should be greater than 'trailing_stop_positive', 262 | # so this intermediate parameter is used as the value of the difference between 263 | # them. The value of the 'trailing_stop_positive_offset' is constructed in the 264 | # generate_trailing_params() method. 265 | # This is similar to the hyperspace dimensions used for constructing the ROI tables. 266 | SKDecimal(0.001, 0.1, decimals=3, name='trailing_stop_positive_offset_p1'), 267 | 268 | Categorical([True, False], name='trailing_only_offset_is_reached'), 269 | ] 270 | -------------------------------------------------------------------------------- /user_data/strategies/Obelisk_Ichimoku_Slow_v1_3.py: -------------------------------------------------------------------------------- 1 | # --- Do not remove these libs --- 2 | from freqtrade.strategy import IStrategy, merge_informative_pair 3 | from pandas import DataFrame 4 | import talib.abstract as ta 5 | import freqtrade.vendor.qtpylib.indicators as qtpylib 6 | 7 | # -------------------------------- 8 | import pandas as pd 9 | import numpy as np 10 | import technical.indicators as ftt 11 | from freqtrade.exchange import timeframe_to_minutes 12 | 13 | # Obelisk_Ichimoku_Slow v1.3 - 2021-04-20 14 | # 15 | # by Obelisk 16 | # https://github.com/brookmiles/ 17 | # 18 | # 1.3 increase return without too much additional drawdown 19 | # - add ema entry guards 20 | # - remove cloud top exit signal from 1.2 21 | # 22 | # The point of this strategy is to buy and hold an up trend as long as possible. 23 | # If you are tempted to add ROI or trailing stops, you will need to make other modifications as well. 24 | # 25 | # This strategy can optionally be backtested at 5m or 1m to validate roi/trailing stop behaviour (there isn't any). 26 | # 27 | # WARNING 28 | # 29 | # Do not use stoploss_on_exchange or the bot may trigger emergencysell when it 30 | # fails to place the stoploss. 31 | # 32 | # WARNING 33 | # 34 | # This strat will buy into ongoing trends, so pay attention to timing when you launch it. 35 | # If the market is peaking then you may end up buying into trends that are just about to end. 36 | # 37 | # 38 | # Contributions: 39 | # JimmyNixx - SSL Channel confirmation 40 | # 41 | # Backtested with pairlist generated with: 42 | # "pairlists": [ 43 | # { 44 | # "method": "VolumePairList", 45 | # "number_assets": 25, 46 | # "sort_key": "quoteVolume", 47 | # "refresh_period": 1800 48 | # }, 49 | # {"method": "AgeFilter", "min_days_listed": 10}, 50 | # {"method": "PrecisionFilter"}, 51 | # {"method": "PriceFilter", "low_price_ratio": 0.001}, 52 | # { 53 | # "method": "RangeStabilityFilter", 54 | # "lookback_days": 3, 55 | # "min_rate_of_change": 0.1, 56 | # "refresh_period": 1440 57 | # }, 58 | # ], 59 | 60 | def ssl_atr(dataframe, length = 7): 61 | df = dataframe.copy() 62 | df['smaHigh'] = df['high'].rolling(length).mean() + df['atr'] 63 | df['smaLow'] = df['low'].rolling(length).mean() - df['atr'] 64 | df['hlv'] = np.where(df['close'] > df['smaHigh'], 1, np.where(df['close'] < df['smaLow'], -1, np.NAN)) 65 | df['hlv'] = df['hlv'].ffill() 66 | df['sslDown'] = np.where(df['hlv'] < 0, df['smaHigh'], df['smaLow']) 67 | df['sslUp'] = np.where(df['hlv'] < 0, df['smaLow'], df['smaHigh']) 68 | return df['sslDown'], df['sslUp'] 69 | 70 | class Obelisk_Ichimoku_Slow_v1_3(IStrategy): 71 | 72 | # Optimal timeframe for the strategy 73 | timeframe = '1h' 74 | 75 | # generate signals from the 1h timeframe 76 | informative_timeframe = '1h' 77 | 78 | # WARNING: ichimoku is a long indicator, if you remove or use a 79 | # shorter startup_candle_count your results will be unstable/invalid 80 | # for up to a week from the start of your backtest or dry/live run 81 | # (180 candles = 7.5 days) 82 | startup_candle_count = 180 83 | 84 | # NOTE: this strat only uses candle information, so processing between 85 | # new candles is a waste of resources as nothing will change 86 | process_only_new_candles = True 87 | 88 | minimal_roi = { 89 | "0": 0.10, 90 | "60": 0.072, 91 | "120": 0.049, 92 | "240": 0.02, 93 | "360": 0, 94 | } 95 | # Trailing stoploss (not used) 96 | trailing_stop = True 97 | trailing_only_offset_is_reached = True 98 | trailing_stop_positive = 0.005 99 | trailing_stop_positive_offset = 0.04 100 | 101 | # WARNING setting a stoploss for this strategy doesn't make much sense, as it will buy 102 | # back into the trend at the next available opportunity, unless the trend has ended, 103 | # in which case it would sell anyway. 104 | 105 | # Stoploss: 106 | stoploss = -0.99 107 | 108 | 109 | def informative_pairs(self): 110 | pairs = self.dp.current_whitelist() 111 | informative_pairs = [(pair, self.informative_timeframe) for pair in pairs] 112 | return informative_pairs 113 | 114 | def slow_tf_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: 115 | 116 | displacement = 30 117 | ichimoku = ftt.ichimoku(dataframe, 118 | conversion_line_period=20, 119 | base_line_periods=60, 120 | laggin_span=120, 121 | displacement=displacement 122 | ) 123 | 124 | dataframe['chikou_span'] = ichimoku['chikou_span'] 125 | 126 | # cross indicators 127 | dataframe['tenkan_sen'] = ichimoku['tenkan_sen'] 128 | dataframe['kijun_sen'] = ichimoku['kijun_sen'] 129 | 130 | # cloud, green a > b, red a < b 131 | dataframe['senkou_a'] = ichimoku['senkou_span_a'] 132 | dataframe['senkou_b'] = ichimoku['senkou_span_b'] 133 | dataframe['leading_senkou_span_a'] = ichimoku['leading_senkou_span_a'] 134 | dataframe['leading_senkou_span_b'] = ichimoku['leading_senkou_span_b'] 135 | dataframe['cloud_green'] = ichimoku['cloud_green'] * 1 136 | dataframe['cloud_red'] = ichimoku['cloud_red'] * -1 137 | 138 | dataframe.loc[:, 'cloud_top'] = dataframe.loc[:, ['senkou_a', 'senkou_b']].max(axis=1) 139 | dataframe.loc[:, 'cloud_bottom'] = dataframe.loc[:, ['senkou_a', 'senkou_b']].min(axis=1) 140 | 141 | # DANGER ZONE START 142 | 143 | # NOTE: Not actually the future, present data that is normally shifted forward for display as the cloud 144 | dataframe['future_green'] = (dataframe['leading_senkou_span_a'] > dataframe['leading_senkou_span_b']).astype('int') * 2 145 | 146 | # The chikou_span is shifted into the past, so we need to be careful not to read the 147 | # current value. But if we shift it forward again by displacement it should be safe to use. 148 | # We're effectively "looking back" at where it normally appears on the chart. 149 | dataframe['chikou_high'] = ( 150 | (dataframe['chikou_span'] > dataframe['senkou_a']) & 151 | (dataframe['chikou_span'] > dataframe['senkou_b']) 152 | ).shift(displacement).fillna(0).astype('int') 153 | 154 | # DANGER ZONE END 155 | 156 | dataframe['ema50'] = ta.EMA(dataframe, timeperiod=50) 157 | dataframe['ema200'] = ta.EMA(dataframe, timeperiod=200) 158 | dataframe['ema_ok'] = ( 159 | (dataframe['close'] > dataframe['ema50']) 160 | & (dataframe['ema50'] > dataframe['ema200']) 161 | ).astype('int') * 2 162 | 163 | dataframe['efi_base'] = ((dataframe['close'] - dataframe['close'].shift()) * dataframe['volume']) 164 | dataframe['efi'] = ta.EMA(dataframe['efi_base'], 13) 165 | dataframe['efi_ok'] = (dataframe['efi'] > 0).astype('int') 166 | 167 | dataframe['atr'] = ta.ATR(dataframe, timeperiod=14) 168 | ssl_down, ssl_up = ssl_atr(dataframe, 10) 169 | dataframe['ssl_down'] = ssl_down 170 | dataframe['ssl_up'] = ssl_up 171 | dataframe['ssl_ok'] = ( 172 | (ssl_up > ssl_down) 173 | ).astype('int') * 3 174 | 175 | dataframe['ichimoku_ok'] = ( 176 | (dataframe['tenkan_sen'] > dataframe['kijun_sen']) 177 | & (dataframe['close'] > dataframe['cloud_top']) 178 | & (dataframe['future_green'] > 0) 179 | & (dataframe['chikou_high'] > 0) 180 | ).astype('int') * 4 181 | 182 | dataframe['entry_ok'] = ( 183 | (dataframe['efi_ok'] > 0) 184 | & (dataframe['open'] < dataframe['ssl_up']) 185 | & (dataframe['close'] < dataframe['ssl_up']) 186 | ).astype('int') * 1 187 | 188 | dataframe['trend_pulse'] = ( 189 | (dataframe['ichimoku_ok'] > 0) 190 | & (dataframe['ssl_ok'] > 0) 191 | & (dataframe['ema_ok'] > 0) 192 | ).astype('int') * 2 193 | 194 | dataframe['trend_over'] = ( 195 | (dataframe['ssl_ok'] == 0) 196 | ).astype('int') * 1 197 | 198 | dataframe.loc[ (dataframe['trend_pulse'] > 0), 'trending'] = 3 199 | dataframe.loc[ (dataframe['trend_over'] > 0) , 'trending'] = 0 200 | dataframe['trending'].fillna(method='ffill', inplace=True) 201 | 202 | return dataframe 203 | 204 | def fast_tf_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: 205 | # none atm 206 | return dataframe 207 | 208 | def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: 209 | 210 | # Obelisk_Ichimoku_Slow does not use trailing stop or roi and should be safe to backtest at 1h 211 | # if self.config['runmode'].value in ('backtest', 'hyperopt'): 212 | # assert (timeframe_to_minutes(self.timeframe) <= 5), "Backtest this strategy in 5m or 1m timeframe." 213 | 214 | if self.timeframe == self.informative_timeframe: 215 | dataframe = self.slow_tf_indicators(dataframe, metadata) 216 | else: 217 | assert self.dp, "DataProvider is required for multiple timeframes." 218 | 219 | informative = self.dp.get_pair_dataframe(pair=metadata['pair'], timeframe=self.informative_timeframe) 220 | informative = self.slow_tf_indicators(informative.copy(), metadata) 221 | 222 | dataframe = merge_informative_pair(dataframe, informative, self.timeframe, self.informative_timeframe, ffill=True) 223 | # don't overwrite the base dataframe's OHLCV information 224 | skip_columns = [(s + "_" + self.informative_timeframe) for s in ['date', 'open', 'high', 'low', 'close', 'volume']] 225 | dataframe.rename(columns=lambda s: s.replace("_{}".format(self.informative_timeframe), "") if (not s in skip_columns) else s, inplace=True) 226 | 227 | dataframe = self.fast_tf_indicators(dataframe, metadata) 228 | 229 | return dataframe 230 | 231 | def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: 232 | dataframe.loc[ 233 | (dataframe['trending'] > 0) 234 | & (dataframe['entry_ok'] > 0) 235 | & (dataframe['date'].dt.minute == 0) # when backtesting at 5m/1m only set signal on the hour 236 | , 'buy'] = 1 237 | return dataframe 238 | 239 | def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: 240 | dataframe.loc[ 241 | (dataframe['trending'] == 0) 242 | & (dataframe['date'].dt.minute == 0) # when backtesting at 5m/1m only set signal on the hour 243 | , 'sell'] = 1 244 | return dataframe 245 | 246 | plot_config = { 247 | # Main plot indicators (Moving averages, ...) 248 | 'main_plot': { 249 | 'senkou_a': { 250 | 'color': 'green', 251 | 'fill_to': 'senkou_b', 252 | 'fill_label': 'Ichimoku Cloud', 253 | 'fill_color': 'rgba(0,0,0,0.2)', 254 | }, 255 | # plot senkou_b, too. Not only the area to it. 256 | 'senkou_b': { 257 | 'color': 'red', 258 | }, 259 | 'tenkan_sen': { 'color': 'blue' }, 260 | 'kijun_sen': { 'color': 'orange' }, 261 | 262 | # 'chikou_span': { 'color': 'lightgreen' }, 263 | 264 | # 'ssl_up': { 'color': 'green' }, 265 | # 'ssl_down': { 'color': 'red' }, 266 | 267 | # 'ema50': { 'color': 'violet' }, 268 | # 'ema200': { 'color': 'magenta' }, 269 | }, 270 | 'subplots': { 271 | "Trend": { 272 | 'trend_pulse': {'color': 'blue'}, 273 | 'trending': {'color': 'orange'}, 274 | 'trend_over': {'color': 'red'}, 275 | }, 276 | "Signals": { 277 | 'ichimoku_ok': {'color': 'green'}, 278 | 'ssl_ok': {'color': 'red'}, 279 | 'ema_ok': {'color': 'orange'}, 280 | 'entry_ok': {'color': 'blue'}, 281 | }, 282 | } 283 | } 284 | -------------------------------------------------------------------------------- /user_data/strategies/NostalgiaForInfinityV2.py: -------------------------------------------------------------------------------- 1 | import freqtrade.vendor.qtpylib.indicators as qtpylib 2 | import numpy as np 3 | import talib.abstract as ta 4 | from freqtrade.strategy.interface import IStrategy 5 | from freqtrade.strategy import DecimalParameter, IntParameter 6 | from pandas import DataFrame 7 | from freqtrade.strategy import merge_informative_pair 8 | from freqtrade.persistence import Trade 9 | 10 | 11 | ########################################################################################################### 12 | ## NostalgiaForInfinityV2 by iterativ ## 13 | ## ## 14 | ## Strategy for Freqtrade https://github.com/freqtrade/freqtrade ## 15 | ## ## 16 | ########################################################################################################### 17 | ## GENERAL RECOMMENDATIONS ## 18 | ## ## 19 | ## For optimal performance, suggested to use between 4 and 6 open trades, with unlimited stake. ## 20 | ## A pairlist with 20 to 60 pairs. Volume pairlist works well. ## 21 | ## Prefer stable coin (USDT, BUSDT etc) pairs, instead of BTC or ETH pairs. ## 22 | ## Highly recommended to blacklist leveraged tokens (*BULL, *BEAR, *UP, *DOWN etc). ## 23 | ## Ensure that you don't override any variables in you config.json. Especially ## 24 | ## the timeframe (must be 5m). ## 25 | ## ## 26 | ########################################################################################################### 27 | ## DONATIONS ## 28 | ## ## 29 | ## Absolutely not required. However, will be accepted as a token of appreciation. ## 30 | ## ## 31 | ## BTC: bc1qvflsvddkmxh7eqhc4jyu5z5k6xcw3ay8jl49sk ## 32 | ## ETH: 0x83D3cFb8001BDC5d2211cBeBB8cB3461E5f7Ec91 ## 33 | ## ## 34 | ########################################################################################################### 35 | 36 | 37 | # SSL Channels 38 | def SSLChannels(dataframe, length = 7): 39 | df = dataframe.copy() 40 | df['ATR'] = ta.ATR(df, timeperiod=14) 41 | df['smaHigh'] = df['high'].rolling(length).mean() + df['ATR'] 42 | df['smaLow'] = df['low'].rolling(length).mean() - df['ATR'] 43 | df['hlv'] = np.where(df['close'] > df['smaHigh'], 1, np.where(df['close'] < df['smaLow'], -1, np.NAN)) 44 | df['hlv'] = df['hlv'].ffill() 45 | df['sslDown'] = np.where(df['hlv'] < 0, df['smaHigh'], df['smaLow']) 46 | df['sslUp'] = np.where(df['hlv'] < 0, df['smaLow'], df['smaHigh']) 47 | return df['sslDown'], df['sslUp'] 48 | 49 | class NostalgiaForInfinityV2(IStrategy): 50 | INTERFACE_VERSION = 2 51 | 52 | minimal_roi = { 53 | "0": 10 54 | } 55 | 56 | stoploss = -1.0 57 | 58 | timeframe = '5m' 59 | inf_1h = '1h' 60 | 61 | custom_info = {} 62 | 63 | # Sell signal 64 | use_sell_signal = True 65 | sell_profit_only = False 66 | sell_profit_offset = 0.001 # it doesn't meant anything, just to guarantee there is a minimal profit. 67 | ignore_roi_if_buy_signal = True 68 | 69 | # Trailing stoploss 70 | trailing_stop = False 71 | trailing_only_offset_is_reached = True 72 | trailing_stop_positive = 0.02 73 | trailing_stop_positive_offset = 0.04 74 | # Custom stoploss 75 | use_custom_stoploss = False 76 | 77 | # Run "populate_indicators()" only for new candle. 78 | process_only_new_candles = True 79 | 80 | # Number of candles the strategy requires before producing valid signals 81 | startup_candle_count: int = 200 82 | 83 | # Optional order type mapping. 84 | order_types = { 85 | 'buy': 'limit', 86 | 'sell': 'limit', 87 | 'stoploss': 'market', 88 | 'stoploss_on_exchange': False 89 | } 90 | 91 | # Buy params 92 | buy_params = { 93 | "buy_bb40_bbdelta_close": 0.017, 94 | "buy_bb40_closedelta_close": 0.013, 95 | "buy_bb40_tail_bbdelta": 0.445, 96 | 97 | "buy_bb20_close_bblowerband": 0.992, 98 | "buy_bb20_volume": 27, 99 | 100 | "buy_rsi_diff": 52.438, 101 | } 102 | 103 | # Sell params 104 | sell_params = { 105 | "sell_rsi_bb": 79.706, 106 | 107 | "sell_rsi_main": 85.023, 108 | 109 | "sell_rsi_2": 87.545, 110 | 111 | "sell_rsi_diff": 0.873, 112 | "sell_ema_relative": 0.03, 113 | } 114 | 115 | buy_bb40_bbdelta_close = DecimalParameter(0.005, 0.05, default=0.049, space='buy', optimize=True, load=True) 116 | buy_bb40_closedelta_close = DecimalParameter(0.01, 0.03, default=0.023, space='buy', optimize=True, load=True) 117 | buy_bb40_tail_bbdelta = DecimalParameter(0.15, 0.45, default=0.287, space='buy', optimize=True, load=True) 118 | buy_bb20_close_bblowerband = DecimalParameter(0.8, 1.1, default=0.991, space='buy', optimize=True, load=True) 119 | buy_bb20_volume = IntParameter(18, 34, default=20, space='buy', optimize=True, load=True) 120 | buy_rsi_diff = DecimalParameter(36.0, 54.0, default=37.0, space='buy', optimize=True, load=True) 121 | 122 | sell_rsi_bb = DecimalParameter(60.0, 80.0, default=70, space='sell', optimize=True, load=True) 123 | sell_rsi_main = DecimalParameter(72.0, 90.0, default=78.0, space='sell', optimize=True, load=True) 124 | sell_rsi_2 = DecimalParameter(72.0, 90.0, default=60.0, space='sell', optimize=True, load=True) 125 | sell_ema_relative = DecimalParameter(0.005, 0.1, default=0.03, space='sell', optimize=False, load=True) 126 | sell_rsi_diff = DecimalParameter(0.0, 5.0, default=5.0, space='sell', optimize=True, load=True) 127 | 128 | 129 | def informative_pairs(self): 130 | pairs = self.dp.current_whitelist() 131 | informative_pairs = [(pair, '1h') for pair in pairs] 132 | return informative_pairs 133 | 134 | def informative_1h_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: 135 | assert self.dp, "DataProvider is required for multiple timeframes." 136 | # Get the informative pair 137 | informative_1h = self.dp.get_pair_dataframe(pair=metadata['pair'], timeframe=self.inf_1h) 138 | # EMA 139 | informative_1h['ema_20'] = ta.EMA(informative_1h, timeperiod=20) 140 | informative_1h['ema_50'] = ta.EMA(informative_1h, timeperiod=50) 141 | informative_1h['ema_200'] = ta.EMA(informative_1h, timeperiod=200) 142 | # RSI 143 | informative_1h['rsi'] = ta.RSI(informative_1h, timeperiod=14) 144 | # SSL Channels 145 | ssl_down_1h, ssl_up_1h = SSLChannels(informative_1h, 20) 146 | informative_1h['ssl_down'] = ssl_down_1h 147 | informative_1h['ssl_up'] = ssl_up_1h 148 | 149 | return informative_1h 150 | 151 | def normal_tf_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: 152 | bb_40 = qtpylib.bollinger_bands(dataframe['close'], window=40, stds=2) 153 | dataframe['lower'] = bb_40['lower'] 154 | dataframe['mid'] = bb_40['mid'] 155 | dataframe['bbdelta'] = (bb_40['mid'] - dataframe['lower']).abs() 156 | dataframe['closedelta'] = (dataframe['close'] - dataframe['close'].shift()).abs() 157 | dataframe['tail'] = (dataframe['close'] - dataframe['low']).abs() 158 | 159 | bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=2) 160 | dataframe['bb_lowerband'] = bollinger['lower'] 161 | dataframe['bb_middleband'] = bollinger['mid'] 162 | dataframe['bb_upperband'] = bollinger['upper'] 163 | dataframe['ema_slow'] = ta.EMA(dataframe, timeperiod=50) 164 | dataframe['volume_mean_slow'] = dataframe['volume'].rolling(window=30).mean() 165 | 166 | # EMA 167 | dataframe['ema_50'] = ta.EMA(dataframe, timeperiod=50) 168 | dataframe['ema_200'] = ta.EMA(dataframe, timeperiod=200) 169 | 170 | # SMA 171 | dataframe['sma_5'] = ta.SMA(dataframe, timeperiod=5) 172 | dataframe['sma_9'] = ta.SMA(dataframe, timeperiod=9) 173 | 174 | # RSI 175 | dataframe['rsi'] = ta.RSI(dataframe, timeperiod=14) 176 | 177 | return dataframe 178 | 179 | def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: 180 | # The indicators for the 1h informative timeframe 181 | informative_1h = self.informative_1h_indicators(dataframe, metadata) 182 | dataframe = merge_informative_pair(dataframe, informative_1h, self.timeframe, self.inf_1h, ffill=True) 183 | 184 | # The indicators for the normal (5m) timeframe 185 | dataframe = self.normal_tf_indicators(dataframe, metadata) 186 | 187 | return dataframe 188 | 189 | def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: 190 | dataframe.loc[ 191 | ( 192 | (dataframe['close'] < dataframe['sma_9']) & 193 | (dataframe['close'] > dataframe['ema_200_1h']) & 194 | (dataframe['ema_50'] > dataframe['ema_200']) & 195 | (dataframe['ema_50_1h'] > dataframe['ema_200_1h']) & 196 | 197 | dataframe['lower'].shift().gt(0) & 198 | dataframe['bbdelta'].gt(dataframe['close'] * self.buy_bb40_bbdelta_close.value) & 199 | dataframe['closedelta'].gt(dataframe['close'] * self.buy_bb40_closedelta_close.value) & 200 | dataframe['tail'].lt(dataframe['bbdelta'] * self.buy_bb40_tail_bbdelta.value) & 201 | dataframe['close'].lt(dataframe['lower'].shift()) & 202 | dataframe['close'].le(dataframe['close'].shift()) & 203 | (dataframe['volume'] > 0) 204 | ) 205 | | 206 | ( 207 | (dataframe['close'] < dataframe['sma_9']) & 208 | (dataframe['close'] > dataframe['ema_200']) & 209 | (dataframe['close'] > dataframe['ema_200_1h']) & 210 | 211 | (dataframe['close'] < dataframe['ema_slow']) & 212 | (dataframe['close'] < self.buy_bb20_close_bblowerband.value * dataframe['bb_lowerband']) & 213 | (dataframe['volume'] < (dataframe['volume_mean_slow'].shift(1) * self.buy_bb20_volume.value)) 214 | ) 215 | | 216 | ( 217 | (dataframe['close'] < dataframe['sma_5']) & 218 | (dataframe['close'] > dataframe['ema_200']) & 219 | (dataframe['close'] > dataframe['ema_200_1h']) & 220 | (dataframe['ssl_up_1h'] > dataframe['ssl_down_1h']) & 221 | (dataframe['ema_50'] > dataframe['ema_200']) & 222 | (dataframe['ema_50_1h'] > dataframe['ema_200_1h']) & 223 | 224 | (dataframe['rsi'] < dataframe['rsi_1h'] - self.buy_rsi_diff.value) & 225 | (dataframe['volume'] > 0) 226 | ) 227 | , 228 | 'buy' 229 | ] = 1 230 | return dataframe 231 | 232 | def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: 233 | dataframe.loc[ 234 | ( 235 | (dataframe['rsi'] > self.sell_rsi_bb.value) & 236 | (dataframe['close'] > dataframe['bb_upperband']) & 237 | (dataframe['close'].shift(1) > dataframe['bb_upperband'].shift(1)) & 238 | (dataframe['close'].shift(2) > dataframe['bb_upperband'].shift(2)) & 239 | (dataframe['volume'] > 0) 240 | ) 241 | | 242 | ( 243 | (dataframe['rsi'] > self.sell_rsi_main.value) & 244 | (dataframe['volume'] > 0) 245 | ) 246 | | 247 | ( 248 | (dataframe['close'] < dataframe['ema_200']) & 249 | (dataframe['close'] > dataframe['ema_50']) & 250 | (dataframe['rsi'] > self.sell_rsi_2.value) & 251 | (dataframe['volume'] > 0) 252 | ) 253 | | 254 | ( 255 | (dataframe['close'] < dataframe['ema_200']) & 256 | (((dataframe['ema_200'] - dataframe['close']) / dataframe['close']) < self.sell_ema_relative.value) & 257 | 258 | (dataframe['rsi'] > dataframe['rsi_1h'] + self.sell_rsi_diff.value) & 259 | (dataframe['volume'] > 0) 260 | ) 261 | , 262 | 'sell' 263 | ] = 1 264 | return dataframe 265 | -------------------------------------------------------------------------------- /user_data/strategies/Obelisk_Ichimoku_ZEMA_v1.py: -------------------------------------------------------------------------------- 1 | # --- Do not remove these libs --- 2 | from freqtrade.strategy import IStrategy, merge_informative_pair, DecimalParameter, IntParameter 3 | from pandas import DataFrame 4 | import talib.abstract as ta 5 | import freqtrade.vendor.qtpylib.indicators as qtpylib 6 | 7 | # -------------------------------- 8 | import pandas as pd 9 | import numpy as np 10 | import technical.indicators as ftt 11 | from freqtrade.exchange import timeframe_to_minutes 12 | import logging 13 | 14 | logger = logging.getLogger(__name__) 15 | 16 | # Obelisk_Ichimoku_ZEMA v1 - 2021-05-20 17 | # 18 | # EXPERIMENTAL 19 | # 20 | # RUN AT YOUR OWN RISK 21 | # 22 | # by Obelisk 23 | # https://github.com/brookmiles/ 24 | 25 | def ssl_atr(dataframe, length = 7): 26 | df = dataframe.copy() 27 | df['smaHigh'] = df['high'].rolling(length).mean() + df['atr'] 28 | df['smaLow'] = df['low'].rolling(length).mean() - df['atr'] 29 | df['hlv'] = np.where(df['close'] > df['smaHigh'], 1, np.where(df['close'] < df['smaLow'], -1, np.NAN)) 30 | df['hlv'] = df['hlv'].ffill() 31 | df['sslDown'] = np.where(df['hlv'] < 0, df['smaHigh'], df['smaLow']) 32 | df['sslUp'] = np.where(df['hlv'] < 0, df['smaLow'], df['smaHigh']) 33 | return df['sslDown'], df['sslUp'] 34 | 35 | class Obelisk_Ichimoku_ZEMA_v1(IStrategy): 36 | 37 | # Optimal timeframe for the strategy 38 | timeframe = '5m' 39 | 40 | # generate signals from the 1h timeframe 41 | informative_timeframe = '1h' 42 | 43 | # WARNING: ichimoku is a long indicator, if you remove or use a 44 | # shorter startup_candle_count your backtest results will be unreliable 45 | startup_candle_count = 200 46 | 47 | # NOTE: this strat only uses candle information, so processing between 48 | # new candles is a waste of resources as nothing will change 49 | process_only_new_candles = True 50 | 51 | # ROI table: 52 | minimal_roi = { 53 | "0": 0.078, 54 | "40": 0.062, 55 | "99": 0.039, 56 | "218": 0 57 | } 58 | 59 | stoploss = -0.294 60 | 61 | # Buy hyperspace params: 62 | buy_params = { 63 | 'low_offset': 0.964, 'zema_len_buy': 51 64 | } 65 | 66 | # Sell hyperspace params: 67 | sell_params = { 68 | 'high_offset': 1.004, 'zema_len_sell': 72 69 | } 70 | 71 | low_offset = DecimalParameter(0.80, 1.20, default=1.004, space='buy', optimize=True) 72 | high_offset = DecimalParameter(0.80, 1.20, default=0.964, space='sell', optimize=True) 73 | zema_len_buy = IntParameter(30, 90, default=72, space='buy', optimize=True) 74 | zema_len_sell = IntParameter(30, 90, default=51, space='sell', optimize=True) 75 | 76 | def informative_pairs(self): 77 | pairs = self.dp.current_whitelist() 78 | informative_pairs = [(pair, self.informative_timeframe) for pair in pairs] 79 | return informative_pairs 80 | 81 | def slow_tf_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: 82 | 83 | displacement = 30 84 | ichimoku = ftt.ichimoku(dataframe, 85 | conversion_line_period=20, 86 | base_line_periods=60, 87 | laggin_span=120, 88 | displacement=displacement 89 | ) 90 | 91 | dataframe['chikou_span'] = ichimoku['chikou_span'] 92 | 93 | # cross indicators 94 | dataframe['tenkan_sen'] = ichimoku['tenkan_sen'] 95 | dataframe['kijun_sen'] = ichimoku['kijun_sen'] 96 | 97 | # cloud, green a > b, red a < b 98 | dataframe['senkou_a'] = ichimoku['senkou_span_a'] 99 | dataframe['senkou_b'] = ichimoku['senkou_span_b'] 100 | dataframe['leading_senkou_span_a'] = ichimoku['leading_senkou_span_a'] 101 | dataframe['leading_senkou_span_b'] = ichimoku['leading_senkou_span_b'] 102 | dataframe['cloud_green'] = ichimoku['cloud_green'] * 1 103 | dataframe['cloud_red'] = ichimoku['cloud_red'] * -1 104 | 105 | dataframe.loc[:, 'cloud_top'] = dataframe.loc[:, ['senkou_a', 'senkou_b']].max(axis=1) 106 | dataframe.loc[:, 'cloud_bottom'] = dataframe.loc[:, ['senkou_a', 'senkou_b']].min(axis=1) 107 | 108 | # DANGER ZONE START 109 | 110 | # NOTE: Not actually the future, present data that is normally shifted forward for display as the cloud 111 | dataframe['future_green'] = (dataframe['leading_senkou_span_a'] > dataframe['leading_senkou_span_b']).astype('int') * 2 112 | dataframe['future_red'] = (dataframe['leading_senkou_span_a'] < dataframe['leading_senkou_span_b']).astype('int') * 2 113 | 114 | # The chikou_span is shifted into the past, so we need to be careful not to read the 115 | # current value. But if we shift it forward again by displacement it should be safe to use. 116 | # We're effectively "looking back" at where it normally appears on the chart. 117 | dataframe['chikou_high'] = ( 118 | (dataframe['chikou_span'] > dataframe['cloud_top']) 119 | ).shift(displacement).fillna(0).astype('int') 120 | 121 | dataframe['chikou_low'] = ( 122 | (dataframe['chikou_span'] < dataframe['cloud_bottom']) 123 | ).shift(displacement).fillna(0).astype('int') 124 | 125 | # DANGER ZONE END 126 | 127 | dataframe['atr'] = ta.ATR(dataframe, timeperiod=14) 128 | ssl_down, ssl_up = ssl_atr(dataframe, 10) 129 | dataframe['ssl_down'] = ssl_down 130 | dataframe['ssl_up'] = ssl_up 131 | dataframe['ssl_ok'] = ( 132 | (ssl_up > ssl_down) 133 | ).astype('int') * 3 134 | dataframe['ssl_bear'] = ( 135 | (ssl_up < ssl_down) 136 | ).astype('int') * 3 137 | 138 | dataframe['ichimoku_ok'] = ( 139 | (dataframe['tenkan_sen'] > dataframe['kijun_sen']) 140 | & (dataframe['close'] > dataframe['cloud_top']) 141 | & (dataframe['future_green'] > 0) 142 | # & (dataframe['chikou_high'] > 0) 143 | ).astype('int') * 4 144 | 145 | dataframe['ichimoku_bear'] = ( 146 | (dataframe['tenkan_sen'] < dataframe['kijun_sen']) 147 | & (dataframe['close'] < dataframe['cloud_bottom']) 148 | & (dataframe['future_red'] > 0) 149 | # & (dataframe['chikou_low'] > 0) 150 | ).astype('int') * 4 151 | 152 | dataframe['ichimoku_valid'] = ( 153 | (dataframe['leading_senkou_span_b'] == dataframe['leading_senkou_span_b']) # not NaN 154 | ).astype('int') * 1 155 | 156 | dataframe['trend_pulse'] = ( 157 | (dataframe['ichimoku_ok'] > 0) 158 | & (dataframe['ssl_ok'] > 0) 159 | ).astype('int') * 2 160 | 161 | dataframe['bear_trend_pulse'] = ( 162 | (dataframe['ichimoku_bear'] > 0) 163 | & (dataframe['ssl_bear'] > 0) 164 | ).astype('int') * 2 165 | 166 | 167 | dataframe['trend_over'] = ( 168 | (dataframe['ssl_ok'] == 0) 169 | | (dataframe['close'] < dataframe['cloud_top']) 170 | ).astype('int') * 1 171 | 172 | dataframe['bear_trend_over'] = ( 173 | (dataframe['ssl_bear'] == 0) 174 | | (dataframe['close'] > dataframe['cloud_bottom']) 175 | ).astype('int') * 1 176 | 177 | dataframe.loc[ (dataframe['trend_pulse'] > 0), 'trending'] = 3 178 | dataframe.loc[ (dataframe['trend_over'] > 0) , 'trending'] = 0 179 | dataframe['trending'].fillna(method='ffill', inplace=True) 180 | 181 | dataframe.loc[ (dataframe['bear_trend_pulse'] > 0), 'bear_trending'] = 3 182 | dataframe.loc[ (dataframe['bear_trend_over'] > 0) , 'bear_trending'] = 0 183 | dataframe['bear_trending'].fillna(method='ffill', inplace=True) 184 | 185 | return dataframe 186 | 187 | def fast_tf_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: 188 | if self.config['runmode'].value == 'hyperopt': 189 | for len in range(30, 91): 190 | dataframe[f'zema_{len}'] = ftt.zema(dataframe, period=len) 191 | else: 192 | dataframe[f'zema_{self.zema_len_buy.value}'] = ftt.zema(dataframe, period=self.zema_len_buy.value) 193 | dataframe[f'zema_{self.zema_len_sell.value}'] = ftt.zema(dataframe, period=self.zema_len_sell.value) 194 | dataframe[f'zema_buy'] = ftt.zema(dataframe, period=self.zema_len_buy.value) * self.low_offset.value 195 | dataframe[f'zema_sell'] = ftt.zema(dataframe, period=self.zema_len_sell.value) * self.high_offset.value 196 | 197 | 198 | return dataframe 199 | 200 | def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: 201 | 202 | assert (timeframe_to_minutes(self.timeframe) == 5), "Run this strategy at 5m." 203 | 204 | if self.timeframe == self.informative_timeframe: 205 | dataframe = self.slow_tf_indicators(dataframe, metadata) 206 | else: 207 | assert self.dp, "DataProvider is required for multiple timeframes." 208 | 209 | informative = self.dp.get_pair_dataframe(pair=metadata['pair'], timeframe=self.informative_timeframe) 210 | informative = self.slow_tf_indicators(informative.copy(), metadata) 211 | 212 | dataframe = merge_informative_pair(dataframe, informative, self.timeframe, self.informative_timeframe, ffill=True) 213 | # don't overwrite the base dataframe's OHLCV information 214 | skip_columns = [(s + "_" + self.informative_timeframe) for s in ['date', 'open', 'high', 'low', 'close', 'volume']] 215 | dataframe.rename(columns=lambda s: s.replace("_{}".format(self.informative_timeframe), "") if (not s in skip_columns) else s, inplace=True) 216 | 217 | dataframe = self.fast_tf_indicators(dataframe, metadata) 218 | 219 | return dataframe 220 | 221 | def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: 222 | zema = f'zema_{self.zema_len_buy.value}' 223 | 224 | dataframe.loc[ 225 | (dataframe['ichimoku_valid'] > 0) 226 | & (dataframe['bear_trending'] == 0) 227 | & (qtpylib.crossed_above(dataframe['close'], (dataframe[zema] * self.low_offset.value))) 228 | # & (dataframe['close'] < (dataframe[zema] * self.low_offset.value)) 229 | , 'buy'] = 1 230 | return dataframe 231 | 232 | def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: 233 | zema = f'zema_{self.zema_len_sell.value}' 234 | 235 | dataframe.loc[ 236 | ( 237 | qtpylib.crossed_above(dataframe['close'], (dataframe[zema] * self.high_offset.value)) 238 | ) 239 | , 'sell'] = 1 240 | 241 | return dataframe 242 | 243 | def confirm_trade_exit(self, pair: str, trade: 'Trade', order_type: str, amount: float, 244 | rate: float, time_in_force: str, sell_reason: str, 245 | current_time: 'datetime', **kwargs) -> bool: 246 | 247 | if sell_reason in ('roi',): 248 | dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe) 249 | current_candle = dataframe.iloc[-1] 250 | if current_candle is not None: 251 | current_candle = current_candle.squeeze() 252 | # don't sell during ichimoku uptrend 253 | if current_candle['trending'] > 0: 254 | return False 255 | 256 | return True 257 | 258 | plot_config = { 259 | # Main plot indicators (Moving averages, ...) 260 | 'main_plot': { 261 | 'senkou_a': { 262 | 'color': 'green', 263 | 'fill_to': 'senkou_b', 264 | 'fill_label': 'Ichimoku Cloud', 265 | 'fill_color': 'rgba(0,0,0,0.2)', 266 | }, 267 | # plot senkou_b, too. Not only the area to it. 268 | 'senkou_b': { 269 | 'color': 'red', 270 | }, 271 | 'tenkan_sen': { 'color': 'blue' }, 272 | 'kijun_sen': { 'color': 'orange' }, 273 | 274 | # 'chikou_span': { 'color': 'lightgreen' }, 275 | 276 | 'ssl_up': { 'color': 'green' }, 277 | # 'ssl_down': { 'color': 'red' }, 278 | 279 | # 'ema50': { 'color': 'violet' }, 280 | # 'ema200': { 'color': 'magenta' }, 281 | 282 | 'zema_buy': { 'color': 'blue' }, 283 | 'zema_sell': { 'color': 'orange' }, 284 | }, 285 | 'subplots': { 286 | "Trend": { 287 | 'trending': {'color': 'green'}, 288 | 'bear_trending': {'color': 'red'}, 289 | }, 290 | "Bull": { 291 | 'trend_pulse': {'color': 'blue'}, 292 | 'trending': {'color': 'orange'}, 293 | 'trend_over': {'color': 'red'}, 294 | }, 295 | "Bull Signals": { 296 | 'ichimoku_ok': {'color': 'green'}, 297 | 'ssl_ok': {'color': 'red'}, 298 | }, 299 | "Bear": { 300 | 'bear_trend_pulse': {'color': 'blue'}, 301 | 'bear_trending': {'color': 'orange'}, 302 | 'bear_trend_over': {'color': 'red'}, 303 | }, 304 | "Bear Signals": { 305 | 'ichimoku_bear': {'color': 'green'}, 306 | 'ssl_bear': {'color': 'red'}, 307 | }, 308 | "Misc": { 309 | 'ichimoku_valid': {'color': 'green'}, 310 | }, 311 | } 312 | } 313 | -------------------------------------------------------------------------------- /user_data/notebooks/strategy_analysis_example.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Strategy analysis example\n", 8 | "\n", 9 | "Debugging a strategy can be time-consuming. Freqtrade offers helper functions to visualize raw data.\n", 10 | "The following assumes you work with SampleStrategy, data for 5m timeframe from Binance and have downloaded them into the data directory in the default location." 11 | ] 12 | }, 13 | { 14 | "cell_type": "markdown", 15 | "metadata": {}, 16 | "source": [ 17 | "## Setup" 18 | ] 19 | }, 20 | { 21 | "cell_type": "code", 22 | "execution_count": null, 23 | "metadata": {}, 24 | "outputs": [], 25 | "source": [ 26 | "from pathlib import Path\n", 27 | "from freqtrade.configuration import Configuration\n", 28 | "\n", 29 | "# Customize these according to your needs.\n", 30 | "\n", 31 | "# Initialize empty configuration object\n", 32 | "config = Configuration.from_files([])\n", 33 | "# Optionally, use existing configuration file\n", 34 | "# config = Configuration.from_files([\"config.json\"])\n", 35 | "\n", 36 | "# Define some constants\n", 37 | "config[\"timeframe\"] = \"5m\"\n", 38 | "# Name of the strategy class\n", 39 | "config[\"strategy\"] = \"SampleStrategy\"\n", 40 | "# Location of the data\n", 41 | "data_location = Path(config['user_data_dir'], 'data', 'binance')\n", 42 | "# Pair to analyze - Only use one pair here\n", 43 | "pair = \"BTC/USDT\"" 44 | ] 45 | }, 46 | { 47 | "cell_type": "code", 48 | "execution_count": null, 49 | "metadata": {}, 50 | "outputs": [], 51 | "source": [ 52 | "# Load data using values set above\n", 53 | "from freqtrade.data.history import load_pair_history\n", 54 | "\n", 55 | "candles = load_pair_history(datadir=data_location,\n", 56 | " timeframe=config[\"timeframe\"],\n", 57 | " pair=pair,\n", 58 | " data_format = \"hdf5\",\n", 59 | " )\n", 60 | "\n", 61 | "# Confirm success\n", 62 | "print(\"Loaded \" + str(len(candles)) + f\" rows of data for {pair} from {data_location}\")\n", 63 | "candles.head()" 64 | ] 65 | }, 66 | { 67 | "cell_type": "markdown", 68 | "metadata": {}, 69 | "source": [ 70 | "## Load and run strategy\n", 71 | "* Rerun each time the strategy file is changed" 72 | ] 73 | }, 74 | { 75 | "cell_type": "code", 76 | "execution_count": null, 77 | "metadata": {}, 78 | "outputs": [], 79 | "source": [ 80 | "# Load strategy using values set above\n", 81 | "from freqtrade.resolvers import StrategyResolver\n", 82 | "strategy = StrategyResolver.load_strategy(config)\n", 83 | "\n", 84 | "# Generate buy/sell signals using strategy\n", 85 | "df = strategy.analyze_ticker(candles, {'pair': pair})\n", 86 | "df.tail()" 87 | ] 88 | }, 89 | { 90 | "cell_type": "markdown", 91 | "metadata": {}, 92 | "source": [ 93 | "### Display the trade details\n", 94 | "\n", 95 | "* Note that using `data.head()` would also work, however most indicators have some \"startup\" data at the top of the dataframe.\n", 96 | "* Some possible problems\n", 97 | " * Columns with NaN values at the end of the dataframe\n", 98 | " * Columns used in `crossed*()` functions with completely different units\n", 99 | "* Comparison with full backtest\n", 100 | " * having 200 buy signals as output for one pair from `analyze_ticker()` does not necessarily mean that 200 trades will be made during backtesting.\n", 101 | " * Assuming you use only one condition such as, `df['rsi'] < 30` as buy condition, this will generate multiple \"buy\" signals for each pair in sequence (until rsi returns > 29). The bot will only buy on the first of these signals (and also only if a trade-slot (\"max_open_trades\") is still available), or on one of the middle signals, as soon as a \"slot\" becomes available. \n" 102 | ] 103 | }, 104 | { 105 | "cell_type": "code", 106 | "execution_count": null, 107 | "metadata": {}, 108 | "outputs": [], 109 | "source": [ 110 | "# Report results\n", 111 | "print(f\"Generated {df['buy'].sum()} buy signals\")\n", 112 | "data = df.set_index('date', drop=False)\n", 113 | "data.tail()" 114 | ] 115 | }, 116 | { 117 | "cell_type": "markdown", 118 | "metadata": {}, 119 | "source": [ 120 | "## Load existing objects into a Jupyter notebook\n", 121 | "\n", 122 | "The following cells assume that you have already generated data using the cli. \n", 123 | "They will allow you to drill deeper into your results, and perform analysis which otherwise would make the output very difficult to digest due to information overload." 124 | ] 125 | }, 126 | { 127 | "cell_type": "markdown", 128 | "metadata": {}, 129 | "source": [ 130 | "### Load backtest results to pandas dataframe\n", 131 | "\n", 132 | "Analyze a trades dataframe (also used below for plotting)" 133 | ] 134 | }, 135 | { 136 | "cell_type": "code", 137 | "execution_count": null, 138 | "metadata": {}, 139 | "outputs": [], 140 | "source": [ 141 | "from freqtrade.data.btanalysis import load_backtest_data, load_backtest_stats\n", 142 | "\n", 143 | "# if backtest_dir points to a directory, it'll automatically load the last backtest file.\n", 144 | "backtest_dir = config[\"user_data_dir\"] / \"backtest_results\"\n", 145 | "# backtest_dir can also point to a specific file \n", 146 | "# backtest_dir = config[\"user_data_dir\"] / \"backtest_results/backtest-result-2020-07-01_20-04-22.json\"" 147 | ] 148 | }, 149 | { 150 | "cell_type": "code", 151 | "execution_count": null, 152 | "metadata": {}, 153 | "outputs": [], 154 | "source": [ 155 | "# You can get the full backtest statistics by using the following command.\n", 156 | "# This contains all information used to generate the backtest result.\n", 157 | "stats = load_backtest_stats(backtest_dir)\n", 158 | "\n", 159 | "strategy = 'SampleStrategy'\n", 160 | "# All statistics are available per strategy, so if `--strategy-list` was used during backtest, this will be reflected here as well.\n", 161 | "# Example usages:\n", 162 | "print(stats['strategy'][strategy]['results_per_pair'])\n", 163 | "# Get pairlist used for this backtest\n", 164 | "print(stats['strategy'][strategy]['pairlist'])\n", 165 | "# Get market change (average change of all pairs from start to end of the backtest period)\n", 166 | "print(stats['strategy'][strategy]['market_change'])\n", 167 | "# Maximum drawdown ()\n", 168 | "print(stats['strategy'][strategy]['max_drawdown'])\n", 169 | "# Maximum drawdown start and end\n", 170 | "print(stats['strategy'][strategy]['drawdown_start'])\n", 171 | "print(stats['strategy'][strategy]['drawdown_end'])\n", 172 | "\n", 173 | "\n", 174 | "# Get strategy comparison (only relevant if multiple strategies were compared)\n", 175 | "print(stats['strategy_comparison'])\n" 176 | ] 177 | }, 178 | { 179 | "cell_type": "code", 180 | "execution_count": null, 181 | "metadata": {}, 182 | "outputs": [], 183 | "source": [ 184 | "# Load backtested trades as dataframe\n", 185 | "trades = load_backtest_data(backtest_dir)\n", 186 | "\n", 187 | "# Show value-counts per pair\n", 188 | "trades.groupby(\"pair\")[\"sell_reason\"].value_counts()" 189 | ] 190 | }, 191 | { 192 | "cell_type": "markdown", 193 | "metadata": {}, 194 | "source": [ 195 | "## Plotting daily profit / equity line" 196 | ] 197 | }, 198 | { 199 | "cell_type": "code", 200 | "execution_count": null, 201 | "metadata": {}, 202 | "outputs": [], 203 | "source": [ 204 | "# Plotting equity line (starting with 0 on day 1 and adding daily profit for each backtested day)\n", 205 | "\n", 206 | "from freqtrade.configuration import Configuration\n", 207 | "from freqtrade.data.btanalysis import load_backtest_data, load_backtest_stats\n", 208 | "import plotly.express as px\n", 209 | "import pandas as pd\n", 210 | "\n", 211 | "# strategy = 'SampleStrategy'\n", 212 | "# config = Configuration.from_files([\"user_data/config.json\"])\n", 213 | "# backtest_dir = config[\"user_data_dir\"] / \"backtest_results\"\n", 214 | "\n", 215 | "stats = load_backtest_stats(backtest_dir)\n", 216 | "strategy_stats = stats['strategy'][strategy]\n", 217 | "\n", 218 | "dates = []\n", 219 | "profits = []\n", 220 | "for date_profit in strategy_stats['daily_profit']:\n", 221 | " dates.append(date_profit[0])\n", 222 | " profits.append(date_profit[1])\n", 223 | "\n", 224 | "equity = 0\n", 225 | "equity_daily = []\n", 226 | "for daily_profit in profits:\n", 227 | " equity_daily.append(equity)\n", 228 | " equity += float(daily_profit)\n", 229 | "\n", 230 | "\n", 231 | "df = pd.DataFrame({'dates': dates,'equity_daily': equity_daily})\n", 232 | "\n", 233 | "fig = px.line(df, x=\"dates\", y=\"equity_daily\")\n", 234 | "fig.show()\n" 235 | ] 236 | }, 237 | { 238 | "cell_type": "markdown", 239 | "metadata": {}, 240 | "source": [ 241 | "### Load live trading results into a pandas dataframe\n", 242 | "\n", 243 | "In case you did already some trading and want to analyze your performance" 244 | ] 245 | }, 246 | { 247 | "cell_type": "code", 248 | "execution_count": null, 249 | "metadata": {}, 250 | "outputs": [], 251 | "source": [ 252 | "from freqtrade.data.btanalysis import load_trades_from_db\n", 253 | "\n", 254 | "# Fetch trades from database\n", 255 | "trades = load_trades_from_db(\"sqlite:///tradesv3.sqlite\")\n", 256 | "\n", 257 | "# Display results\n", 258 | "trades.groupby(\"pair\")[\"sell_reason\"].value_counts()" 259 | ] 260 | }, 261 | { 262 | "cell_type": "markdown", 263 | "metadata": {}, 264 | "source": [ 265 | "## Analyze the loaded trades for trade parallelism\n", 266 | "This can be useful to find the best `max_open_trades` parameter, when used with backtesting in conjunction with `--disable-max-market-positions`.\n", 267 | "\n", 268 | "`analyze_trade_parallelism()` returns a timeseries dataframe with an \"open_trades\" column, specifying the number of open trades for each candle." 269 | ] 270 | }, 271 | { 272 | "cell_type": "code", 273 | "execution_count": null, 274 | "metadata": {}, 275 | "outputs": [], 276 | "source": [ 277 | "from freqtrade.data.btanalysis import analyze_trade_parallelism\n", 278 | "\n", 279 | "# Analyze the above\n", 280 | "parallel_trades = analyze_trade_parallelism(trades, '5m')\n", 281 | "\n", 282 | "parallel_trades.plot()" 283 | ] 284 | }, 285 | { 286 | "cell_type": "markdown", 287 | "metadata": {}, 288 | "source": [ 289 | "## Plot results\n", 290 | "\n", 291 | "Freqtrade offers interactive plotting capabilities based on plotly." 292 | ] 293 | }, 294 | { 295 | "cell_type": "code", 296 | "execution_count": null, 297 | "metadata": {}, 298 | "outputs": [], 299 | "source": [ 300 | "from freqtrade.plot.plotting import generate_candlestick_graph\n", 301 | "# Limit graph period to keep plotly quick and reactive\n", 302 | "\n", 303 | "# Filter trades to one pair\n", 304 | "trades_red = trades.loc[trades['pair'] == pair]\n", 305 | "\n", 306 | "data_red = data['2019-06-01':'2019-06-10']\n", 307 | "# Generate candlestick graph\n", 308 | "graph = generate_candlestick_graph(pair=pair,\n", 309 | " data=data_red,\n", 310 | " trades=trades_red,\n", 311 | " indicators1=['sma20', 'ema50', 'ema55'],\n", 312 | " indicators2=['rsi', 'macd', 'macdsignal', 'macdhist']\n", 313 | " )\n", 314 | "\n", 315 | "\n" 316 | ] 317 | }, 318 | { 319 | "cell_type": "code", 320 | "execution_count": null, 321 | "metadata": {}, 322 | "outputs": [], 323 | "source": [ 324 | "# Show graph inline\n", 325 | "# graph.show()\n", 326 | "\n", 327 | "# Render graph in a seperate window\n", 328 | "graph.show(renderer=\"browser\")\n" 329 | ] 330 | }, 331 | { 332 | "cell_type": "markdown", 333 | "metadata": {}, 334 | "source": [ 335 | "## Plot average profit per trade as distribution graph" 336 | ] 337 | }, 338 | { 339 | "cell_type": "code", 340 | "execution_count": null, 341 | "metadata": {}, 342 | "outputs": [], 343 | "source": [ 344 | "import plotly.figure_factory as ff\n", 345 | "\n", 346 | "hist_data = [trades.profit_ratio]\n", 347 | "group_labels = ['profit_ratio'] # name of the dataset\n", 348 | "\n", 349 | "fig = ff.create_distplot(hist_data, group_labels,bin_size=0.01)\n", 350 | "fig.show()\n" 351 | ] 352 | }, 353 | { 354 | "cell_type": "markdown", 355 | "metadata": {}, 356 | "source": [ 357 | "Feel free to submit an issue or Pull Request enhancing this document if you would like to share ideas on how to best analyze the data." 358 | ] 359 | } 360 | ], 361 | "metadata": { 362 | "file_extension": ".py", 363 | "kernelspec": { 364 | "display_name": "Python 3", 365 | "language": "python", 366 | "name": "python3" 367 | }, 368 | "language_info": { 369 | "codemirror_mode": { 370 | "name": "ipython", 371 | "version": 3 372 | }, 373 | "file_extension": ".py", 374 | "mimetype": "text/x-python", 375 | "name": "python", 376 | "nbconvert_exporter": "python", 377 | "pygments_lexer": "ipython3", 378 | "version": "3.8.5" 379 | }, 380 | "mimetype": "text/x-python", 381 | "name": "python", 382 | "npconvert_exporter": "python", 383 | "pygments_lexer": "ipython3", 384 | "toc": { 385 | "base_numbering": 1, 386 | "nav_menu": {}, 387 | "number_sections": true, 388 | "sideBar": true, 389 | "skip_h1_title": false, 390 | "title_cell": "Table of Contents", 391 | "title_sidebar": "Contents", 392 | "toc_cell": false, 393 | "toc_position": {}, 394 | "toc_section_display": true, 395 | "toc_window_display": false 396 | }, 397 | "varInspector": { 398 | "cols": { 399 | "lenName": 16, 400 | "lenType": 16, 401 | "lenVar": 40 402 | }, 403 | "kernels_config": { 404 | "python": { 405 | "delete_cmd_postfix": "", 406 | "delete_cmd_prefix": "del ", 407 | "library": "var_list.py", 408 | "varRefreshCmd": "print(var_dic_list())" 409 | }, 410 | "r": { 411 | "delete_cmd_postfix": ") ", 412 | "delete_cmd_prefix": "rm(", 413 | "library": "var_list.r", 414 | "varRefreshCmd": "cat(var_dic_list()) " 415 | } 416 | }, 417 | "types_to_exclude": [ 418 | "module", 419 | "function", 420 | "builtin_function_or_method", 421 | "instance", 422 | "_Feature" 423 | ], 424 | "window_display": false 425 | }, 426 | "version": 3 427 | }, 428 | "nbformat": 4, 429 | "nbformat_minor": 4 430 | } 431 | -------------------------------------------------------------------------------- /user_data/strategies/CombinedBinHClucAndMADV6.py: -------------------------------------------------------------------------------- 1 | import freqtrade.vendor.qtpylib.indicators as qtpylib 2 | import numpy as np 3 | import talib.abstract as ta 4 | from freqtrade.persistence import Trade 5 | from freqtrade.strategy.interface import IStrategy 6 | from pandas import DataFrame 7 | from datetime import datetime, timedelta 8 | from freqtrade.strategy import merge_informative_pair 9 | 10 | 11 | ########################################################################################################### 12 | ## CombinedBinHClucAndMADV6 by ilya ## 13 | ## ## 14 | ## https://github.com/i1ya/freqtrade-strategies ## 15 | ## The stratagy most inspired by iterativ (authors of the CombinedBinHAndClucV6) ## 16 | ## ## ## 17 | ########################################################################################################### 18 | ## The main point of this strat is: ## 19 | ## - make drawdown as low as possible ## 20 | ## - buy at dip ## 21 | ## - sell quick as fast as you can (release money for the next buy) ## 22 | ## - soft check if market if rising ## 23 | ## - hard check is market if fallen ## 24 | ## ## 25 | ## ## 26 | ########################################################################################################### 27 | ## What's new ## 28 | ## ## 29 | ## + change ROI from 0-10 min to 2.9% (I feel lucky) ## 30 | ## + try to exclude pumping ## 31 | ## ## 32 | ########################################################################################################### 33 | ## GENERAL RECOMMENDATIONS ## 34 | ## ## 35 | ## For optimal performance, suggested to use between 2 and 4 open trades, with unlimited stake. ## 36 | ## With my pairlist which can be found in this repo. ## 37 | ## ## 38 | ## Ensure that you don't override any variables in your config.json. Especially ## 39 | ## the timeframe (must be 5m). ## 40 | ## ## 41 | ## sell_profit_only: ## 42 | ## True - risk more (gives you higher profit and higher Drawdown) ## 43 | ## False (default) - risk less (gives you less ~10-15% profit and much lower Drawdown) ## 44 | ## ## 45 | ########################################################################################################### 46 | ## DONATIONS 2 @iterativ (author of the original strategy) ## 47 | ## ## 48 | ## Absolutely not required. However, will be accepted as a token of appreciation. ## 49 | ## ## 50 | ## BTC: bc1qvflsvddkmxh7eqhc4jyu5z5k6xcw3ay8jl49sk ## 51 | ## ETH: 0x83D3cFb8001BDC5d2211cBeBB8cB3461E5f7Ec91 ## 52 | ## ## 53 | ########################################################################################################### 54 | 55 | # SSL Channels 56 | def SSLChannels(dataframe, length=7): 57 | df = dataframe.copy() 58 | df["ATR"] = ta.ATR(df, timeperiod=14) 59 | df["smaHigh"] = df["high"].rolling(length).mean() + df["ATR"] 60 | df["smaLow"] = df["low"].rolling(length).mean() - df["ATR"] 61 | df["hlv"] = np.where( 62 | df["close"] > df["smaHigh"], 1, np.where(df["close"] < df["smaLow"], -1, np.NAN) 63 | ) 64 | df["hlv"] = df["hlv"].ffill() 65 | df["sslDown"] = np.where(df["hlv"] < 0, df["smaHigh"], df["smaLow"]) 66 | df["sslUp"] = np.where(df["hlv"] < 0, df["smaLow"], df["smaHigh"]) 67 | return df["sslDown"], df["sslUp"] 68 | 69 | 70 | class CombinedBinHClucAndMADV6(IStrategy): 71 | INTERFACE_VERSION = 2 72 | 73 | minimal_roi = { 74 | "0": 0.029, # I feel lucky! 75 | "10": 0.021, 76 | "40": 0.005, 77 | } 78 | 79 | stoploss = -0.99 # effectively disabled. 80 | 81 | timeframe = "5m" 82 | inf_1h = "1h" 83 | 84 | # Sell signal 85 | use_sell_signal = True 86 | sell_profit_only = False 87 | sell_profit_offset = ( 88 | 0.001 # it doesn't meant anything, just to guarantee there is a minimal profit. 89 | ) 90 | ignore_roi_if_buy_signal = False 91 | 92 | # Trailing stoploss 93 | trailing_stop = False 94 | trailing_only_offset_is_reached = False 95 | trailing_stop_positive = 0.01 96 | trailing_stop_positive_offset = 0.025 97 | 98 | # Custom stoploss 99 | use_custom_stoploss = True 100 | 101 | # Run "populate_indicators()" only for new candle. 102 | process_only_new_candles = False 103 | 104 | # Number of candles the strategy requires before producing valid signals 105 | startup_candle_count: int = 200 106 | 107 | # Optional order type mapping. 108 | order_types = { 109 | "buy": "limit", 110 | "sell": "limit", 111 | "stoploss": "market", 112 | "stoploss_on_exchange": False, 113 | } 114 | 115 | def custom_stoploss( 116 | self, 117 | pair: str, 118 | trade: "Trade", 119 | current_time: datetime, 120 | current_rate: float, 121 | current_profit: float, 122 | **kwargs 123 | ) -> float: 124 | # Manage losing trades and open room for better ones. 125 | 126 | if (current_profit < 0) & ( 127 | current_time - timedelta(minutes=240) > trade.open_date_utc 128 | ): 129 | return 0.01 130 | return 0.99 131 | 132 | def informative_pairs(self): 133 | pairs = self.dp.current_whitelist() 134 | informative_pairs = [(pair, "1h") for pair in pairs] 135 | return informative_pairs 136 | 137 | def informative_1h_indicators( 138 | self, dataframe: DataFrame, metadata: dict 139 | ) -> DataFrame: 140 | assert self.dp, "DataProvider is required for multiple timeframes." 141 | # Get the informative pair 142 | informative_1h = self.dp.get_pair_dataframe( 143 | pair=metadata["pair"], timeframe=self.inf_1h 144 | ) 145 | # EMA 146 | informative_1h["ema_50"] = ta.EMA(informative_1h, timeperiod=50) 147 | informative_1h["ema_200"] = ta.EMA(informative_1h, timeperiod=200) 148 | # RSI 149 | informative_1h["rsi"] = ta.RSI(informative_1h, timeperiod=14) 150 | 151 | # SSL Channels 152 | ssl_down_1h, ssl_up_1h = SSLChannels(informative_1h, 20) 153 | informative_1h["ssl_down"] = ssl_down_1h 154 | informative_1h["ssl_up"] = ssl_up_1h 155 | 156 | return informative_1h 157 | 158 | def normal_tf_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: 159 | 160 | # strategy ClucMay72018 161 | bollinger = qtpylib.bollinger_bands( 162 | qtpylib.typical_price(dataframe), window=20, stds=2 163 | ) 164 | dataframe["bb_lowerband"] = bollinger["lower"] 165 | dataframe["bb_middleband"] = bollinger["mid"] 166 | dataframe["bb_upperband"] = bollinger["upper"] 167 | dataframe["ema_slow"] = ta.EMA(dataframe, timeperiod=50) 168 | dataframe["volume_mean_slow"] = dataframe["volume"].rolling(window=30).mean() 169 | 170 | # EMA 171 | dataframe["ema_200"] = ta.EMA(dataframe, timeperiod=200) 172 | 173 | dataframe["ema_26"] = ta.EMA(dataframe, timeperiod=26) 174 | dataframe["ema_12"] = ta.EMA(dataframe, timeperiod=12) 175 | 176 | # SMA 177 | dataframe["sma_5"] = ta.EMA(dataframe, timeperiod=5) 178 | 179 | # RSI 180 | dataframe["rsi"] = ta.RSI(dataframe, timeperiod=14) 181 | 182 | return dataframe 183 | 184 | def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: 185 | # The indicators for the 1h informative timeframe 186 | informative_1h = self.informative_1h_indicators(dataframe, metadata) 187 | dataframe = merge_informative_pair( 188 | dataframe, informative_1h, self.timeframe, self.inf_1h, ffill=True 189 | ) 190 | 191 | # The indicators for the normal (5m) timeframe 192 | dataframe = self.normal_tf_indicators(dataframe, metadata) 193 | 194 | return dataframe 195 | 196 | def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: 197 | 198 | dataframe.loc[ 199 | # When market at bull mode (guard) 200 | ( # strategy ClucMay72018 201 | (dataframe["close"] > dataframe["ema_200"]) 202 | & (dataframe["close"] > dataframe["ema_200_1h"]) 203 | & (dataframe["close"] < dataframe["ema_slow"]) 204 | & (dataframe["close"] < 0.99 * dataframe["bb_lowerband"]) 205 | & ( # Guard is on, candle should dig not so hard (0,99) 206 | dataframe["volume_mean_slow"] 207 | > dataframe["volume_mean_slow"].shift(30) * 0.4 208 | ) 209 | & # Try to exclude pumping 210 | # (dataframe['volume'] < (dataframe['volume'].shift() * 4)) & # Don't buy if someone drop the market. 211 | (dataframe["volume"] > 0) 212 | ) 213 | | 214 | # When market at bear mode (without guard) 215 | ( # strategy ClucMay72018 216 | (dataframe["close"] < dataframe["ema_slow"]) 217 | & (dataframe["close"] < 0.975 * dataframe["bb_lowerband"]) 218 | & ( # Guard is off, candle should dig hard (0,975) 219 | dataframe["volume"] < (dataframe["volume"].shift() * 4) 220 | ) 221 | & (dataframe["rsi_1h"] < 15) # Don't buy if someone drop the market. 222 | & ( # Buy only at dip 223 | dataframe["volume_mean_slow"] 224 | > dataframe["volume_mean_slow"].shift(30) * 0.4 225 | ) 226 | & ( # Try to exclude pumping 227 | dataframe["volume"] > 0 228 | ) # Make sure Volume is not 0 229 | ) 230 | | 231 | # When market at bull mode (guard) 232 | ( # strategy MACD Low buy 233 | (dataframe["close"] > dataframe["ema_200"]) 234 | & (dataframe["close"] > dataframe["ema_200_1h"]) 235 | & (dataframe["ema_26"] > dataframe["ema_12"]) 236 | & ( 237 | (dataframe["ema_26"] - dataframe["ema_12"]) 238 | > (dataframe["open"] * 0.02) 239 | ) 240 | & ( 241 | (dataframe["ema_26"].shift() - dataframe["ema_12"].shift()) 242 | > (dataframe["open"] / 100) 243 | ) 244 | & (dataframe["volume"] < (dataframe["volume"].shift() * 4)) 245 | & ( # Don't buy if someone drop the market. 246 | dataframe["close"] < (dataframe["bb_lowerband"]) 247 | ) 248 | & ( 249 | dataframe["volume_mean_slow"] 250 | > dataframe["volume_mean_slow"].shift(30) * 0.4 251 | ) 252 | & ( # Try to exclude pumping 253 | dataframe["volume"] > 0 254 | ) # Make sure Volume is not 0 255 | ) 256 | | 257 | # When market at bear mode (without guard) 258 | ( # strategy MACD Low buy 259 | (dataframe["ema_26"] > dataframe["ema_12"]) 260 | & ( 261 | (dataframe["ema_26"] - dataframe["ema_12"]) 262 | > (dataframe["open"] * 0.03) 263 | ) 264 | & ( 265 | (dataframe["ema_26"].shift() - dataframe["ema_12"].shift()) 266 | > (dataframe["open"] / 100) 267 | ) 268 | & (dataframe["volume"] < (dataframe["volume"].shift() * 4)) 269 | & ( # Don't buy if someone drop the market. 270 | dataframe["close"] < (dataframe["bb_lowerband"]) 271 | ) 272 | & (dataframe["volume"] > 0) # Make sure Volume is not 0 273 | ) 274 | | ( 275 | (dataframe["close"] < dataframe["sma_5"]) 276 | & (dataframe["ssl_up_1h"] > dataframe["ssl_down_1h"]) 277 | & (dataframe["ema_slow"] > dataframe["ema_200"]) 278 | & (dataframe["ema_50_1h"] > dataframe["ema_200_1h"]) 279 | & (dataframe["rsi"] < dataframe["rsi_1h"] - 43.276) 280 | & (dataframe["volume"] > 0) 281 | ), 282 | "buy", 283 | ] = 1 284 | 285 | return dataframe 286 | 287 | def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: 288 | dataframe.loc[ 289 | ( 290 | (dataframe["close"] > dataframe["bb_middleband"] * 1.01) 291 | & ( # Don't be gready, sell fast 292 | dataframe["volume"] > 0 293 | ) # Make sure Volume is not 0 294 | ), 295 | "sell", 296 | ] = 1 297 | return dataframe 298 | -------------------------------------------------------------------------------- /user_data/strategies/nfi/BB_RPB_TSL_RNG.py: -------------------------------------------------------------------------------- 1 | # --- Do not remove these libs --- 2 | import freqtrade.vendor.qtpylib.indicators as qtpylib 3 | import numpy as np 4 | import talib.abstract as ta 5 | import pandas_ta as pta 6 | 7 | from freqtrade.persistence import Trade 8 | from freqtrade.strategy.interface import IStrategy 9 | from pandas import DataFrame, Series, DatetimeIndex, merge 10 | from datetime import datetime, timedelta 11 | from freqtrade.strategy import merge_informative_pair, CategoricalParameter, DecimalParameter, IntParameter, stoploss_from_open 12 | from functools import reduce 13 | from technical.indicators import RMI, zema 14 | 15 | # -------------------------------- 16 | def EWO(dataframe, ema_length=5, ema2_length=35): 17 | df = dataframe.copy() 18 | ema1 = ta.EMA(df, timeperiod=ema_length) 19 | ema2 = ta.EMA(df, timeperiod=ema2_length) 20 | emadif = (ema1 - ema2) / df['low'] * 100 21 | return emadif 22 | 23 | # Williams %R 24 | def williams_r(dataframe: DataFrame, period: int = 14) -> Series: 25 | """Williams %R, or just %R, is a technical analysis oscillator showing the current closing price in relation to the high and low 26 | of the past N days (for a given N). It was developed by a publisher and promoter of trading materials, Larry Williams. 27 | Its purpose is to tell whether a stock or commodity market is trading near the high or the low, or somewhere in between, 28 | of its recent trading range. 29 | The oscillator is on a negative scale, from −100 (lowest) up to 0 (highest). 30 | """ 31 | 32 | highest_high = dataframe["high"].rolling(center=False, window=period).max() 33 | lowest_low = dataframe["low"].rolling(center=False, window=period).min() 34 | 35 | WR = Series( 36 | (highest_high - dataframe["close"]) / (highest_high - lowest_low), 37 | name=f"{period} Williams %R", 38 | ) 39 | 40 | return WR * -100 41 | 42 | class BB_RPB_TSL_RNG(IStrategy): 43 | ''' 44 | BB_RPB_TSL 45 | @author jilv220 46 | Simple bollinger brand strategy inspired by this blog ( https://hacks-for-life.blogspot.com/2020/12/freqtrade-notes.html ) 47 | RPB, which stands for Real Pull Back, taken from ( https://github.com/GeorgeMurAlkh/freqtrade-stuff/blob/main/user_data/strategies/TheRealPullbackV2.py ) 48 | The trailing custom stoploss taken from BigZ04_TSL from Perkmeister ( modded by ilya ) 49 | I modified it to better suit my taste and added Hyperopt for this strategy. 50 | ''' 51 | 52 | ########################################################################## 53 | 54 | # Hyperopt result area 55 | 56 | # buy space 57 | buy_params = { 58 | ## 59 | "buy_btc_safe": -289, 60 | "buy_btc_safe_1d": -0.05, 61 | ## 62 | "buy_threshold": 0.003, 63 | "buy_bb_factor": 0.999, 64 | "buy_bb_delta": 0.025, 65 | "buy_bb_width": 0.095, 66 | ## 67 | "buy_cci": -116, 68 | "buy_cci_length": 25, 69 | "buy_rmi": 49, 70 | "buy_rmi_length": 17, 71 | "buy_srsi_fk": 32, 72 | ## 73 | "buy_closedelta": 12.148, 74 | "buy_ema_diff": 0.022, 75 | ## 76 | "buy_adx": 20, 77 | "buy_fastd": 20, 78 | "buy_fastk": 22, 79 | "buy_ema_cofi": 0.98, 80 | "buy_ewo_high": 4.179, 81 | ## 82 | "buy_ema_high_2": 1.087, 83 | "buy_ema_low_2": 0.970, 84 | ## 85 | } 86 | 87 | # sell space 88 | sell_params = { 89 | "pHSL": -0.178, 90 | "pPF_1": 0.019, 91 | "pPF_2": 0.065, 92 | "pSL_1": 0.019, 93 | "pSL_2": 0.062, 94 | "sell_btc_safe": -389, 95 | "base_nb_candles_sell": 24, 96 | "high_offset": 0.991, 97 | "high_offset_2": 0.997 98 | } 99 | 100 | # really hard to use this 101 | minimal_roi = { 102 | "0": 0.10, 103 | } 104 | 105 | # Optimal timeframe for the strategy 106 | timeframe = '5m' 107 | inf_1h = '1h' 108 | 109 | # Disabled 110 | stoploss = -0.99 111 | 112 | # Custom stoploss 113 | use_custom_stoploss = True 114 | use_sell_signal = True 115 | 116 | process_only_new_candles = True 117 | 118 | ############################################################################ 119 | 120 | ## Buy params 121 | 122 | is_optimize_dip = False 123 | buy_rmi = IntParameter(30, 50, default=35, optimize= is_optimize_dip) 124 | buy_cci = IntParameter(-135, -90, default=-133, optimize= is_optimize_dip) 125 | buy_srsi_fk = IntParameter(30, 50, default=25, optimize= is_optimize_dip) 126 | buy_cci_length = IntParameter(25, 45, default=25, optimize = is_optimize_dip) 127 | buy_rmi_length = IntParameter(8, 20, default=8, optimize = is_optimize_dip) 128 | 129 | is_optimize_break = False 130 | buy_bb_width = DecimalParameter(0.05, 0.2, default=0.15, optimize = is_optimize_break) 131 | buy_bb_delta = DecimalParameter(0.025, 0.08, default=0.04, optimize = is_optimize_break) 132 | 133 | is_optimize_local_dip = False 134 | buy_ema_diff = DecimalParameter(0.022, 0.027, default=0.025, optimize = is_optimize_local_dip) 135 | buy_bb_factor = DecimalParameter(0.990, 0.999, default=0.995, optimize = False) 136 | buy_closedelta = DecimalParameter(12.0, 18.0, default=15.0, optimize = is_optimize_local_dip) 137 | 138 | is_optimize_ewo = False 139 | buy_rsi_fast = IntParameter(35, 50, default=45, optimize = False) 140 | buy_rsi = IntParameter(15, 30, default=35, optimize = False) 141 | buy_ewo = DecimalParameter(-6.0, 5, default=-5.585, optimize = is_optimize_ewo) 142 | buy_ema_low = DecimalParameter(0.9, 0.99, default=0.942 , optimize = is_optimize_ewo) 143 | buy_ema_high = DecimalParameter(0.95, 1.2, default=1.084 , optimize = is_optimize_ewo) 144 | 145 | is_optimize_ewo_2 = False 146 | buy_ema_low_2 = DecimalParameter(0.96, 0.978, default=0.96 , optimize = is_optimize_ewo_2) 147 | buy_ema_high_2 = DecimalParameter(1.05, 1.2, default=1.09 , optimize = is_optimize_ewo_2) 148 | 149 | is_optimize_cofi = False 150 | buy_ema_cofi = DecimalParameter(0.96, 0.98, default=0.97 , optimize = is_optimize_cofi) 151 | buy_fastk = IntParameter(20, 30, default=20, optimize = is_optimize_cofi) 152 | buy_fastd = IntParameter(20, 30, default=20, optimize = is_optimize_cofi) 153 | buy_adx = IntParameter(20, 30, default=30, optimize = is_optimize_cofi) 154 | buy_ewo_high = DecimalParameter(2, 12, default=3.553, optimize = is_optimize_cofi) 155 | 156 | is_optimize_btc_safe = False 157 | buy_btc_safe = IntParameter(-300, 50, default=-200, optimize = is_optimize_btc_safe) 158 | buy_btc_safe_1d = DecimalParameter(-0.075, -0.025, default=-0.05, optimize = is_optimize_btc_safe) 159 | buy_threshold = DecimalParameter(0.003, 0.012, default=0.008, optimize = is_optimize_btc_safe) 160 | 161 | # Buy params toggle 162 | buy_is_dip_enabled = CategoricalParameter([True, False], default=True, space='buy', optimize=False, load=True) 163 | buy_is_break_enabled = CategoricalParameter([True, False], default=True, space='buy', optimize=False, load=True) 164 | 165 | ## Sell params 166 | sell_btc_safe = IntParameter(-400, -300, default=-365, optimize = True) 167 | base_nb_candles_sell = IntParameter(5, 80, default=sell_params['base_nb_candles_sell'], space='sell', optimize=True) 168 | high_offset = DecimalParameter(0.95, 1.1, default=sell_params['high_offset'], space='sell', optimize=True) 169 | high_offset_2 = DecimalParameter(0.99, 1.5, default=sell_params['high_offset_2'], space='sell', optimize=True) 170 | 171 | ## Trailing params 172 | 173 | # hard stoploss profit 174 | pHSL = DecimalParameter(-0.200, -0.040, default=-0.08, decimals=3, space='sell', load=True) 175 | # profit threshold 1, trigger point, SL_1 is used 176 | pPF_1 = DecimalParameter(0.008, 0.020, default=0.016, decimals=3, space='sell', load=True) 177 | pSL_1 = DecimalParameter(0.008, 0.020, default=0.011, decimals=3, space='sell', load=True) 178 | 179 | # profit threshold 2, SL_2 is used 180 | pPF_2 = DecimalParameter(0.040, 0.100, default=0.080, decimals=3, space='sell', load=True) 181 | pSL_2 = DecimalParameter(0.020, 0.070, default=0.040, decimals=3, space='sell', load=True) 182 | 183 | ############################################################################ 184 | 185 | def informative_pairs(self): 186 | 187 | informative_pairs = [("BTC/USDT", "5m")] 188 | 189 | return informative_pairs 190 | 191 | ############################################################################ 192 | 193 | ## Custom Trailing stoploss ( credit to Perkmeister for this custom stoploss to help the strategy ride a green candle ) 194 | def custom_stoploss(self, pair: str, trade: 'Trade', current_time: datetime, 195 | current_rate: float, current_profit: float, **kwargs) -> float: 196 | 197 | # hard stoploss profit 198 | HSL = self.pHSL.value 199 | PF_1 = self.pPF_1.value 200 | SL_1 = self.pSL_1.value 201 | PF_2 = self.pPF_2.value 202 | SL_2 = self.pSL_2.value 203 | 204 | # For profits between PF_1 and PF_2 the stoploss (sl_profit) used is linearly interpolated 205 | # between the values of SL_1 and SL_2. For all profits above PL_2 the sl_profit value 206 | # rises linearly with current profit, for profits below PF_1 the hard stoploss profit is used. 207 | 208 | if (current_profit > PF_2): 209 | sl_profit = SL_2 + (current_profit - PF_2) 210 | elif (current_profit > PF_1): 211 | sl_profit = SL_1 + ((current_profit - PF_1) * (SL_2 - SL_1) / (PF_2 - PF_1)) 212 | else: 213 | sl_profit = HSL 214 | 215 | # Only for hyperopt invalid return 216 | if (sl_profit >= current_profit): 217 | return -0.99 218 | 219 | return stoploss_from_open(sl_profit, current_profit) 220 | 221 | ############################################################################ 222 | 223 | def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame: 224 | 225 | assert self.dp, "DataProvider is required for multiple timeframes." 226 | 227 | # Bollinger bands (hyperopt hard to implement) 228 | bollinger2 = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=2) 229 | dataframe['bb_lowerband2'] = bollinger2['lower'] 230 | dataframe['bb_middleband2'] = bollinger2['mid'] 231 | dataframe['bb_upperband2'] = bollinger2['upper'] 232 | 233 | bollinger3 = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=20, stds=3) 234 | dataframe['bb_lowerband3'] = bollinger3['lower'] 235 | dataframe['bb_middleband3'] = bollinger3['mid'] 236 | dataframe['bb_upperband3'] = bollinger3['upper'] 237 | 238 | ### BTC protection 239 | 240 | # BTC info 241 | inf_tf = '5m' 242 | informative = self.dp.get_pair_dataframe('BTC/USDT', timeframe=inf_tf) 243 | informative_past = informative.copy().shift(1) # Get recent BTC info 244 | 245 | # BTC 5m dump protection 246 | informative_past_source = (informative_past['open'] + informative_past['close'] + informative_past['high'] + informative_past['low']) / 4 # Get BTC price 247 | informative_threshold = informative_past_source * self.buy_threshold.value # BTC dump n% in 5 min 248 | informative_past_delta = informative_past['close'].shift(1) - informative_past['close'] # should be positive if dump 249 | informative_diff = informative_threshold - informative_past_delta # Need be larger than 0 250 | dataframe['btc_threshold'] = informative_threshold 251 | dataframe['btc_diff'] = informative_diff 252 | 253 | # BTC 1d dump protection 254 | informative_past_1d = informative.copy().shift(288) 255 | informative_past_source_1d = (informative_past_1d['open'] + informative_past_1d['close'] + informative_past_1d['high'] + informative_past_1d['low']) / 4 256 | dataframe['btc_5m'] = informative_past_source 257 | dataframe['btc_1d'] = informative_past_source_1d 258 | 259 | ### Other checks 260 | 261 | dataframe['bb_width'] = ((dataframe['bb_upperband2'] - dataframe['bb_lowerband2']) / dataframe['bb_middleband2']) 262 | dataframe['bb_delta'] = ((dataframe['bb_lowerband2'] - dataframe['bb_lowerband3']) / dataframe['bb_lowerband2']) 263 | dataframe['bb_bottom_cross'] = qtpylib.crossed_below(dataframe['close'], dataframe['bb_lowerband3']).astype('int') 264 | 265 | # CCI hyperopt 266 | for val in self.buy_cci_length.range: 267 | dataframe[f'cci_length_{val}'] = ta.CCI(dataframe, val) 268 | 269 | dataframe['cci'] = ta.CCI(dataframe, 26) 270 | dataframe['cci_long'] = ta.CCI(dataframe, 170) 271 | 272 | # RMI hyperopt 273 | for val in self.buy_rmi_length.range: 274 | dataframe[f'rmi_length_{val}'] = RMI(dataframe, length=val, mom=4) 275 | #dataframe['rmi'] = RMI(dataframe, length=8, mom=4) 276 | 277 | # SRSI hyperopt ? 278 | stoch = ta.STOCHRSI(dataframe, 15, 20, 2, 2) 279 | dataframe['srsi_fk'] = stoch['fastk'] 280 | dataframe['srsi_fd'] = stoch['fastd'] 281 | 282 | # BinH 283 | dataframe['closedelta'] = (dataframe['close'] - dataframe['close'].shift()).abs() 284 | 285 | # SMA 286 | dataframe['sma_15'] = ta.SMA(dataframe, timeperiod=15) 287 | dataframe['sma_30'] = ta.SMA(dataframe, timeperiod=30) 288 | 289 | # CTI 290 | dataframe['cti'] = pta.cti(dataframe["close"], length=20) 291 | 292 | # EMA 293 | dataframe['ema_8'] = ta.EMA(dataframe, timeperiod=8) 294 | dataframe['ema_12'] = ta.EMA(dataframe, timeperiod=12) 295 | dataframe['ema_13'] = ta.EMA(dataframe, timeperiod=13) 296 | dataframe['ema_16'] = ta.EMA(dataframe, timeperiod=16) 297 | dataframe['ema_26'] = ta.EMA(dataframe, timeperiod=26) 298 | dataframe['hma_50'] = qtpylib.hull_moving_average(dataframe['close'], window=50) 299 | dataframe['ema_100'] = ta.EMA(dataframe, timeperiod=100) 300 | dataframe['sma_9'] = ta.SMA(dataframe, timeperiod=9) 301 | 302 | # RSI 303 | dataframe['rsi'] = ta.RSI(dataframe, timeperiod=14) 304 | dataframe['rsi_fast'] = ta.RSI(dataframe, timeperiod=4) 305 | dataframe['rsi_slow'] = ta.RSI(dataframe, timeperiod=20) 306 | 307 | # Elliot 308 | dataframe['EWO'] = EWO(dataframe, 50, 200) 309 | 310 | # Cofi 311 | stoch_fast = ta.STOCHF(dataframe, 5, 3, 0, 3, 0) 312 | dataframe['fastd'] = stoch_fast['fastd'] 313 | dataframe['fastk'] = stoch_fast['fastk'] 314 | dataframe['adx'] = ta.ADX(dataframe) 315 | 316 | # Williams %R 317 | dataframe['r_14'] = williams_r(dataframe, period=14) 318 | 319 | # Volume 320 | dataframe['volume_mean_4'] = dataframe['volume'].rolling(4).mean().shift(1) 321 | 322 | 323 | # Calculate all ma_sell values 324 | for val in self.base_nb_candles_sell.range: 325 | dataframe[f'ma_sell_{val}'] = ta.EMA(dataframe, timeperiod=val) 326 | 327 | return dataframe 328 | 329 | def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: 330 | 331 | 332 | conditions = [] 333 | dataframe.loc[:, 'buy_tag'] = '' 334 | 335 | if self.buy_is_dip_enabled.value: 336 | 337 | is_dip = ( 338 | (dataframe[f'rmi_length_{self.buy_rmi_length.value}'] < self.buy_rmi.value) & 339 | (dataframe[f'cci_length_{self.buy_cci_length.value}'] <= self.buy_cci.value) & 340 | (dataframe['srsi_fk'] < self.buy_srsi_fk.value) 341 | ) 342 | 343 | #conditions.append(is_dip) 344 | 345 | if self.buy_is_break_enabled.value: 346 | 347 | is_break = ( 348 | 349 | ( (dataframe['bb_delta'] > self.buy_bb_delta.value) #"buy_bb_delta": 0.025 0.036 350 | & #"buy_bb_width": 0.095 0.133 351 | (dataframe['bb_width'] > self.buy_bb_width.value) 352 | ) 353 | & 354 | (dataframe['closedelta'] > dataframe['close'] * self.buy_closedelta.value / 1000 ) & # from BinH 355 | (dataframe['close'] < dataframe['bb_lowerband3'] * self.buy_bb_factor.value) 356 | ) 357 | #conditions.append(is_break) 358 | 359 | is_local_uptrend = ( # from NFI next gen 360 | 361 | (dataframe['ema_26'] > dataframe['ema_12']) & 362 | (dataframe['ema_26'] - dataframe['ema_12'] > dataframe['open'] * self.buy_ema_diff.value) & 363 | (dataframe['ema_26'].shift() - dataframe['ema_12'].shift() > dataframe['open'] / 100) & 364 | (dataframe['close'] < dataframe['bb_lowerband2'] * self.buy_bb_factor.value) & 365 | (dataframe['closedelta'] > dataframe['close'] * self.buy_closedelta.value / 1000 ) 366 | ) 367 | 368 | is_ewo = ( # from SMA offset 369 | (dataframe['rsi_fast'] < self.buy_rsi_fast.value) & 370 | (dataframe['close'] < dataframe['ema_8'] * self.buy_ema_low.value) & 371 | (dataframe['EWO'] > self.buy_ewo.value) & 372 | (dataframe['close'] < dataframe['ema_16'] * self.buy_ema_high.value) & 373 | (dataframe['rsi'] < self.buy_rsi.value) 374 | ) 375 | 376 | is_ewo_2 = ( 377 | (dataframe['rsi_fast'] < self.buy_rsi_fast.value) & 378 | (dataframe['close'] < dataframe['ema_8'] * self.buy_ema_low_2.value) & 379 | (dataframe['EWO'] > self.buy_ewo_high.value) & 380 | (dataframe['close'] < dataframe['ema_16'] * self.buy_ema_high_2.value) & 381 | (dataframe['rsi'] < self.buy_rsi.value) 382 | ) 383 | 384 | is_cofi = ( 385 | (dataframe['open'] < dataframe['ema_8'] * self.buy_ema_cofi.value) & 386 | (qtpylib.crossed_above(dataframe['fastk'], dataframe['fastd'])) & 387 | (dataframe['fastk'] < self.buy_fastk.value) & 388 | (dataframe['fastd'] < self.buy_fastd.value) & 389 | (dataframe['adx'] > self.buy_adx.value) & 390 | (dataframe['EWO'] > self.buy_ewo_high.value) 391 | ) 392 | 393 | # NFI quick mode 394 | 395 | is_nfi_32 = ( 396 | (dataframe['rsi_slow'] < dataframe['rsi_slow'].shift(1)) & 397 | (dataframe['rsi_fast'] < 46) & 398 | (dataframe['rsi'] > 19) & 399 | (dataframe['close'] < dataframe['sma_15'] * 0.942) & 400 | (dataframe['cti'] < -0.86) 401 | ) 402 | 403 | is_nfi_33 = ( 404 | (dataframe['close'] < (dataframe['ema_13'] * 0.978)) & 405 | (dataframe['EWO'] > 8) & 406 | (dataframe['cti'] < -0.88) & 407 | (dataframe['rsi'] < 32) & 408 | (dataframe['r_14'] < -98.0) & 409 | (dataframe['volume'] < (dataframe['volume_mean_4'] * 2.5)) 410 | ) 411 | 412 | # is_btc_safe = ( 413 | 414 | # (dataframe['btc_diff'] > self.buy_btc_safe.value) 415 | # &(dataframe['btc_5m'] - dataframe['btc_1d'] > dataframe['btc_1d'] * self.buy_btc_safe_1d.value) 416 | # &(dataframe['volume'] > 0) # Make sure Volume is not 0 417 | # ) 418 | 419 | is_BB_checked = is_dip & is_break 420 | 421 | #print(dataframe['btc_5m']) 422 | #print(dataframe['btc_1d']) 423 | #print(dataframe['btc_5m'] - dataframe['btc_1d']) 424 | #print(dataframe['btc_1d'] * -0.025) 425 | #print(dataframe['btc_5m'] - dataframe['btc_1d'] > dataframe['btc_1d'] * -0.025) 426 | 427 | ## condition append 428 | conditions.append(is_BB_checked) # ~1.7 89% 429 | dataframe.loc[is_BB_checked, 'buy_tag'] += 'bb ' 430 | 431 | conditions.append(is_local_uptrend) # ~3.84 90.2% 432 | dataframe.loc[is_local_uptrend, 'buy_tag'] += 'local uptrend ' 433 | 434 | conditions.append(is_ewo) # ~2.26 93.5% 435 | dataframe.loc[is_ewo, 'buy_tag'] += 'ewo ' 436 | 437 | conditions.append(is_ewo_2) # ~3.68 90.3% 438 | dataframe.loc[is_ewo_2, 'buy_tag'] += 'ewo2 ' 439 | 440 | conditions.append(is_cofi) # ~3.21 90.8% 441 | dataframe.loc[is_cofi, 'buy_tag'] += 'cofi ' 442 | 443 | conditions.append(is_nfi_32) # ~2.43 91.3% 444 | dataframe.loc[is_nfi_32, 'buy_tag'] += 'nfi 32 ' 445 | 446 | conditions.append(is_nfi_33) # ~0.11 100% 447 | dataframe.loc[is_nfi_33, 'buy_tag'] += 'nfi 33 ' 448 | 449 | if conditions: 450 | dataframe.loc[reduce(lambda x, y: x | y, conditions), 'buy' ] = 1 451 | 452 | return dataframe 453 | 454 | def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame: 455 | conditions = [] 456 | 457 | conditions.append( 458 | ( 459 | (dataframe['close'] > dataframe['sma_9'])& 460 | (dataframe['close'] > (dataframe[f'ma_sell_{self.base_nb_candles_sell.value}'] * self.high_offset_2.value)) & 461 | (dataframe['rsi']>50)& 462 | (dataframe['volume'] > 0)& 463 | (dataframe['rsi_fast'] > dataframe['rsi_slow']) 464 | 465 | ) 466 | | 467 | ( 468 | (dataframe['sma_9'] > (dataframe['sma_9'].shift(1) + dataframe['sma_9'].shift(1)*0.005 )) & 469 | (dataframe['close'] < dataframe['hma_50'])& 470 | (dataframe['close'] > (dataframe[f'ma_sell_{self.base_nb_candles_sell.value}'] * self.high_offset.value)) & 471 | (dataframe['volume'] > 0)& 472 | (dataframe['rsi_fast']>dataframe['rsi_slow']) 473 | ) 474 | 475 | ) 476 | 477 | if conditions: 478 | dataframe.loc[ 479 | reduce(lambda x, y: x | y, conditions), 480 | 'sell' 481 | ]=1 482 | 483 | return dataframe 484 | --------------------------------------------------------------------------------