Timeframe
3m
Direction
Long & Short
Stoploss
-1.0%
Trailing Stop
No
ROI
0m: 2.0%, 30m: 1.0%, 60m: 0.5%
Interface Version
3
Startup Candles
N/A
Indicators
1
import numpy as np
import pandas as pd
from freqtrade.strategy import IStrategy, IntParameter, DecimalParameter,Trade
from pandas import DataFrame
import talib.abstract as ta
from technical import qtpylib
import numpy as np
import pandas as pd
from datetime import datetime, timedelta, timezone
from pandas import DataFrame
from typing import Optional, Union
class VolMeanReversionStrategy(IStrategy):
INTERFACE_VERSION = 3
timeframe = "3m"
# Minimal ROI
minimal_roi = {
"0": 0.02, # 2% profit
"30": 0.01,
"60": 0.005
}
# Parameters
bb_window = IntParameter(10, 50, default=20, space='buy')
bb_std = DecimalParameter(1.5, 3.0, default=2.0, decimals=1, space='buy')
vol_window = IntParameter(10, 50, default=20, space='buy')
# Stoploss
stoploss = -0.01 # 2% stoploss
# trailing stoploss
trailing_stop: bool = True
trailing_stop_positive: float = 0.01
trailing_stop_positive_offset: float = 0.0
trailing_only_offset_is_reached = False
use_custom_stoploss: bool = True
can_short = True
def custom_stoploss(
self,
pair: str,
trade: Trade,
current_time: datetime,
current_rate: float,
current_profit: float,
after_fill: bool,
**kwargs,
) -> float | None:
"""
Custom stoploss logic, returning the new distance relative to current_rate (as ratio).
e.g. returning -0.05 would create a stoploss 5% below current_rate.
The custom stoploss can never be below self.stoploss, which serves as a hard maximum loss.
For full documentation please go to https://www.freqtrade.io/en/latest/strategy-advanced/
When not implemented by a strategy, returns the initial stoploss value.
Only called when use_custom_stoploss is set to True.
:param pair: Pair that's currently analyzed
:param trade: trade object.
:param current_time: datetime object, containing the current datetime
:param current_rate: Rate, calculated based on pricing settings in exit_pricing.
:param current_profit: Current profit (as ratio), calculated based on current_rate.
:param after_fill: True if the stoploss is called after the order was filled.
:param **kwargs: Ensure to keep this here so updates to this won't break your strategy.
:return float: New stoploss value, relative to the current_rate
"""
return self.stoploss
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
# Volatility
dataframe['volatility'] = dataframe['close'].rolling(window=self.vol_window.value).std()
dataframe['volatility_mean'] = dataframe['volatility'].rolling(window=self.vol_window.value).mean()
# Bollinger Bands
bollinger = qtpylib.bollinger_bands(
dataframe['close'],
window=self.bb_window.value,
stds=self.bb_std.value
)
dataframe['bb_upperband'] = bollinger['upper']
dataframe['bb_middleband'] = bollinger['mid']
dataframe['bb_lowerband'] = bollinger['lower']
# Volume Filters
dataframe['volume_mean'] = dataframe['volume'].rolling(window=self.vol_window.value).mean()
return dataframe
def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
dataframe.loc[
(
# Price below lower band
(dataframe['close'] < dataframe['bb_lowerband']) &
# High volatility
(dataframe['volatility'] > dataframe['volatility_mean']) &
# Good volume
(dataframe['volume'] > dataframe['volume_mean'])
),
'enter_short'
] = 1
return dataframe
def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
dataframe.loc[
(
# Price above middle band
(dataframe['close'] > dataframe['bb_middleband']) |
# Volatility back to normal
(dataframe['volatility'] < dataframe['volatility_mean'])
),
'exit_short'
] = 1
return dataframe