Timeframe
N/A
Direction
Long Only
Stoploss
-100.0%
Trailing Stop
Yes
ROI
0m: 100.0%
Interface Version
N/A
Startup Candles
N/A
Indicators
1
freqtrade/freqtrade-strategies
Sample strategy implementing Informative Pairs - compares stake_currency with USDT. Not performing very well - but should serve as an example how to use a referential pair against USDT. author@: xmatthias github@: https://github.com/freqtrade/freqtrade-strategies
freqtrade/freqtrade-strategies
Strategy 003 author@: Gerald Lonlas github@: https://github.com/freqtrade/freqtrade-strategies
freqtrade/freqtrade-strategies
# MyStrategyNew6
# Author: @ntsd (Jirawat Boonkumnerd)
# Github: https://github.com/ntsd
# V2 Update: Add periods for each timeframe
# V3 Update: Add operators
# V6 Update: Optimise by categories
# freqtrade download-data --exchange binance -t 5m --days 500
# freqtrade download-data --exchange binance -t 15m --days 500
# freqtrade download-data --exchange binance -t 30m --days 500
# freqtrade download-data --exchange binance -t 1h --days 500
# freqtrade download-data --exchange binance -t 4h --days 500
# ShortTradeDurHyperOptLoss, SharpeHyperOptLoss, SharpeHyperOptLossDaily, OnlyProfitHyperOptLoss
# freqtrade hyperopt --hyperopt-loss OnlyProfitHyperOptLoss --spaces buy sell --timeframe 5m -e 2000 --timerange 20210301-20210813 --strategy MyStrategyNew6
# freqtrade backtesting --timeframe 5m --timerange 20200807-20210807 --strategy MyStrategyNew6
from typing import Tuple
from freqtrade.strategy import IStrategy, CategoricalParameter, DecimalParameter, IntParameter, merge_informative_pair
from pandas import DataFrame, Series
import talib.abstract as ta
import freqtrade.vendor.qtpylib.indicators as qtpylib
from functools import reduce
import numpy as np
import itertools
########################### Static Parameters ###########################
# Timeframes available for the exchange `Binance`: 1m, 3m, 5m, 15m, 30m, 1h, 2h, 4h, 6h, 8h, 12h, 1d, 3d, 1w, 1M
TIMEFRAMES = ('5m', '15m', '30m', '1h', '4h')
BASE_TIMEFRAME = TIMEFRAMES[0]
INFO_TIMEFRAMES = TIMEFRAMES[1:]
PERIODS = (5, 8, 13, 24, 39, 48) # (5, 6, 8, 9, 13, 18, 24, 31, 39, 48)
MAX_CONDITIONS = 3
########################### Operators ###########################
def greater_operator(dataframe: DataFrame, first_indicator: str, second_indicator: str):
return (dataframe[first_indicator] >
dataframe[second_indicator])
OPERATORS = {
'>': greater_operator
}
def apply_operator(dataframe: DataFrame, first_indicator, second_indicator, operator) -> tuple[Series, DataFrame]:
condition = OPERATORS[operator](dataframe, first_indicator, second_indicator)
return condition, dataframe
########################### Condition ###########################
NONE_CONDITION = 'NONE'
def generate_condition_set() -> set:
""" generate_condition_set wil return possible indicators with operator
{indicator_with_period}-{operator}-{indicator_with_period}
None condition mean do nothing
"""
# indicators_with_period will be format {indicator_name}_{period}_{timeframe}
indicator_with_periods = set()
for timeframe in TIMEFRAMES:
for periods in PERIODS:
indicator_with_periods.add(f'ema_{periods}_{timeframe}')
# indicator_with_operators will be format {indicator_with_period}-{operator}-{indicator_with_period}
possible_condition = set()
possible_condition.add(f'x-{NONE_CONDITION}-x')
indicators_permutations = itertools.permutations(indicator_with_periods, 2)
for first_indicator, second_indicator in indicators_permutations:
for operator in OPERATORS:
possible_condition.add(f'{first_indicator}-{operator}-{second_indicator}')
return possible_condition
def unpack_condition(condition: str) -> tuple[str, str, str]:
""" Return first_indicator, operator, second_indicator"""
first_indicator, operator, second_indicator = condition.split('-')
return first_indicator, operator, second_indicator
condition_set = generate_condition_set()
print('condition_set legth:', len(condition_set))
class MyStrategyNew6(IStrategy):
# ROI table:
minimal_roi = {"0": 1}
# Trailing stop:
trailing_stop = True
trailing_stop_positive = 0.15
trailing_stop_positive_offset = 0.197
trailing_only_offset_is_reached = True
# Stoploss
stoploss = -1
# Timeframe
timeframe = BASE_TIMEFRAME
# Hyperopt parameters
buy_condition_0 = CategoricalParameter(condition_set, space='buy')
buy_condition_1 = CategoricalParameter(condition_set, space='buy')
buy_condition_2 = CategoricalParameter(condition_set, space='buy')
sell_condition_0 = CategoricalParameter(condition_set, space='sell')
sell_condition_1 = CategoricalParameter(condition_set, space='sell')
sell_condition_2 = CategoricalParameter(condition_set, space='sell')
def apply_indicator(self, dataframe: DataFrame, key: str, period: int):
if key not in dataframe.keys():
dataframe[key] = ta.EMA(dataframe, timeperiod=period)
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
assert self.dp, "DataProvider is required for multiple timeframes."
avalidable_info_timeframes = set()
avalidable_periods = set()
run_mode = self.dp.runmode.value
if run_mode in ('backtest', 'live', 'dry_run'):
# TODO add only using timeframe and period
avalidable_info_timeframes = INFO_TIMEFRAMES
avalidable_periods = PERIODS
else:
avalidable_info_timeframes = INFO_TIMEFRAMES
avalidable_periods = PERIODS
# apply info timeframe indicator
for info_timeframe in avalidable_info_timeframes:
info_dataframe = self.dp.get_pair_dataframe(pair=metadata['pair'], timeframe=info_timeframe)
for period in avalidable_periods:
self.apply_indicator(info_dataframe, f'ema_{period}', period)
dataframe = merge_informative_pair(dataframe, info_dataframe, self.timeframe, info_timeframe, ffill=True)
# apply base timeframe indicator
for period in avalidable_periods:
self.apply_indicator(dataframe, f'ema_{period}_{BASE_TIMEFRAME}', period)
return dataframe
def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
conditions = list()
for condition_idx in range(MAX_CONDITIONS):
condition_name = getattr(self, f'buy_condition_{condition_idx}').value
first_indicator, operator, second_indicator = unpack_condition(condition_name)
if operator == NONE_CONDITION:
continue
condition, dataframe = apply_operator(dataframe, first_indicator, second_indicator, operator)
conditions.append(condition)
if conditions:
dataframe.loc[reduce(lambda x, y: x & y, conditions), 'buy'] = 1
return dataframe
def populate_sell_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
conditions = list()
for condition_idx in range(MAX_CONDITIONS):
condition_name = getattr(self, f'sell_condition_{condition_idx}').value
first_indicator, operator, second_indicator = unpack_condition(condition_name)
if operator == NONE_CONDITION:
continue
condition, dataframe = apply_operator(dataframe, first_indicator, second_indicator, operator)
conditions.append(condition)
if conditions:
dataframe.loc[reduce(lambda x, y: x & y, conditions), 'sell'] = 1
return dataframe