Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

The Quantitative Qualitative Estimation (QQE) Strategy request. #260

Open
JiSeopHyun opened this issue Jul 26, 2022 · 1 comment
Open

The Quantitative Qualitative Estimation (QQE) Strategy request. #260

JiSeopHyun opened this issue Jul 26, 2022 · 1 comment
Labels
Strategy Request Requests asking for an implementation of a specific strategy

Comments

@JiSeopHyun
Copy link

For requestion a new strategy. Please use the template below.
Any strategy request that does not follow the template will be closed.

Step 1: What indicators are required?

I found an explanation that corresponds to QQE.

The Quantitative Qualitative Estimation (QQE) indicator is derived from Wilder’s famous Relative Strength Index (RSI). In essence, the QQE is a heavily smoothed RSI.

This is the original content.
https://tradingtact.com/qqe-indicator/

And I also found some meaningful pseudo-code for this.

https://stackoverflow.com/questions/57164253/pinescript-to-python-getting-the-truth-value-of-a-series-is-ambiguous

Please list all the indicators required for the buy and sell strategy.

"(Volume Adjusted Moving Average) VAMA" , "Smoothed RSI" , "Slow Trailing"

Step 2: Explain the Buy Strategy

Please explain in details the indicators you need to run the buy strategy, then
explain in detail what is the trigger to buy.

entry trend
"Smoothed RSI" below "Slow Trailing" --> enter Short (Any Time)
"Slow Trailing" below "Smoothed RSI" --> enter Long (Any Time)
When VAMA is increased more than usual (hypetopt) is the best entry point

Step 1: Explain the Sell Strategy

exit trend
"Smoothed RSI" crossed above "Slow Trailing" --> exit Short
"Slow Trailing" crossed above "Smoothed RSI" --> exit Long
When VAMA is increased more than usual (hypetopt)

Please explain in details the indicators you need to run the sell strategy, then
explain in detail what is the trigger to sell.

Source

What come from this strategy? Cite your source:

This is my latest Fsupertrend that I have corrected.

--- Do not remove these libs ---

import numpy as np # noqa
import pandas as pd # noqa
from pandas import DataFrame # noqa
from datetime import datetime # noqa
from typing import Optional, Union # noqa

from freqtrade.strategy import (BooleanParameter, CategoricalParameter, DecimalParameter,
IStrategy, IntParameter)

from numpy.lib import math
import talib.abstract as ta
import freqtrade.vendor.qtpylib.indicators as qtpylib
import logging
from functools import reduce

class FSupertrendStrategy(IStrategy):

INTERFACE_VERSION: int = 3
# Buy hyperspace params:
buy_params = {
    "buy_m1": 4,
    "buy_m2": 7,
    "buy_m3": 1,
    "buy_p1": 8,
    "buy_p2": 9,
    "buy_p3": 8,
}

# Sell hyperspace params:
sell_params = {
    "sell_m1": 1,
    "sell_m2": 3,
    "sell_m3": 6,
    "sell_p1": 16,
    "sell_p2": 18,
    "sell_p3": 18,
}

# ROI table:
minimal_roi = {"0": 0.1, "30": 0.75, "60": 0.05, "120": 0.025}
# minimal_roi = {"0": 1}

# Stoploss:
stoploss = -0.265

# Can this strategy go short?
# can_short: bool = False
can_short: bool = True

# Trailing stop:
trailing_stop = True
trailing_stop_positive = 0.03 # old value 0.05
trailing_stop_positive_offset = 0.1
trailing_only_offset_is_reached = False # trailing_stop_positive_offset in use True

timeframe = "1h"

startup_candle_count = 25


buy_m1 = IntParameter(1, 7, default=1)
buy_m2 = IntParameter(1, 7, default=3)
buy_m3 = IntParameter(1, 7, default=4)
buy_p1 = IntParameter(7, 21, default=14)
buy_p2 = IntParameter(7, 21, default=10)
buy_p3 = IntParameter(7, 21, default=10)

sell_m1 = IntParameter(1, 7, default=1)
sell_m2 = IntParameter(1, 7, default=3)
sell_m3 = IntParameter(1, 7, default=4)
sell_p1 = IntParameter(7, 21, default=14)
sell_p2 = IntParameter(7, 21, default=10)
sell_p3 = IntParameter(7, 21, default=10)
ADD
# timeframe_select = CategoricalParameter(["5m", "15m","30m" , "1h" ], default="1h", space="buy")
# if timeframe_select.value == "5m" :
#     timeframe = "5m"
# if timeframe_select.value == "15m" :
#     timeframe = "15m"
# if timeframe_select.value == "30m" :
#     timeframe = "30m"
# if timeframe_select.value == "1h" :
#     timeframe = "1h"
                    
# EnterL_bollinger_enabled = CategoricalParameter([True, False], default=False, space="buy")
# EnterL_trigger_bollinger = CategoricalParameter(["bb_middleband", "bb_lowerband"], default="bb_lowerband", space="buy")

# EnterS_bollinger_enabled = CategoricalParameter([True, False], default=False, space="sell")
# EnterS_trigger_bollinger = CategoricalParameter(["bb_upperband", "bb_middleband"], default="bb_upperband", space="sell")

# ExitL_bollinger_enabled = CategoricalParameter([True, False], default=False, space="buy")
# ExitL_trigger_bollinger = CategoricalParameter(["bb_middleband", "bb_lowerband"], default="bb_lowerband", space="buy")

# ExitS_bollinger_enabled = CategoricalParameter([True, False], default=False, space="sell")
# ExitS_trigger_bollinger = CategoricalParameter(["bb_upperband", "bb_middleband"], default="bb_upperband", space="sell")
def version(self) -> str:
    return "1.2"


def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
    # # Bollinger bands
    # bollinger = qtpylib.bollinger_bands(qtpylib.typical_price(dataframe), window=17, stds=2)
    # dataframe['bb_lowerband'] = bollinger['lower']
    # dataframe['bb_middleband'] = bollinger['mid']
    # dataframe['bb_upperband'] = bollinger['upper']
    
    # dataframe['cci_one'] = ta.CCI(dataframe, timeperiod=17)

    frames = [dataframe]
    for multiplier in self.buy_m1.range:
        for period in self.buy_p1.range:
            frames.append(DataFrame({
                f'supertrend_1_buy_{multiplier}_{period}' : self.supertrend ( dataframe, multiplier, period )['STX']
            }))

    for multiplier in self.buy_m2.range:
        for period in self.buy_p2.range:
            frames.append(DataFrame({
                f'supertrend_2_buy_{multiplier}_{period}' : self.supertrend ( dataframe, multiplier, period )['STX']
            }))

    for multiplier in self.buy_m3.range:
        for period in self.buy_p3.range:
            frames.append(DataFrame({
                f'supertrend_3_buy_{multiplier}_{period}' : self.supertrend ( dataframe, multiplier, period )['STX']
            }))                

    for multiplier in self.sell_m1.range:
        for period in self.sell_p1.range:
            frames.append(DataFrame({
                f'supertrend_1_sell_{multiplier}_{period}' : self.supertrend ( dataframe, multiplier, period )['STX']
            }))                

    for multiplier in self.sell_m2.range:
        for period in self.sell_p2.range:
            frames.append(DataFrame({
                f'supertrend_2_sell_{multiplier}_{period}' : self.supertrend ( dataframe, multiplier, period )['STX']
            }))                 

    for multiplier in self.sell_m3.range:
        for period in self.sell_p3.range:
            frames.append(DataFrame({
                f'supertrend_3_sell_{multiplier}_{period}' : self.supertrend ( dataframe, multiplier, period )['STX']
            }))                  

    # Append columns to existing dataframe
    merged_frame = pd.concat(frames, axis=1)
    
    return merged_frame

def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:

    conditions = []

    conditions.append ( dataframe[f'supertrend_1_buy_{self.buy_m1.value}_{self.buy_p1.value}'] == "up" )

    conditions.append ( dataframe[f'supertrend_2_buy_{self.buy_m2.value}_{self.buy_p2.value}'] == "up" )

    conditions.append ( dataframe[f'supertrend_3_buy_{self.buy_m3.value}_{self.buy_p3.value}'] == "up" )

    conditions.append ( dataframe['volume'] > 0 )

    # if self.EnterL_bollinger_enabled.value:

    #     if self.EnterL_trigger_bollinger.value == "bb_middleband" :

    #         conditions.append ( dataframe['low'] < dataframe['bb_middleband'] )

    #     if self.EnterL_trigger_bollinger.value == "bb_lowerband" :

    #         conditions.append ( dataframe['low'] < dataframe['bb_lowerband'] )
    
    if conditions:
    
        dataframe.loc[
    
            reduce(lambda x, y: x & y, conditions), ['enter_long','enter_tag']

        ] = ( 1 , 'FSupertrendStrategy_InL' )
    
    conditions = []

    conditions.append ( dataframe[f'supertrend_1_sell_{self.sell_m1.value}_{self.sell_p1.value}'] == "down" )

    conditions.append ( dataframe[f'supertrend_2_sell_{self.sell_m2.value}_{self.sell_p2.value}'] == "down" )

    conditions.append ( dataframe[f'supertrend_3_sell_{self.sell_m3.value}_{self.sell_p3.value}'] == "down" )

    conditions.append ( dataframe['volume'] > 0 )

    # if self.EnterS_bollinger_enabled.value:

    #     if self.EnterS_trigger_bollinger.value == "bb_upperband" :

    #         conditions.append ( dataframe['high'] > dataframe['bb_upperband'] )

    #     if self.EnterS_trigger_bollinger.value == "bb_middleband" :

    #         conditions.append ( dataframe['high'] > dataframe['bb_middleband'] )

    if conditions:
        
        dataframe.loc[
    
            reduce(lambda x, y: x & y, conditions), ['enter_short','enter_tag']
                        
        ] = ( 1 , 'FSupertrendStrategy_InS' )

    return dataframe

def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:

    conditions = []

    conditions.append ( dataframe[ f'supertrend_2_sell_{self.sell_m2.value}_{self.sell_p2.value}'] == "down" )

    conditions.append ( dataframe['volume'] > 0 )

    # if self.ExitL_bollinger_enabled.value:
    
    #     if self.ExitL_trigger_bollinger.value == "bb_upperband" :

    #         conditions.append ( dataframe['high'] > dataframe['bb_upperband'] )

    #     if self.ExitL_trigger_bollinger.value == "bb_middleband" :

    #         conditions.append ( dataframe['high'] > dataframe['bb_middleband'] )

    if conditions:
        
        dataframe.loc[
    
            reduce(lambda x, y: x & y, conditions), ['exit_long','exit_tag']
                        
        ] = ( 1 , 'FSupertrendStrategy_OutL' )

    conditions = []

    conditions.append (  dataframe[f'supertrend_2_buy_{self.buy_m2.value}_{self.buy_p2.value}'] == "up" )

    conditions.append ( dataframe['volume'] > 0 )

    # if self.ExitS_bollinger_enabled.value:
    
    #     if self.ExitS_trigger_bollinger.value == "bb_upperband" :

    #         conditions.append ( dataframe['high'] > dataframe['bb_upperband'] )

    #     if self.ExitS_trigger_bollinger.value == "bb_middleband" :

    #         conditions.append ( dataframe['high'] > dataframe['bb_middleband'] )

    if conditions:
        
        dataframe.loc[
    
            reduce(lambda x, y: x & y, conditions), ['exit_short','exit_tag']
                        
        ] = ( 1 , 'FSupertrendStrategy_OutS' )

    return dataframe

"""
    Supertrend Indicator; adapted for freqtrade
    from: https://github.com/freqtrade/freqtrade-strategies/issues/30
"""

def supertrend(self, dataframe: DataFrame, multiplier, period):
    df = dataframe.copy()

    df["TR"] = ta.TRANGE(df)
    df["ATR"] = ta.SMA(df["TR"], period)

    st = "ST_" + str(period) + "_" + str(multiplier)
    stx = "STX_" + str(period) + "_" + str(multiplier)

    # Compute basic upper and lower bands
    df["basic_ub"] = (df["high"] + df["low"]) / 2 + multiplier * df["ATR"]
    df["basic_lb"] = (df["high"] + df["low"]) / 2 - multiplier * df["ATR"]

    # Compute final upper and lower bands
    df["final_ub"] = 0.00
    df["final_lb"] = 0.00
    for i in range(period, len(df)):
        df["final_ub"].iat[i] = (
            df["basic_ub"].iat[i]
            if df["basic_ub"].iat[i] < df["final_ub"].iat[i - 1]
            or df["close"].iat[i - 1] > df["final_ub"].iat[i - 1]
            else df["final_ub"].iat[i - 1]
        )
        df["final_lb"].iat[i] = (
            df["basic_lb"].iat[i]
            if df["basic_lb"].iat[i] > df["final_lb"].iat[i - 1]
            or df["close"].iat[i - 1] < df["final_lb"].iat[i - 1]
            else df["final_lb"].iat[i - 1]
        )

    # Set the Supertrend value
    df[st] = 0.00
    for i in range(period, len(df)):
        df[st].iat[i] = (
            df["final_ub"].iat[i]
            if df[st].iat[i - 1] == df["final_ub"].iat[i - 1]
            and df["close"].iat[i] <= df["final_ub"].iat[i]
            else df["final_lb"].iat[i]
            if df[st].iat[i - 1] == df["final_ub"].iat[i - 1]
            and df["close"].iat[i] > df["final_ub"].iat[i]
            else df["final_lb"].iat[i]
            if df[st].iat[i - 1] == df["final_lb"].iat[i - 1]
            and df["close"].iat[i] >= df["final_lb"].iat[i]
            else df["final_ub"].iat[i]
            if df[st].iat[i - 1] == df["final_lb"].iat[i - 1]
            and df["close"].iat[i] < df["final_lb"].iat[i]
            else 0.00
        )
    # Mark the trend direction up/down
    df[stx] = np.where(
        (df[st] > 0.00), np.where((df["close"] < df[st]), "down", "up"), np.NaN
    )

    # Remove basic and final bands from the columns
    df.drop(["basic_ub", "basic_lb", "final_ub", "final_lb"], inplace=True, axis=1)

    df.fillna(0, inplace=True)

    return DataFrame(index=df.index, data={"ST": df[st], "STX": df[stx]})

def leverage(self, pair: str, current_time: datetime, current_rate: float, proposed_leverage: float, max_leverage: float, entry_tag: Optional[str], side: str, **kwargs) -> float:
    # """
    # Customize leverage for each new trade. This method is only called in futures mode.

    # :param pair: Pair that's currently analyzed
    # :param current_time: datetime object, containing the current datetime
    # :param current_rate: Rate, calculated based on pricing settings in exit_pricing.
    # :param proposed_leverage: A leverage proposed by the bot.
    # :param max_leverage: Max leverage allowed on this pair
    # :param entry_tag: Optional entry_tag (buy_tag) if provided with the buy signal.
    # :param side: 'long' or 'short' - indicating the direction of the proposed trade
    # :return: A leverage amount, which is between 1.0 and max_leverage.
    # """
  
    return 4.0

###########################
Original source: Juan Carlos Soriano
###########################

References

https://www.freqtrade.io/en/stable/strategy-advanced/#performance-warning
https://www.freqtrade.io/en/stable/strategy-advanced/
https://www.freqtrade.io/en/stable/strategy-callbacks/#leverage-callback

I use the "Fsupertrend" strategy to backtest the practice and optimization.
It brought a profit, but there were many cases where you could buy at the highs and sell at the lows and lose money.
I came across QQE while searching for power to compensate for this.
Thank you to everyone involved in the Freqtrade projector for their hard work. And it is a projector that helps several programmers and ordinary investors.
I'm using a transformer.

@JiSeopHyun JiSeopHyun added the Strategy Request Requests asking for an implementation of a specific strategy label Jul 26, 2022
@xmatthias
Copy link
Member

I think this request is combining 2 things, which should really be separate as they're not really related.
It's one point to request a strategy (based on a new or existing indicator) - however the FSupertrend stuff is not related to this new strategy/indicator.
While it could be added to it - the request doesn't include this - and i think it produces different signals than supertrend, anyway.

If you've made improvements to a strategy you'd like to contribute, i'd apreciate a Pull request - which is adding the changes directly to the repository.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Strategy Request Requests asking for an implementation of a specific strategy
Projects
None yet
Development

No branches or pull requests

2 participants