Stock Screening with Shortening 15-Minute MACD Bars, Turnover, and Valuation
Summary
This proposed equity screen combines three conditions: the position-increase ratio is above 5%, the prior day's trading value exceeds 60 million yuan, and the histogram bars in a 15-minute MACD calculation are getting shorter. The text interprets the position ratio as a sign of buying interest, trading value as a liquidity or activity filter, and a shrinking negative MACD histogram as a possible easing of short-term downside pressure. An expanded version adds a price-to-earnings ratio below 20.
The article provides illustrative Python logic for applying these filters, but gives no backtest, sample period, or measured results. It acknowledges that the setup focuses on short-term price behavior and omits longer-term trend and company fundamentals; changing market conditions may also undermine it. Adding valuation and other technical filters is suggested, but their effect is not evaluated. The screening conditions therefore describe a hypothesis rather than demonstrated evidence of future gains.
Key ideas
- The screen combines a position-increase ratio above 5%, prior-day trading value above 60 million yuan, and shortening 15-minute MACD histogram bars.
- The proposed extension also requires a price-to-earnings ratio below 20.
- The MACD condition is presented as a possible sign that short-term selling pressure is easing.
- The article provides sample implementation logic but no measured strategy performance.
- It cautions that short-term signals omit fundamentals and may fail when market conditions shift.
Tags
Full text
# MultiMa.py
```py
# MultiMa Strategy V2
# Author: @Mablue (Masoud Azizi)
# github: https://github.com/mablue/
# --- Do not remove these libs ---
from freqtrade.strategy import IntParameter, IStrategy
from pandas import DataFrame
# --------------------------------
# Add your lib to import here
import talib.abstract as ta
import freqtrade.vendor.qtpylib.indicators as qtpylib
from functools import reduce
class MultiMa(IStrategy):
# 111/2000: 18 trades. 12/4/2 Wins/Draws/Losses. Avg profit 9.72%. Median profit 3.01%. Total profit 733.01234143 USDT ( 73.30%). Avg duration 2 days, 18:40:00 min. Objective: 1.67048
INTERFACE_VERSION: int = 3
# Buy hyperspace params:
buy_params = {
"buy_ma_count": 4,
"buy_ma_gap": 15,
}
# Sell hyperspace params:
sell_params = {
"sell_ma_count": 12,
"sell_ma_gap": 68,
}
# ROI table:
minimal_roi = {
"0": 0.523,
"1553": 0.123,
"2332": 0.076,
"3169": 0
}
# Stoploss:
stoploss = -0.345
# Trailing stop:
trailing_stop = False # value loaded from strategy
trailing_stop_positive = None # value loaded from strategy
trailing_stop_positive_offset = 0.0 # value loaded from strategy
trailing_only_offset_is_reached = False # value loaded from strategy
# Opimal Timeframe
timeframe = "4h"
count_max = 20
gap_max = 100
buy_ma_count = IntParameter(1, count_max, default=7, space="buy")
buy_ma_gap = IntParameter(1, gap_max, default=7, space="buy")
sell_ma_count = IntParameter(1, count_max, default=7, space="sell")
sell_ma_gap = IntParameter(1, gap_max, default=94, space="sell")
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
for count in range(self.count_max):
for gap in range(self.gap_max):
if count*gap > 1 and count*gap not in dataframe.keys():
dataframe[count*gap] = ta.TEMA(
dataframe, timeperiod=int(count*gap)
)
print(" ", metadata['pair'], end="\t\r")
return dataframe
def populate_entry_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
conditions = []
# I used range(self.buy_ma_count.value) instade of self.buy_ma_count.range
# Cuz it returns range(7,8) but we need range(8) for all modes hyperopt, backtest and etc
for ma_count in range(self.buy_ma_count.value):
key = ma_count*self.buy_ma_gap.value
past_key = (ma_count-1)*self.buy_ma_gap.value
if past_key > 1 and key in dataframe.keys() and past_key in dataframe.keys():
conditions.append(dataframe[key] < dataframe[past_key])
if conditions:
dataframe.loc[reduce(lambda x, y: x & y, conditions), "enter_long"] = 1
return dataframe
def populate_exit_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
conditions = []
for ma_count in range(self.sell_ma_count.value):
key = ma_count*self.sell_ma_gap.value
past_key = (ma_count-1)*self.sell_ma_gap.value
if past_key > 1 and key in dataframe.keys() and past_key in dataframe.keys():
conditions.append(dataframe[key] > dataframe[past_key])
if conditions:
dataframe.loc[reduce(lambda x, y: x | y, conditions), "exit_long"] = 1
return dataframe
```Shown in full with attribution under the source's licence. Licence: GPL-3.0
This summary was written by Stratmill's research agent from the original; it is not a copy of the source.