<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by FMZQuant on Medium]]></title>
        <description><![CDATA[Stories by FMZQuant on Medium]]></description>
        <link>https://medium.com/@FMZQuant?source=rss-b78414ad1c60------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*lUxEq6Vqk_l9CRxgnmF2JA.png</url>
            <title>Stories by FMZQuant on Medium</title>
            <link>https://medium.com/@FMZQuant?source=rss-b78414ad1c60------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Mon, 22 Jun 2026 16:35:55 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@FMZQuant/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[Multi-Dimensional Market Analysis Quantitative Trading Strategy]]></title>
            <link>https://medium.com/@FMZQuant/multi-dimensional-market-analysis-quantitative-trading-strategy-ce46073b1cfd?source=rss-b78414ad1c60------2</link>
            <guid isPermaLink="false">https://medium.com/p/ce46073b1cfd</guid>
            <category><![CDATA[cryptocurrency]]></category>
            <category><![CDATA[fmz-quant]]></category>
            <category><![CDATA[source-code]]></category>
            <category><![CDATA[trading-strategy]]></category>
            <category><![CDATA[market-analysis]]></category>
            <dc:creator><![CDATA[FMZQuant]]></dc:creator>
            <pubDate>Tue, 29 Jul 2025 02:16:11 GMT</pubDate>
            <atom:updated>2025-07-29T02:16:11.036Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*ACMe6Yi8JAOQRZxJcwe4gQ.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*xF_cVN2TtJlun8eW4GLlpg.png" /></figure><h4>Overview</h4><p>The Multi-Dimensional Market Analysis Quantitative Trading Strategy is a highly intelligent quantitative trading system that integrates multiple technical indicators and market state recognition algorithms to analyze market behavior in real-time and provide trading signals. The core of this strategy lies in its unique market type recognition mechanism, which can automatically identify 10 different market states (such as bull market, bear market, box, volatility, etc.), and dynamically adjust indicator weights based on the current market environment to optimize the decision-making process. The strategy combines trend following, momentum analysis, volume analysis, and candlestick pattern recognition across multiple dimensions, calculating market signal strength through a comprehensive scoring system to ultimately form clear buy or sell decisions.</p><h4>Strategy Principles</h4><p>The strategy principles are based on a multi-layered market analysis framework:</p><ol><li><strong>Basic Indicator Calculation</strong>: First, the strategy calculates various technical indicators as the foundation for decision-making, including EMA(55), volume SMA(20/40/10), MACD(12,26,9), RSI(14), and ATR(14).</li><li><strong>Market State Recognition</strong>: The strategy has designed a comprehensive market type recognition algorithm that can accurately determine when the current market is in one of the following 10 states:</li></ol><ul><li>Bull: Price above EMA55, MACD line above signal line, RSI&gt;50, relative volume&gt;1</li><li>Bear: Price below EMA55, MACD line below signal line, RSI&lt;50, volume greater than average</li><li>Sideways: Difference between price and EMA55 less than 0.5 times ATR, and ATR lower than its 20-period average</li><li>Volatile: ATR higher than 1.2 times its 20-period average</li><li>Momentum: Price change greater than 1.5 times ATR, and volume greater than 1.5 times its 20-period average</li><li>Mean Reversion: RSI&gt;70 or RSI❤0</li><li>Box: Sideways and price range less than 0.8 times its 20-period average</li><li>Macro: Absolute value of price change greater than 2 times ATR</li><li>Wolf: Price change less than -ATR and price below EMA55</li><li>Eagle: Bull market and ATR lower than 0.8 times its 20-period average</li></ul><p><strong>3. Dynamic Weight Matrix</strong>: The strategy automatically adjusts the weights of various indicators based on the identified market type. For example, in a bull market environment, the weights of trend and MACD indicators are increased to 2.0, while in other market types, the weights of various indicators differ.</p><p><strong>4. Comprehensive Scoring System</strong>: The strategy calculates a 0–100 comprehensive score through weighted calculation of each indicator’s score. A score greater than 65 indicates a strong buy signal, less than 35 indicates a strong sell signal, and the middle range suggests unclear market conditions, recommending observation.</p><p><strong>5. Trading Rules</strong>: The strategy opens long positions when it identifies bull market, eagle market, or momentum market with a score greater than 65; it opens short positions when it identifies bear market or wolf market with a score less than 35. When the conditions are no longer met, it automatically closes positions.</p><h4>Strategy Advantages</h4><ol><li><strong>Multi-dimensional Analysis</strong>: The strategy not only focuses on price trends but also comprehensively considers volume, volatility, market state, and other dimensions, capturing market opportunities from all angles.</li><li><strong>Intelligent Market Recognition</strong>: It can automatically identify 10 different market states. This refined market classification greatly improves the strategy’s adaptability, allowing it to maintain effectiveness in different market environments.</li><li><strong>Dynamic Weight Adjustment</strong>: The core advantage of the strategy is its dynamic weight mechanism, which automatically adjusts the importance of various indicators according to different market types, avoiding blindly following certain indicators in unsuitable market environments.</li><li><strong>Visual Decision Panel</strong>: The strategy provides a detailed visual panel that clearly displays the status of various indicators, market type, and comprehensive score, making it easy for traders to understand the current decision logic.</li><li><strong>Integration of Multiple Technical Analysis Methods</strong>: The strategy organically combines trend following, momentum, mean reversion, volume analysis, and candlestick pattern recognition, forming a comprehensive analysis system.</li><li><strong>Clear Entry and Exit Signals</strong>: Through the comprehensive scoring system, the strategy provides clear trading signals, reducing the subjectivity and indecision in trading decisions.</li></ol><h4>Strategy Risks</h4><ol><li><strong>Parameter Sensitivity</strong>: The strategy uses multiple indicators and thresholds, and these parameter settings may significantly impact strategy performance. In different market environments or instruments, these parameters may need adjustment, otherwise, they may lead to false signals. The solution is to optimize parameters through backtesting or create adaptive parameter sets for different trading instruments.</li><li><strong>Rapid Market Transition Risk</strong>: When market states change rapidly, the strategy may not capture changes in time, leading to delayed reactions. This can be mitigated by adding short-term indicators or setting more sensitive market state transition detection mechanisms.</li><li><strong>False Breakout Risk</strong>: In box markets, false breakouts may occur, leading to incorrect signals. It is recommended to add confirmation mechanisms to the strategy, such as waiting for the price to continue in the breakout direction for a certain period or combining with other indicators for confirmation.</li><li><strong>Overtrading Risk</strong>: In highly volatile markets, scores may fluctuate frequently, leading to overtrading. This can be reduced by setting minimum holding periods or adding trade filtering conditions to reduce unnecessary trades.</li><li><strong>System Complexity</strong>: The strategy combines multiple indicators and market states, making the system relatively complex, which may increase the risk of errors or overfitting. It is recommended to periodically evaluate the contribution of each component, retain the truly effective parts, and simplify the system.</li></ol><h4>Strategy Optimization Directions</h4><ol><li><strong>Adaptive Parameter Adjustment</strong>: Currently, the strategy uses fixed parameter values. An adaptive mechanism could be introduced to automatically adjust indicator parameters based on market volatility, such as using longer-period moving averages in high-volatility markets and shorter-period ones in low-volatility markets. This can improve the strategy’s adaptability in different market environments.</li><li><strong>Enhanced Market State Transition Detection</strong>: Machine learning algorithms could be introduced to optimize market state recognition by training models to learn the characteristics of different market states, improving recognition accuracy and transition sensitivity.</li><li><strong>Integration of Multiple Timeframe Information</strong>: The current strategy only analyzes based on a single timeframe. Multi-timeframe analysis could be introduced to ensure that the trading direction is consistent with the trend of larger timeframes, increasing the win rate.</li><li><strong>Risk Management Optimization</strong>: Position size and stop-loss levels could be dynamically adjusted based on market volatility and current market state, reducing positions in high-risk environments and appropriately increasing positions in low-risk environments.</li><li><strong>Drawdown Control Mechanism</strong>: Design a risk control mechanism based on account drawdown that automatically reduces trading frequency or pauses trading when the strategy drawdown reaches a certain threshold, protecting capital safety.</li><li><strong>Optimization of Candlestick Pattern Recognition</strong>: The current strategy only recognizes simple hammer lines and engulfing patterns. More high-reliability candlestick patterns could be expanded and combined with volume confirmation to improve pattern recognition accuracy.</li><li><strong>Seasonality and Time Factors</strong>: Analysis of trading sessions, day of the week, month, and other time factors could be introduced to capture the seasonal characteristics of the market and optimize trading timing.</li></ol><h4>Summary</h4><p>The Multi-Dimensional Market Analysis Quantitative Trading Strategy is a comprehensive, intelligent quantitative trading system that achieves multi-dimensional market analysis by integrating multiple technical indicators and innovative market state recognition mechanisms. The core advantage of the strategy lies in its ability to accurately identify different market environments and dynamically adjust the weights of various indicators, thereby optimizing the decision-making process and improving trading success rates.</p><p>This strategy is particularly suitable for medium to long-term traders because it can effectively identify market trend transition points and maintain positions in favorable market environments. The strategy’s visual panel also provides traders with a clear market analysis view, facilitating understanding of the current market state and decision logic.</p><p>Despite the high complexity of the strategy, its modular design allows each part to be independently optimized and adjusted, enabling traders to customize it according to their preferences and market characteristics. By implementing the aforementioned optimization suggestions, this strategy has the potential to further improve its stability and profitability in various market environments, becoming a powerful quantitative trading tool.</p><p><strong>Strategy source code</strong></p><pre>/*backtest<br>start: 2024-07-22 00:00:00<br>end: 2025-07-20 08:00:00<br>period: 2d<br>basePeriod: 2d<br>exchanges: [{&quot;eid&quot;:&quot;Futures_Binance&quot;,&quot;currency&quot;:&quot;ETH_USDT&quot;,&quot;balance&quot;:2000000}]<br>*/<br><br>//@version=6<br>strategy(&quot;Panel Pro+ Quantum SmartPrompt&quot;, overlay=true, max_lines_count=500, max_bars_back=500, calc_on_every_tick=true)<br><br>// --- COLORS AND DESIGN<br>col_fondo    = color.new(color.rgb(245,245,220), 0)<br>col_borde    = color.rgb(130,130,130)<br>col_verde    = color.rgb(0,190,80)<br>col_amarillo = color.rgb(245,200,50)<br>col_rojo     = color.rgb(240,40,40)<br>col_texto    = color.rgb(30,30,30)<br><br>// --- BASE INDICATORS<br>ema_suprem   = ta.ema(close, 55)<br>sma_vol20    = ta.sma(volume, 20)<br>sma_vol40    = ta.sma(volume, 40)<br>sma_vol10    = ta.sma(volume, 10)<br>[macdLine, signalLine, _] = ta.macd(close, 12, 26, 9)<br>rsi_val      = ta.rsi(close, 14)<br>atr14        = ta.atr(14)<br>range20      = ta.stdev(close, 20)<br>delta        = close - open<br>sniper_umbral= ta.percentile_nearest_rank(volume, 40, 80)<br>rvol         = volume / sma_vol20<br><br>// --- PRE-CALCULATIONS FOR WARNINGS<br>smaATR20 = ta.sma(atr14, 20)<br>smaATR20x12 = smaATR20 * 1.2<br>smaATR20x08 = smaATR20 * 0.8<br>smaRange20 = ta.sma(range20, 20)<br>smaRange20x08 = smaRange20 * 0.8<br><br>// --- VOLUMES<br>vol_abs      = volume<br>vol_abs_umbral = sma_vol20 * 1.2<br>vol_abs_col  = vol_abs &gt; vol_abs_umbral ? col_verde : vol_abs &gt; sma_vol20 ? col_amarillo : col_rojo<br>vol_abs_prompt = vol_abs &gt; vol_abs_umbral ? &quot;High flight.&quot; : vol_abs &gt; sma_vol20 ? &quot;Vol avg.&quot; : &quot;Low vol.&quot;<br><br>rvol_col     = rvol &gt; 1.5 ? col_verde : rvol &gt; 0.8 ? col_amarillo : col_rojo<br>rvol_prompt  = rvol &gt; 1.5 ? &quot;Strong RVOL.&quot; : rvol &gt; 0.8 ? &quot;Average RVOL.&quot; : &quot;Weak RVOL.&quot;<br><br>delta_col    = delta &gt; 0 ? col_verde : delta &lt; 0 ? col_rojo : col_amarillo<br>delta_prompt = delta &gt; 0 ? &quot;Delta+&quot; : delta &lt; 0 ? &quot;Delta-&quot; : &quot;Neutral&quot;<br><br>sniper_col   = volume &gt; sniper_umbral ? col_verde : volume &gt; sma_vol20 ? col_amarillo : col_rojo<br>sniper_prompt= volume &gt; sniper_umbral ? &quot;Sniper: High vol.&quot; : volume &gt; sma_vol20 ? &quot;Sniper: Okay.&quot; : &quot;Sniper: Bye.&quot;<br><br>bloques      = volume &gt; (ta.highest(volume, 10) * 0.8) ? &quot;Big&quot; : volume &gt; sma_vol20 ? &quot;Normal&quot; : &quot;Low&quot;<br>bloques_col  = bloques == &quot;Big&quot; ? col_verde : bloques == &quot;Normal&quot; ? col_amarillo : col_rojo<br>bloques_prompt = bloques == &quot;Big&quot; ? &quot;Large blocks.&quot; : bloques == &quot;Normal&quot; ? &quot;Normal blocks.&quot; : &quot;Small blocks.&quot;<br><br>tick_col     = volume &gt; sma_vol20 ? col_verde : col_rojo<br>tick_prompt  = volume &gt; sma_vol20 ? &quot;High tick.&quot; : &quot;Low tick.&quot;<br><br>// --- TREND AND OTHER INDICATORS<br>tendencia    = close &gt; ema_suprem ? 1 : close &lt; ema_suprem ? -1 : 0<br>tendencia_txt= tendencia == 1 ? &quot;Bullish&quot; : tendencia == -1 ? &quot;Bassist&quot; : &quot;Lateral&quot;<br>tendencia_col= tendencia == 1 ? col_verde : tendencia == -1 ? col_rojo : col_amarillo<br>tendencia_prompt = tendencia == 1 ? &quot;Positive momentum.&quot; : tendencia == -1 ? &quot;Negative momentum.&quot; : &quot;No clear force.&quot;<br><br>rsi_col      = rsi_val &gt; 70 ? col_rojo : rsi_val &lt; 30 ? col_verde : col_amarillo<br>rsi_prompt   = rsi_val &gt; 70 ? &quot;Overbought.&quot; : rsi_val &lt; 30 ? &quot;Oversold.&quot; : &quot;RSI neutro.&quot;<br><br>macd_col     = macdLine &gt; signalLine ? col_verde : macdLine &lt; signalLine ? col_rojo : col_amarillo<br>macd_prompt  = macdLine &gt; signalLine ? &quot;Bullish MACD.&quot; : macdLine &lt; signalLine ? &quot;MACD bajista.&quot; : &quot;MACD neutro.&quot;<br><br>// --- SIMPLIFIED SAILING PATTERNS<br>is_hammer    = (high - low) &gt; 3 * math.abs(open - close) and<br>               (close - low) / (0.001 + high - low) &gt; 0.6 and<br>               (open - low) / (0.001 + high - low) &gt; 0.6<br>is_engulfing = close &gt; open[1] and open &lt; close[1] and<br>               close &gt; open and open &lt; close<br><br>pattern      = is_hammer ? 1 : is_engulfing ? 2 : 0<br>pattern_str  = pattern == 1 ? &quot;Hammer&quot; : pattern == 2 ? &quot;Engulfing&quot; : &quot;-&quot;<br>pattern_col  = pattern == 1 ? col_verde : pattern == 2 ? col_amarillo : col_rojo<br>pattern_prompt = pattern == 1 ? &quot;Hammer: possible twist.&quot; : pattern == 2 ? &quot;Engulfing: possible change.&quot; : &quot;No clear pattern.&quot;<br><br>// --- DETECTION OF 10 MARKET TYPES (INTEGRATED)<br>isBull      = close &gt; ema_suprem and macdLine &gt; signalLine and rsi_val &gt; 50 and rvol &gt; 1<br>isBear      = close &lt; ema_suprem and macdLine &lt; signalLine and rsi_val &lt; 50 and volume &gt; sma_vol20<br>isSideways  = math.abs(close - ema_suprem) &lt; atr14*0.5 and atr14 &lt; smaATR20<br>isVolatile  = atr14 &gt; smaATR20x12<br>isMomentum  = ta.change(close,1) &gt; atr14*1.5 and volume &gt; sma_vol20*1.5<br>isMeanRev   = rsi_val &gt; 70 or rsi_val &lt; 30<br>isBox       = isSideways and range20 &lt; smaRange20x08<br>isMacro     = math.abs(ta.change(close,1)) &gt; atr14*2<br>isWolf      = ta.change(close,1) &lt; -atr14 and close &lt; ema_suprem<br>isEagle     = isBull and atr14 &lt; smaATR20x08<br><br>var string marketType = &quot;&quot;<br>var string marketEmoji = &quot;&quot;<br>var string marketPrompt = &quot;&quot;<br>var color  marketColor = na<br><br>if isEagle<br>    marketType := &quot;Eagle&quot;<br>    marketEmoji := &quot;🦅&quot;<br>    marketPrompt := &quot;Eagle: Fast bull, hold long.&quot;<br>    marketColor := col_verde<br>else if isBull<br>    marketType := &quot;Bull&quot;<br>    marketEmoji := &quot;📈&quot;<br>    marketPrompt := &quot;Bull: buy on pullbacks.&quot;<br>    marketColor := col_verde<br>else if isWolf<br>    marketType := &quot;Wolf&quot;<br>    marketEmoji := &quot;🐺&quot;<br>    marketPrompt := &quot;Wolf: short opportunity.&quot;<br>    marketColor := col_amarillo<br>else if isBear<br>    marketType := &quot;Bear&quot;<br>    marketEmoji := &quot;📉&quot;<br>    marketPrompt := &quot;Bear: reverses a ralli.&quot;<br>    marketColor := col_rojo<br>else if isBox<br>    marketType := &quot;Box&quot;<br>    marketEmoji := &quot;📦&quot;<br>    marketPrompt := &quot;Box: operate ruptures.&quot;<br>    marketColor := col_amarillo<br>else if isSideways<br>    marketType := &quot;Sideways&quot;<br>    marketEmoji := &quot;↔️&quot;<br>    marketPrompt := &quot;Range: support/res edges.&quot;<br>    marketColor := col_amarillo<br>else if isVolatile<br>    marketType := &quot;Volatile&quot;<br>    marketEmoji := &quot;🌪&quot;<br>    marketPrompt := &quot;Volatile: fast scalping.&quot;<br>    marketColor := col_amarillo<br>else if isMomentum<br>    marketType := &quot;Momentum&quot;<br>    marketEmoji := &quot;🚁&quot;<br>    marketPrompt := &quot;Momentum: impulsive sails.&quot;<br>    marketColor := col_amarillo<br>else if isMeanRev<br>    marketType := &quot;MeanRev&quot;<br>    marketEmoji := &quot;🔁&quot;<br>    marketPrompt := &quot;Reversal in extremes.&quot;<br>    marketColor := col_amarillo<br>else if isMacro<br>    marketType := &quot;Macro&quot;<br>    marketEmoji := &quot;📅&quot;<br>    marketPrompt := &quot;Macro event: confirm.&quot;<br>    marketColor := col_amarillo<br>else<br>    marketType := &quot;Unknown&quot;<br>    marketEmoji := &quot;❓&quot;<br>    marketPrompt := &quot;No clear regime.&quot;<br>    marketColor := col_amarillo<br><br>// --- DYNAMIC WEIGHTING MATRIX<br>// You can adjust these values in the future. Each row represents the market type, and each column represents an indicator.<br>ponderaciones = array.new_float(10)<br>if marketType == &quot;Bull&quot;<br>    array.set(ponderaciones, 0, 2.0) // trend<br>    array.set(ponderaciones, 1, 1.5) // rsi<br>    array.set(ponderaciones, 2, 2.0) // macd<br>    array.set(ponderaciones, 3, 1.3) // vol abs<br>    array.set(ponderaciones, 4, 1.2) // rvol<br>    array.set(ponderaciones, 5, 1.0) // delta<br>    array.set(ponderaciones, 6, 1.2) // sniper<br>    array.set(ponderaciones, 7, 1.0) // blocks<br>    array.set(ponderaciones, 8, 1.0) // tick<br>    array.set(ponderaciones, 9, 1.0) // pattern<br>else if marketType == &quot;Bear&quot;<br>    array.set(ponderaciones, 0, 2.0)<br>    array.set(ponderaciones, 1, 1.5)<br>    array.set(ponderaciones, 2, 2.0)<br>    array.set(ponderaciones, 3, 1.5)<br>    array.set(ponderaciones, 4, 1.3)<br>    array.set(ponderaciones, 5, 1.1)<br>    array.set(ponderaciones, 6, 1.2)<br>    array.set(ponderaciones, 7, 1.1)<br>    array.set(ponderaciones, 8, 1.0)<br>    array.set(ponderaciones, 9, 1.0)<br>// ... You can complete for all types according to your preference.<br><br>// --- DYNAMIC GLOBAL SCORING<br>// (You can expand the weighting for other types just like the example above)<br>base_score = 0.0<br>base_score := base_score + ((tendencia == 1 ? 20 : tendencia == -1 ? -20 : 0) * array.get(ponderaciones,0))<br>base_score := base_score + ((rsi_col == col_verde ? 10 : rsi_col == col_rojo ? -10 : 0) * array.get(ponderaciones,1))<br>base_score := base_score + ((macd_col == col_verde ? 10 : macd_col == col_rojo ? -10 : 0) * array.get(ponderaciones,2))<br>base_score := base_score + ((vol_abs_col == col_verde ? 8 : vol_abs_col == col_rojo ? -8 : 0) * array.get(ponderaciones,3))<br>base_score := base_score + ((rvol_col == col_verde ? 7 : rvol_col == col_rojo ? -7 : 0) * array.get(ponderaciones,4))<br>base_score := base_score + ((delta_col == col_verde ? 6 : delta_col == col_rojo ? -6 : 0) * array.get(ponderaciones,5))<br>base_score := base_score + ((sniper_col == col_verde ? 8 : sniper_col == col_rojo ? -8 : 0) * array.get(ponderaciones,6))<br>base_score := base_score + ((bloques_col == col_verde ? 5 : bloques_col == col_rojo ? -5 : 0) * array.get(ponderaciones,7))<br>base_score := base_score + ((tick_col == col_verde ? 5 : -5) * array.get(ponderaciones,8))<br>base_score := base_score + ((pattern == 1 ? 7 : pattern == 2 ? 5 : 0) * array.get(ponderaciones,9))<br><br>score_pct = math.max(0, math.min(100, 50 + base_score))<br>prompt_global = score_pct &gt; 65 ? &quot;🟢 Strong signal: Consider entry.&quot; : score_pct &lt; 35 ? &quot;🔴 Weak signal: DO NOT enter.&quot; : &quot;🟡 Mixed signal: Better to wait.&quot;<br>explicacion_global = score_pct &gt; 65 ? &quot;Optimal conditions. 👍&quot; : score_pct &lt; 35 ? &quot;Weak or mixed indicators. 🚫&quot; : &quot;Sideways or transition market. ⏸&quot;<br><br>// --- ADVANCED VISUAL PANEL<br>var table t = table.new(position.middle_left, 5, 14, bgcolor=col_fondo, border_width=2, border_color=col_borde)<br>if barstate.islast<br>    table.cell(t, 0, 0, &quot;🔎&quot;, bgcolor=col_fondo, text_color=col_texto)<br>    table.cell(t, 1, 0, &quot;🪙 Tipo&quot;, bgcolor=col_fondo, text_color=col_texto)<br>    table.cell(t, 2, 0, &quot;⚡️&quot;, bgcolor=col_fondo, text_color=col_texto)<br>    table.cell(t, 3, 0, &quot;Worth&quot;, bgcolor=col_fondo, text_color=col_texto)<br>    table.cell(t, 4, 0, &quot;Prompt&quot;, bgcolor=col_fondo, text_color=col_texto)<br>    table.cell(t, 1, 1, &quot;Trend&quot;, text_color=col_texto)<br>    table.cell(t, 2, 1, &quot;&quot;, bgcolor=tendencia_col)<br>    table.cell(t, 3, 1, tendencia_txt, text_color=col_texto)<br>    table.cell(t, 4, 1, tendencia_prompt, text_color=col_texto)<br>    table.cell(t, 1, 2, &quot;RSI&quot;, text_color=col_texto)<br>    table.cell(t, 2, 2, &quot;&quot;, bgcolor=rsi_col)<br>    table.cell(t, 3, 2, str.tostring(rsi_val, &quot;#.##&quot;), text_color=col_texto)<br>    table.cell(t, 4, 2, rsi_prompt, text_color=col_texto)<br>    table.cell(t, 1, 3, &quot;MACD&quot;, text_color=col_texto)<br>    table.cell(t, 2, 3, &quot;&quot;, bgcolor=macd_col)<br>    table.cell(t, 3, 3, str.tostring(macdLine, &quot;#.##&quot;), text_color=col_texto)<br>    table.cell(t, 4, 3, macd_prompt, text_color=col_texto)<br>    table.cell(t, 1, 4, &quot;Absolute&quot;, text_color=col_texto)<br>    table.cell(t, 2, 4, &quot;&quot;, bgcolor=vol_abs_col)<br>    table.cell(t, 3, 4, str.tostring(vol_abs), text_color=col_texto)<br>    table.cell(t, 4, 4, vol_abs_prompt, text_color=col_texto)<br>    table.cell(t, 1, 5, &quot;Relative&quot;, text_color=col_texto)<br>    table.cell(t, 2, 5, &quot;&quot;, bgcolor=rvol_col)<br>    table.cell(t, 3, 5, str.tostring(rvol, &quot;#.##&quot;), text_color=col_texto)<br>    table.cell(t, 4, 5, rvol_prompt, text_color=col_texto)<br>    table.cell(t, 1, 6, &quot;Delta&quot;, text_color=col_texto)<br>    table.cell(t, 2, 6, &quot;&quot;, bgcolor=delta_col)<br>    table.cell(t, 3, 6, str.tostring(delta, &quot;#.##&quot;), text_color=col_texto)<br>    table.cell(t, 4, 6, delta_prompt, text_color=col_texto)<br>    table.cell(t, 1, 7, &quot;Sniper&quot;, text_color=col_texto)<br>    table.cell(t, 2, 7, &quot;&quot;, bgcolor=sniper_col)<br>    table.cell(t, 3, 7, sniper_col == col_verde ? &quot;Yeah&quot; : &quot;No&quot;, text_color=col_texto)<br>    table.cell(t, 4, 7, sniper_prompt, text_color=col_texto)<br>    table.cell(t, 1, 8, &quot;Blocks&quot;, text_color=col_texto)<br>    table.cell(t, 2, 8, &quot;&quot;, bgcolor=bloques_col)<br>    table.cell(t, 3, 8, bloques, text_color=col_texto)<br>    table.cell(t, 4, 8, bloques_prompt, text_color=col_texto)<br>    table.cell(t, 1, 9, &quot;Tick&quot;, text_color=col_texto)<br>    table.cell(t, 2, 9, &quot;&quot;, bgcolor=tick_col)<br>    table.cell(t, 3, 9, str.tostring(volume), text_color=col_texto)<br>    table.cell(t, 4, 9, tick_prompt, text_color=col_texto)<br>    table.cell(t, 1,10, &quot;Sailing Pattern&quot;, text_color=col_texto)<br>    table.cell(t, 2,10, pattern_str, bgcolor=pattern_col, text_color=col_texto)<br>    table.cell(t, 3,10, pattern != 0 ? pattern_str : &quot;No pattern&quot;, text_color=col_texto)<br>    table.cell(t, 4,10, pattern_prompt, text_color=col_texto)<br>    // Global<br>    table.cell(t, 1,11, &quot;📊 Global&quot;, text_color=color.black, bgcolor=color.new(col_fondo, 40))<br>    table.cell(t, 2,11, &quot;&quot;, bgcolor=score_pct &gt; 65 ? col_verde : score_pct &lt; 35 ? col_rojo : col_amarillo)<br>    table.cell(t, 3,11, str.tostring(score_pct, &quot;#&quot;) + &quot;%&quot;, text_color=color.black)<br>    table.cell(t, 4,11, prompt_global, text_color=color.black)<br>    // Global Explanation<br>    table.cell(t, 1,12, &quot;Explanation&quot;, text_color=color.black, bgcolor=color.new(col_fondo, 40))<br>    table.cell(t, 2,12, &quot;&quot;, bgcolor=color.new(col_fondo, 0))<br>    table.cell(t, 3,12, &quot;&quot;, bgcolor=color.new(col_fondo, 0))<br>    table.cell(t, 4,12, explicacion_global, text_color=color.black)<br>    // Market Detection<br>    table.cell(t, 1,13, &quot;Market&quot;, text_color=col_texto)<br>    table.cell(t, 2,13, &quot;&quot;, bgcolor=marketColor)<br>    table.cell(t, 3,13, marketEmoji + &quot; &quot; + marketType, text_color=col_texto)<br>    table.cell(t, 4,13, marketPrompt, text_color=col_texto)<br><br>// === STRATEGIC OPERATING RULES AND ALERTS ===<br>longCond = (marketType == &quot;Bull&quot; or marketType == &quot;Eagle&quot; or marketType == &quot;Momentum&quot;) and score_pct &gt; 65<br>shortCond = (marketType == &quot;Bear&quot; or marketType == &quot;Wolf&quot;) and score_pct &lt; 35<br><br>if longCond and strategy.position_size &lt;= 0<br>    strategy.entry(&quot;LONG&quot;, strategy.long)<br>    alert(&quot;🟢 LONG Entrance: Market &quot; + marketType + &quot; | &quot; + prompt_global, alert.freq_once_per_bar)<br>if shortCond and strategy.position_size &gt;= 0<br>    strategy.entry(&quot;CORTO&quot;, strategy.short)<br>    alert(&quot;🔴 SHORT Entry: Market &quot; + marketType + &quot; | &quot; + prompt_global, alert.freq_once_per_bar)<br>if (not longCond and strategy.position_size &gt; 0)<br>    strategy.close(&quot;LONG&quot;, comment=&quot;LONG Exit&quot;)<br>if (not shortCond and strategy.position_size &lt; 0)<br>    strategy.close(&quot;SHORT&quot;, comment=&quot;SHORT Exit&quot;)</pre><p>The original address: <a href="https://www.fmz.com/strategy/502330">Multi-Dimensional Market Analysis Quantitative Trading Strategy</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=ce46073b1cfd" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[ADX and Supertrend Persistent Entry Strategy]]></title>
            <link>https://medium.com/@FMZQuant/adx-and-supertrend-persistent-entry-strategy-fb8bfab04be5?source=rss-b78414ad1c60------2</link>
            <guid isPermaLink="false">https://medium.com/p/fb8bfab04be5</guid>
            <category><![CDATA[fmz-quant]]></category>
            <category><![CDATA[trading-strategy]]></category>
            <category><![CDATA[source-code]]></category>
            <category><![CDATA[supertrends]]></category>
            <category><![CDATA[cryptocurrency]]></category>
            <dc:creator><![CDATA[FMZQuant]]></dc:creator>
            <pubDate>Tue, 29 Jul 2025 01:07:06 GMT</pubDate>
            <atom:updated>2025-07-29T01:07:06.780Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*MqZIUfxCl37uubWa-Mst9w.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*Dh4A-ECJXwQj7BKY4Jf2dA.png" /></figure><h4>Overview</h4><p>The ADX and Supertrend Persistent Entry Trading Strategy is a quantitative trading method that combines directional indicators with trend confirmation tools. This strategy integrates the Average Directional Index (ADX), Directional Movement Index (DMI), and Supertrend indicator, supplemented by volume-weighted Order Block analysis to build a comprehensive trading system. The strategy particularly emphasizes a persistent condition verification mechanism, triggering trading signals only after multiple technical conditions are met, which effectively improves trading quality and reduces the occurrence of false signals.</p><h4>Strategy Principles</h4><p>The core logic of this strategy is based on the following key components:</p><ol><li><strong>ADX and DMI Indicator Analysis</strong>: The system uses the ADX indicator to measure market trend strength and determines trend direction by comparing +DI and -DI values. When the ADX value is above a set threshold (default 25), it indicates a strong market trend; +DI greater than -DI suggests a bullish trend, while the opposite indicates a bearish trend.</li><li><strong>Supertrend Trend Confirmation</strong>: The Supertrend indicator serves as a secondary trend confirmation tool, supporting buying when it shows a bullish signal (trend == -1) and selling when it shows a bearish signal (trend == 1). Changes in Supertrend are also used as exit signal triggers.</li><li><strong>Volume-Weighted Order Blocks</strong>: The strategy introduces a dynamic support and resistance zone identification mechanism based on volume. When volume exceeds a specific multiple of the average level (default 2x) and price reaches local highs or lows, the system marks these areas as potential order blocks and maintains their validity for a set period (default 15 periods).</li><li><strong>Persistent Condition Verification</strong>: The most unique part of the strategy is its persistent condition verification mechanism. The system tracks various trading conditions through four boolean flags: trend condition, ADX condition, DMI condition, and zone condition. Trading signals are triggered only when all conditions are met. This mechanism ensures that trading occurs in optimal market environments.</li></ol><p>Buy conditions:</p><ul><li>ADX above threshold (default 25)</li><li>+DI greater than -DI</li><li>Supertrend in bullish state</li><li>Price not within volume resistance zone</li></ul><p>Sell conditions:</p><ul><li>ADX above threshold (default 25)</li><li>-DI greater than +DI</li><li>Supertrend in bearish state</li><li>Price not within volume support zone</li></ul><p>Exit logic: When the Supertrend indicator changes trend direction, the strategy closes the current position.</p><h4>Strategy Advantages</h4><ol><li><strong>Multiple Confirmation Mechanism</strong>: By integrating multiple technical indicators, the strategy greatly reduces false signals and improves trading accuracy. The combination of ADX and Supertrend, in particular, ensures both trend strength and provides clear directional guidance.</li><li><strong>Persistent Condition Verification</strong>: The strategy’s persistent verification mechanism allows the system to act only when all conditions mature, rather than triggering trades based on single signals. This design greatly enhances the strategy’s robustness and reduces unnecessary trades under unfavorable market conditions.</li><li><strong>Dynamic Support and Resistance Identification</strong>: Volume-based order block analysis provides the strategy with dynamic support and resistance references, making trading decisions more aligned with market microstructure and avoiding counter-trend trading at key price zones.</li><li><strong>Clear Exit Mechanism</strong>: The strategy uses Supertrend reversals as exit signals, providing objective and timely stop-loss and take-profit methods, effectively managing the risk of each trade.</li><li><strong>High Adaptability</strong>: Through multiple adjustable parameters, the strategy can adapt to different market environments and trading instruments, enhancing its practicality and flexibility.</li></ol><h4>Strategy Risks</h4><ol><li><strong>Parameter Sensitivity</strong>: The strategy’s effectiveness largely depends on parameter settings. The choice of ADX length, Supertrend multiplier, and ATR period significantly impacts strategy performance. Inappropriate parameter settings may lead to overtrading or missing important opportunities. The solution is to optimize parameters through historical backtesting and prepare different parameter combinations for different market environments.</li><li><strong>Trend Reversal Risk</strong>: Despite using multiple confirmation mechanisms, the strategy may still face lag risk during strong market reversals or high volatility environments. The solution is to consider introducing volatility filters or dynamically adjusting ADX thresholds to adapt to different market volatility states.</li><li><strong>Volume Anomaly Risk</strong>: The strategy is relatively dependent on volume analysis and may produce incorrect order block identification in cases of abnormal volume (such as sudden non-regular large volume). The solution is to add volume smoothing processing or introduce additional anomaly detection mechanisms.</li><li><strong>Over-Optimization Risk</strong>: Because the strategy contains multiple adjustable parameters, it can easily lead to over-optimization, making the strategy perform well on historical data but poorly in actual trading. The solution is to use forward testing and out-of-sample testing to ensure the strategy’s robustness.</li><li><strong>Liquidity Risk</strong>: In low-liquidity markets, large transactions may lead to slippage or order execution delays, affecting strategy effectiveness. The solution is to add additional liquidity filtering conditions in low-liquidity environments or adjust position size.</li></ol><h4>Strategy Optimization Directions</h4><ol><li><strong>Dynamic Parameter Adjustment</strong>: The strategy can be further optimized to automatically adjust ADX thresholds and Supertrend parameters based on market volatility. For example, ADX thresholds can be increased during high volatility periods to reduce false breakout signals, and thresholds can be lowered during low volatility periods to increase sensitivity. This adaptive mechanism allows the strategy to better adapt to different market phases.</li><li><strong>Time Filter Integration</strong>: Introducing time filters can avoid trading during market opening, closing, or periods of poor liquidity. This optimization is particularly suitable for intraday trading strategies and can significantly reduce unnecessary trades caused by market noise.</li><li><strong>Multi-Timeframe Analysis</strong>: By integrating trend information from higher timeframes, the strategy can ensure that trading direction remains consistent with the larger trend. For example, executing trades only when daily and hourly trend directions align can improve win rates and reduce counter-trend trading risk.</li><li><strong>Risk Management Enhancement</strong>: The current strategy’s exit mechanism is relatively simple and can be enhanced by adding trailing stops, profit-to-loss ratio filtering, or volatility-based stop-loss calculations. These improvements can better protect profits and control risk for each trade.</li><li><strong>Market State Classification</strong>: Introducing a market state classification mechanism enables the strategy to identify different market environments such as consolidation periods, trend periods, and high volatility periods, and adjust trading logic accordingly. This optimization can avoid trading under market conditions unsuitable for the strategy, further enhancing the strategy’s robustness.</li></ol><h4>Summary</h4><p>The ADX and Supertrend Persistent Entry Trading Strategy builds a comprehensive and robust trading system by integrating multiple technical indicators and a unique persistent condition verification mechanism. The strategy particularly emphasizes trading under ideal market conditions, avoiding many common false signal traps. Through the combined use of ADX, DMI, and Supertrend, the strategy can effectively identify strong trend environments and determine the correct trading direction; while volume-weighted order block analysis provides additional microstructure support, helping to avoid counter-trend trading at key support and resistance areas.</p><p>Despite its many advantages, users should still be aware of potential issues such as parameter sensitivity, trend reversal risk, and over-optimization. The strategy still has significant room for optimization through the introduction of dynamic parameter adjustment, multi-timeframe analysis, and enhanced risk management mechanisms. Ultimately, this approach, combining technical indicators and market microstructure analysis, represents a balanced and comprehensive quantitative trading approach suitable for investors seeking high-quality trading signals rather than high-frequency trading.</p><p><strong>Strategy source code</strong></p><pre>/*backtest<br>start: 2024-07-22 00:00:00<br>end: 2025-07-20 08:00:00<br>period: 1d<br>basePeriod: 1d<br>exchanges: [{&quot;eid&quot;:&quot;Futures_Binance&quot;,&quot;currency&quot;:&quot;ETH_USDT&quot;,&quot;balance&quot;:2000000}]<br>*/<br><br>// This Pine Script™ code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/<br><br>// © algostudio<br><br>//Code Generated using PineGPT  - www.marketcalls.in<br><br>//@version=6<br>strategy(&quot;ADX + Supertrend Persistent Entry Logic&quot;, overlay=true, default_qty_type=strategy.percent_of_equity, default_qty_value=10, process_orders_on_close=true, calc_on_every_tick=true, max_bars_back=500)<br><br>// === INPUTS === //<br>adxLen = input.int(7, &quot;ADX Length&quot;)<br>dilen = input.int(7, &quot;+DI/-DI Length&quot;)<br>adxThresh = input.float(25, &quot;ADX Threshold&quot;)<br>supertrendFactor = input.float(2.0, &quot;Supertrend Multiplier&quot;, minval=0.1)<br>supertrendLen = input.int(7, &quot;Supertrend ATR Length&quot;)<br>volLookback = input.int(10, &quot;Volume Zone Lookback&quot;)<br>volMult = input.float(2.0, &quot;Volume Threshold Multiplier&quot;)<br>zoneDuration = input.int(15, &quot;Zone Display Duration&quot;)<br><br>// === ADX AND DI CALCULATION === //<br>[plusDI, minusDI, adx] = ta.dmi(dilen, adxLen)<br><br>// === SUPER TREND CALCULATION === //<br>[supertrend, trend] = ta.supertrend(supertrendFactor, supertrendLen)<br><br>bullishSupertrendShift = trend == -1 and trend[1] == 1<br>bearishSupertrendShift = trend == 1 and trend[1] == -1<br><br>// === DYNAMIC ORDER BLOCK ZONES (Volume weighted) === //<br>volThreshold = ta.sma(volume, volLookback) * volMult<br>volHighs = high == ta.highest(high, 5) and volume &gt; volThreshold<br>volLows = low == ta.lowest(low, 5) and volume &gt; volThreshold<br><br>obSupportValid = ta.valuewhen(volLows, low, 0)<br>bbResistanceValid = ta.valuewhen(volHighs, high, 0)<br>obSupportStart = ta.valuewhen(volLows, bar_index, 0)<br>bbResistanceStart = ta.valuewhen(volHighs, bar_index, 0)<br>obSupportEnd = obSupportStart + zoneDuration<br>bbResistanceEnd = bbResistanceStart + zoneDuration<br><br>inObZone = bar_index &gt;= obSupportStart and bar_index &lt;= obSupportEnd<br>inBbZone = bar_index &gt;= bbResistanceStart and bar_index &lt;= bbResistanceEnd<br><br>// === PLOT ZONES === //<br>plot(inObZone ? obSupportValid : na, title=&quot;OB Support Line&quot;, color=color.green, linewidth=2)<br>plot(inBbZone ? bbResistanceValid : na, title=&quot;BB Resistance Line&quot;, color=color.red, linewidth=2)<br>plot(supertrend, color=trend == 1 ? color.red : color.green, title=&quot;Supertrend&quot;)<br><br>// === PERSISTENT FLAGS === //<br>var bool buyTrendMet = false<br>var bool buyAdxMet = false<br>var bool buyDiMet = false<br>var bool buyZoneClear = false<br><br>var bool sellTrendMet = false<br>var bool sellAdxMet = false<br>var bool sellDiMet = false<br>var bool sellZoneClear = false<br><br>// === READY FLAGS (declare early to resolve use-before-declare issues) === //<br>buyReady = buyTrendMet and buyAdxMet and buyDiMet and buyZoneClear<br>sellReady = sellTrendMet and sellAdxMet and sellDiMet and sellZoneClear<br><br>// Track condition flags<br>buyTrendMet := trend == -1 ? true : buyTrendMet<br>buyAdxMet := adx &gt; adxThresh ? true : (buyReady ? buyAdxMet : false)<br>buyDiMet := plusDI &gt; minusDI ? true : buyDiMet<br>buyZoneClear := not inBbZone ? true : buyZoneClear<br><br>sellTrendMet := trend == 1 ? true : sellTrendMet<br>sellAdxMet := adx &gt; adxThresh ? true : (sellReady ? sellAdxMet : false)<br>sellDiMet := minusDI &gt; plusDI ? true : sellDiMet<br>sellZoneClear := not inObZone ? true : sellZoneClear<br><br>// Recalculate readiness after condition updates<br>buyReady := buyTrendMet and buyAdxMet and buyDiMet and buyZoneClear<br>sellReady := sellTrendMet and sellAdxMet and sellDiMet and sellZoneClear<br><br>// === STRATEGY ENTRIES === //<br>if buyReady<br>    strategy.entry(&quot;Buy&quot;, strategy.long)<br>    buyTrendMet := false<br>    buyAdxMet := false<br>    buyDiMet := false<br>    buyZoneClear := false<br><br>if sellReady<br>    strategy.entry(&quot;Sell&quot;, strategy.short)<br>    sellTrendMet := false<br>    sellAdxMet := false<br>    sellDiMet := false<br>    sellZoneClear := false<br><br>// === STRATEGY EXITS === //<br>if strategy.position_size &gt; 0 and trend == 1<br>    strategy.close(&quot;Buy&quot;)<br><br>if strategy.position_size &lt; 0 and trend == -1<br>    strategy.close(&quot;Sell&quot;)<br><br>// === PLOTS === //<br>plotshape(buyReady, location=location.belowbar, color=color.green, style=shape.labelup, text=&quot;BUY&quot;)<br>plotshape(sellReady, location=location.abovebar, color=color.red, style=shape.labeldown, text=&quot;SELL&quot;)<br><br>// For more tutorials on Tradingview Pinescript visit , visit https://www.marketcalls.in/category/tradingview</pre><p><strong>Strategy parameters</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*QSpfmpXTG8X1ORYNkpY9Ig.png" /></figure><p>The original address: <a href="https://www.fmz.com/strategy/502331">ADX and Supertrend Persistent Entry Strategy</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=fb8bfab04be5" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[An Overview of Market Making Strategies in Crypto: Architecture Design and FMZ Implementation of…]]></title>
            <link>https://medium.com/@FMZQuant/an-overview-of-market-making-strategies-in-crypto-architecture-design-and-fmz-implementation-of-5a2b500984f8?source=rss-b78414ad1c60------2</link>
            <guid isPermaLink="false">https://medium.com/p/5a2b500984f8</guid>
            <category><![CDATA[cryptocurrency]]></category>
            <category><![CDATA[trading-strategy]]></category>
            <category><![CDATA[fmz-quant]]></category>
            <category><![CDATA[market-making]]></category>
            <category><![CDATA[exchange]]></category>
            <dc:creator><![CDATA[FMZQuant]]></dc:creator>
            <pubDate>Mon, 28 Jul 2025 08:22:26 GMT</pubDate>
            <atom:updated>2025-07-28T08:22:26.809Z</atom:updated>
            <content:encoded><![CDATA[<h3><strong>An Overview of Market Making Strategies in Crypto: Architecture Design and FMZ Implementation of the Self-Matching Trading Strategy</strong></h3><h3>⚠️ Important Disclaimer</h3><p><strong>This article demonstrates a volume-boosting self-matching trading strategy intended solely for learning purposes related to trading system architecture. It fundamentally differs from traditional arbitrage or market-making strategies. The core idea of this strategy is to simulate volume through same-price buy-sell matching to obtain exchange rebates or tier-based trading fee discounts, rather than profiting from market inefficiencies.</strong></p><p><strong>The provided code is only a reference framework and has not been tested in live trading environments. The strategy implementation is purely for technical study and research, and has not been thoroughly validated under real market conditions. Readers must perform extensive backtesting and risk evaluation before considering any real-world application. Do not use this strategy for live trading without proper due diligence.</strong></p><p>In the cryptocurrency market, market-making strategies serve not only to improve liquidity and facilitate trading, but also form a core component of many quantitative trading systems. Market makers quote both buy and sell prices, provide liquidity, and capture profits under various market conditions. Professional market-making systems are often highly sophisticated, involving ultra-low-latency optimization, advanced risk management modules, and cross-exchange arbitrage mechanisms. In this article, we explore the basic concept behind a volume-boosting self-matching trading strategy and demonstrate how to implement a simplified educational framework on the FMZ Quant Trading Platform.</p><p>The main content is adapted from the original work “Market Making Strategy: Concepts and Implementation” by Zinan, with some optimizations and adjustments. While some coding practices may now appear outdated, this version recreated on the FMZ platform still offers valuable insights into the structure of trading algorithms and the fundamentals of self-matching trading logic.</p><h3>Concept of Market Making Strategies</h3><p>A Market Making Strategy refers to a trading approach where a trader (market maker) places both buy and sell orders in the market simultaneously, thereby providing liquidity and contributing to market stability. This strategy not only helps maintain market depth but also offers counterparties for other traders. By quoting buy and sell prices across various price levels, market makers aim to profit from market fluctuations.</p><p>In the context of cryptocurrency markets, market makers play a critical role — especially in markets with low trading volume or high volatility. By offering liquidity, market makers help reduce slippage and make it easier for other traders to execute orders at favorable prices.</p><p>The core principle of traditional market-making strategies lies in capturing the bid-ask spread by providing liquidity. Market makers post buy orders at lower prices and sell orders at higher prices, profiting from the difference when orders are filled. For example, when the spot price in the market rises, market makers sell at a higher price and buy at a lower price, earning the difference. The primary sources of income include:</p><ul><li><strong>Bid-ask spread:</strong> Traditional market makers earn profits by placing limit buy and sell orders and capturing the price difference between the bid and ask.</li><li><strong>Volume-based incentives:</strong> The profitability of market makers is closely tied to the trading volume they provide. Higher volume not only leads to more frequent order fills and profit opportunities but also unlocks additional benefits:<br>1). <strong>Fee rebates:</strong> Many exchanges offer fee rebates to incentivize liquidity provision. In some cases, makers receive negative fees — meaning the exchange pays the market maker for executed trades.<br>2). <strong>VIP tier discounts:</strong> Reaching specific volume thresholds may qualify market makers for lower trading fees, reducing operational costs.<br>3). <strong>Market maker incentive programs:</strong> Some exchanges run dedicated incentive programs that reward market makers based on the quality and consistency of their liquidity provision.</li></ul><p>However, market makers also face significant market risk, especially in highly volatile environments such as the cryptocurrency space. Rapid price swings may cause market makers’ quoted prices to deviate significantly from actual market conditions, potentially resulting in losses.</p><h3>Types of Market Making Strategies</h3><p>In the cryptocurrency market, market makers typically choose different strategies based on market conditions, trading volume, and volatility. Common types of market-making strategies include:</p><ul><li><strong>Passive market making:</strong> In this approach, the market maker places buy and sell limit orders based on market depth, historical volatility, and other indicators, then waits for the market to fill those orders. This strategy is characterized by low frequency and a conservative risk profile, relying on natural market movements to generate profit.</li><li><strong>Active market making:</strong> Active market makers dynamically adjust order prices and sizes in real time based on market conditions to improve execution probability. They often place orders close to the current mid-price, aiming to better capture opportunities from short-term volatility.</li><li><strong>Volume-boosting self-matching strategy:</strong> The focus of this article. A volume-boosting self-matching strategy involves placing simultaneous buy and sell orders at the same price to artificially increase trading volume. Unlike traditional market-making, this strategy is not designed to profit from bid-ask spreads. Instead, it seeks to benefit from exchange incentives such as fee rebates, VIP tier discounts, or liquidity mining rewards.</li></ul><p>In a volume-boosting self-matching strategy, the market maker posts buy and sell orders at the same price level. While these trades do not generate profits from price differentials, they quickly accumulate trading volume. Profitability is entirely dependent on the exchange’s incentive mechanisms rather than market inefficiencies or arbitrage.</p><p><strong>Key characteristics:</strong></p><ul><li><strong>Same-price orders:</strong> Unlike traditional market-making, buy and sell orders are placed at the same price, eliminating spread-based profits.</li><li><strong>Volume-oriented execution:</strong> The primary objective is to accumulate trade volume rapidly, not to exploit price arbitrage.</li><li><strong>Incentive-driven profitability:</strong> Returns are fully reliant on exchange incentives such as fee rebates, VIP tier benefits, or dedicated market maker reward programs.</li></ul><p><strong>Important distinction:</strong><br>Compared to traditional market-making strategies, volume-boosting self-matching strategies do not generate profit by providing genuine market liquidity. Instead, they create trading volume artificially to capitalize on policy-driven rewards offered by exchanges. This type of strategy may carry regulatory or compliance risks in certain jurisdictions and must be carefully evaluated before any live trading deployment.</p><h3>Profit Logic Behind Volume-Boosting Self-Matching Strategies</h3><p>Upon analyzing the code implementation, it becomes evident that the buy and sell prices are exactly the same in this strategy:</p><pre>def make_duiqiao_dict(self, trade_amount):<br>    mid_price = self.mid_price  # Med price<br>    trade_price = round(mid_price, self.price_precision)  # Accurate transaction price<br>    trade_dict = {<br>        &#39;trade_price&#39;: trade_price,  # The same price is used for both buying and selling<br>        &#39;amount&#39;: trade_amount<br>    }<br>    return trade_dict</pre><h3>Actual Profit Mechanism</h3><p><strong>1. Volume-boosting via self-matching</strong></p><ul><li>The core objective of this strategy is to increase trading volume rapidly through high-frequency self-matching.</li><li>Profit is derived from exchange incentives such as fee rebates, VIP tier upgrades, or liquidity mining rewards.</li><li>This approach is applicable on exchanges that offer formal market maker incentive programs.</li></ul><p><strong>2. Fee rebate mechanism</strong></p><ul><li>The strategy relies on exchanges offering negative maker fees (maker rates are negative)</li><li>By providing liquidity, the strategy earns rebates on filled orders.</li><li>It requires the exchange to support market maker fee discounts or rebate structures.</li></ul><h3>Suitable Scenarios &amp; Associated Risks</h3><p>✅ Suitable scenarios</p><ul><li>Exchanges with clear market maker rebate or incentive policies.</li><li>Traders aiming to meet high trading volume requirements for VIP tier upgrades.</li><li>Platforms that run liquidity mining or commission rebate campaigns.</li></ul><p>❌ Unsuitable scenarios</p><ul><li>Exchanges that do not offer fee rebates or incentives.</li><li>Platforms with high transaction fees, where self-matching leads to net losses.</li><li>Exchanges that explicitly prohibit wash trading or enforce restrictions on artificial volume.</li></ul><p>⚠️ Risk warnings</p><ul><li>If both buy and sell orders are filled simultaneously, the strategy may incur a net loss after fees.</li><li>Changes in exchange policies may render the strategy unprofitable or non-viable.</li><li>Continuous monitoring of fee structures and trading costs is required.</li><li>The strategy may face compliance risks in jurisdictions where volume-boosting trading is regulated or restricted.</li></ul><h3>Self-Matching Strategy Architecture Analysis</h3><p>This section presents a simplified implementation of a volume-boosting self-matching strategy, inspired by the framework developed by Zinan. The focus is on how to accumulate trading volume through same-price buy and sell orders within a live exchange environment. The strategy architecture is structured around two main classes: MidClass and MarketMaker. These components are responsible for handling exchange interactions and executing the self-matching logic, respectively.</p><p>The architecture follows a layered design, separating the exchange interface logic from the trading strategy logic. This ensures modularity, extensibility, and clean separation of concerns. The main components are:</p><ol><li>MidClass: The exchange middle layer is responsible for interacting with the exchange interface to obtain market data, account information, order status, etc. This layer encapsulates all interactions with external exchanges to ensure that the trading logic and the exchange interface are decoupled.</li><li>MarketMaker: The market making strategy class is responsible for executing the cross-trading strategy, generating pending orders, checking order status, updating strategy status, etc. It interacts with the exchange middle layer to provide specific market making and self-matching trading operations.</li></ol><h3>MidClass</h3><p>MidClass is the middle layer of the exchange. Its main responsibility is to handle the interaction with the exchange, encapsulate all external API calls, and provide a simple interface for MarketMaker to use. Its architecture includes the following key functions:</p><p><strong>1. Market data retrieval:</strong><br>Fetches real-time market data such as tickers, order book depth, and candlestick data (K-lines). Regular updates are essential to ensure the strategy operates on up-to-date information.</p><p><strong>2. Account information management:</strong><br>Retrieves account data, including balances, available margin, and open positions. This is critical for capital allocation and risk control.</p><p><strong>3. Order management:</strong><br>Provides functionality to place, query, and cancel orders. This is the foundation of executing a market-making or self-matching strategy and ensures robust control over open orders.</p><p><strong>4. Data Synchronization:</strong><br>Maintains persistent connections with the exchange and updates internal state for use by the strategy layer.</p><p>By encapsulating these features in MidClass, the strategy logic within MarketMaker remains focused on execution rather than infrastructure. This structure improves the maintainability and scalability of the system, making it easier to add support for different exchanges or optimize existing functions.</p><h3>MarketMaker</h3><p>MarketMaker is the core class of the self-matching strategy, responsible for executing market-making operations and handling self-matching trades. Its architecture typically includes the following key modules:</p><p><strong>1. Initialization:</strong></p><ul><li>Initialize the exchange middleware (MidClass) to retrieve exchange metadata such as trading pair details, precision, tick size, and order book depth.</li><li>Initialize the market-making strategy, set up key parameters like order quantity, price spread, and execution intervals. These parameters directly affect how the strategy behaves and performs in the market.</li></ul><p><strong>2. Data refresh:</strong></p><ul><li>Periodic market data updates, including real-time account information, market price, depth, K-line, etc. These data provide basic information for executing strategies.</li><li>The frequency of updates can be dynamically adjusted based on market volatility to ensure timely responses to market changes.</li></ul><p><strong>3. Self-matching execution logic:</strong></p><ul><li>Order book construction: Based on current market depth and price dynamics, construct a dictionary of orders (both bids and asks) with specified price and size. This is typically calculated using predefined strategy parameters.</li><li>Self-matching execution: Once the order structure is ready, MarketMaker submits both buy and sell orders at the same price level to the market. The goal is to accumulate trade volume quickly via same-price order matching.</li><li>Order status monitoring: During execution, MarketMaker will check the status of the order constantly to ensure that the pending order can be processed in time. If the order fails to be executed, it will adjust the pending order price or quantity until the order is completed.</li></ul><p><strong>4. Strategy state update:</strong></p><ul><li>Strategy status update: Regularly update key performance indicators such as cumulative trading volume, filled order count, and total fees. These metrics allow real-time tracking of the strategy’s performance.</li><li>Dynamic risk management: The strategy adapts its behavior based on current market conditions. MarketMaker can modify execution logic in real time to reduce risk and maintain operational efficiency across varying market environments.</li></ul><h3>Self-Matching Strategy Logic Reconstruction</h3><p>The implementation of a self-matching strategy relies on precise market data and fast execution. The MarketMaker class monitors real-time market conditions and leverages same-price buy and sell orders (self-matching) to rapidly accumulate trading volume, which is the core objective of this strategy.</p><h3>Initialization</h3><p>In the MarketMaker class’s initialization method, the first step is to retrieve the exchange’s precision settings, followed by initializing key strategy parameters such as quantity precision and price precision.</p><pre>self.precision_info = self.exchange_mid.get_precision()  # Get precision information<br>self.price_precision = self.precision_info[&#39;price_precision&#39;]  # Price precision<br>self.amount_precision = self.precision_info[&#39;amount_precision&#39;]  # Trading volume precision</pre><h3>Generating the Self-Matching Order Dictionary</h3><p>At the heart of the self-matching strategy is the construction of an order dictionary containing both buy and sell orders at the same price level, along with their respective quantities. The code generates the dictionary of self-matching trading orders by calculating the middle price.</p><pre>def make_duiqiao_dict(self, trade_amount):<br>    mid_price = self.mid_price  # Mid Price<br>    trade_price = round(mid_price, self.price_precision)  # Accurate transaction price<br>    trade_dict = {<br>        &#39;trade_price&#39;: trade_price,<br>        &#39;amount&#39;: trade_amount<br>    }<br>    return trade_dict</pre><h3>Executing Self-Matching Trades</h3><p>According to the generated dictionary of self-matching trading orders, the self-matching trading transaction is executed. In the code, the create_order method of the exchange middle layer is called to place buy orders and sell orders at the same time.</p><pre>def make_trade_by_dict(self, trade_dict):<br>    if self.position_amount &gt; trade_dict[&#39;amount&#39;] and self.can_buy_amount &gt; trade_dict[&#39;amount&#39;]:<br>        buy_id = self.exchange_mid.create_order(&#39;buy&#39;, trade_dict[&#39;trade_price&#39;], trade_dict[&#39;amount&#39;])  # Pending buy order<br>        sell_id = self.exchange_mid.create_order(&#39;sell&#39;, trade_dict[&#39;trade_price&#39;], trade_dict[&#39;amount&#39;])  # Pending sell order<br>        self.traded_pairs[&#39;dui_qiao&#39;].append({<br>            &#39;buy_id&#39;: buy_id, &#39;sell_id&#39;: sell_id, &#39;init_time&#39;: time.time(), &#39;amount&#39;: trade_dict[&#39;amount&#39;]<br>        })</pre><h3>Order Status Monitoring</h3><p>The strategy periodically checks the status of active orders and handles any unfilled or partially filled ones. In the code, this is done by calling the GetOrder method from the exchange middleware (MidClass). Based on the returned order status, the strategy decides whether to cancel the orders. The self-matching order management logic includes the following key steps:</p><p><strong>1. Fetching order status:</strong></p><ul><li>The strategy retrieves the current status of both the buy and sell orders through the exchange API.</li><li>If the status retrieval fails (e.g., due to a missing order or network issue), the strategy cancels the corresponding order and removes it from the active tracking list.</li></ul><p><strong>2. Evaluating order status:</strong></p><ul><li>The status returned is used to determine whether the order is filled, partially filled, or still open.</li><li>Typical order status include:<br>0(ORDER_STATE_PENDING): Order is open and waiting to be filled.<br>1(ORDER_STATE_CLOSED): Order has been completely filled.<br>2(ORDER_STATE_CANCELED): Order has been canceled.<br>3(ORDER_STATE_UNKNOWN): Order status is unknown or undefined.</li></ul><p><strong>3. Handling order status:</strong></p><ul><li>Both orders unfilled:<br>If both buy and sell orders remain unfilled (status 0), the strategy checks the polling interval (e.g., current_time % 5 == 0) to decide whether to cancel them.<br>After cancellation, the strategy updates the order count and removes the orders from the internal record.</li><li>One order filled, the other unfilled:<br>If one side of the self-matching order pair is filled (status == 1) and the other remains unfilled (status == 0), the strategy uses the polling interval condition to decide whether to cancel the unfilled order.<br>After cancelling an open order, update the volume and the list of open orders and remove the order from the record.</li><li>Both orders filled:<br>If both the buy and sell orders are fully executed (status == 1), the strategy updates the trade volume counter, and the order pair is removed from the internal tracking list.</li><li>Unknown order status:<br>If the order status is neither 0 nor 1, it is recorded as unknown status and logged.</li></ul><p><strong>4. Updating internal records:</strong><br>After processing the order statuses, the strategy updates the total accumulated trade volume, the list of unfilled or partially filled orders, the order submission and cancellation counters.</p><h3>Future Strategy Outlook</h3><p>The self-matching strategy presented in this article is primarily intended as an educational example for understanding the architectural design of trading frameworks. Its practical application in live trading is limited. For readers interested in real market-making strategies, we plan to introduce more advanced and practical models in future content:</p><p><strong>1. Order book market-making strategy</strong></p><ul><li>A true arbitrage-based approach that captures the bid-ask spread.</li><li>Places limit orders between the best bid and ask to earn the spread profit.</li><li>Closely aligns with the traditional profit model of professional market makers.</li></ul><p><strong>2. Dynamic market-making strategy</strong></p><ul><li>Adapts quote prices in real-time based on market volatility.</li><li>Integrates inventory management and risk control mechanisms.</li><li>Suitable for adaptive execution across varying market conditions.</li></ul><p><strong>3. Multi-level market-making strategy</strong></p><ul><li>Places orders at multiple price levels simultaneously.</li><li>Diversifies execution risk and enhances overall return stability.</li><li>Closer to how professional market-making systems operate in production.</li></ul><p>These upcoming strategies will emphasize realistic profit logic and robust risk management, providing quantitative traders with more actionable and valuable insights for developing production-ready systems.</p><h3>Strategy Outlook</h3><p>Self-matching strategies that rely on exchange incentive policies, such as fee rebates, VIP tier upgrades, or liquidity mining rewards — are inherently vulnerable to changes in those policies. If an exchange adjusts its fee structure or removes such incentives, the strategy may become ineffective or even result in net losses. To mitigate this, the strategy must incorporate adaptability to policy changes, such as dynamic monitoring of fee rates and trading incentives, multiple profit sources to reduce over-reliance on a single incentive. fallback mechanisms or automatic shutdown triggers if profitability thresholds are not met. Moreover, self-matching strategies may raise regulatory red flags, as they can be interpreted as attempts to manipulate market volume. In many jurisdictions, such behavior may violate market integrity laws.</p><p>Therefore, traders must stay updated on local legal and compliance requirements, consult with legal professionals when deploying volume-based strategies, avoid practices that could be construed as deceptive or manipulative.</p><p>We hope readers use this strategy framework as a foundation to build more robust, compliant, and innovative trading systems. The true value of quantitative trading lies in continuous learning, experimentation, and refinement. May your journey in quant trading be insightful, adaptive, and rewarding!</p><h3>Strategy Code</h3><pre>import time, json<br><br>class MidClass:<br>    def __init__(self, exchange_instance):<br>        &#39;&#39;&#39;<br>        Initialize the exchange middle layer<br>        <br>        Args:<br>            exchange_instance: FMZ&#39;s exchange structure<br>        &#39;&#39;&#39;<br>        self.init_timestamp = time.time()  # Record initialization time<br>        self.exchange = exchange_instance  # Save the exchange object<br>        self.exchange_name = self.exchange.GetName()  # Get the exchange name<br>        self.trading_pair = self.exchange.GetCurrency()  # Get the trading pair name (such as BTC_USDT)<br><br>    def get_precision(self):<br>        &#39;&#39;&#39;<br>        Get the accuracy information of the trading pair<br>        <br>        Returns:<br>            Returns a dictionary containing precision information, or None on failure.<br>        &#39;&#39;&#39;<br>        symbol_code = self.exchange.GetCurrency()<br>        ticker = self.exchange.GetTicker(symbol_code)  # Backtesting system needs<br>        exchange_info = self.exchange.GetMarkets()<br>        data = exchange_info.get(symbol_code)<br><br>        if not data:<br>            Log(&quot;Failed to obtain market information&quot;, GetLastError())<br>            return None<br><br>        # Get the accuracy information of the trading pair<br>        self.precision_info = {<br>            &#39;tick_size&#39;: data[&#39;TickSize&#39;],                  # Price accuracy<br>            &#39;amount_size&#39;: data[&#39;AmountSize&#39;],              # Quantity accuracy<br>            &#39;price_precision&#39;: data[&#39;PricePrecision&#39;],      # Price decimal places precision<br>            &#39;amount_precision&#39;: data[&#39;AmountPrecision&#39;],    # Number of decimal places of precision<br>            &#39;min_qty&#39;: data[&#39;MinQty&#39;],                      # Minimum order quantity<br>            &#39;max_qty&#39;: data[&#39;MaxQty&#39;]                       # Maximum order quantity<br>        }<br><br>        return self.precision_info<br><br>    def get_account(self):<br>        &#39;&#39;&#39;<br>        Get account information<br>        <br>        Returns:<br>            Returns True if the information is successfully obtained, and returns False if the information is failed.<br>        &#39;&#39;&#39;<br><br>        self.balance = &#39;---&#39;  # Account balance<br>        self.amount = &#39;---&#39;  # Account holdings<br>        self.frozen_balance = &#39;---&#39;  # Freeze balance<br>        self.frozen_stocks = &#39;---&#39;  # Freeze positions<br>        self.init_balance = None<br>        self.init_stocks = None<br>        self.init_equity = None<br><br>        try:<br>            account_info = self.exchange.GetAccount()  # Get account information<br>            self.balance = account_info[&#39;Balance&#39;]  # Update account balance<br>            self.amount = account_info[&#39;Stocks&#39;]  # Update the holdings<br>            self.frozen_balance = account_info[&#39;FrozenBalance&#39;]  # Update frozen balance<br>            self.frozen_stocks = account_info[&#39;FrozenStocks&#39;]  # Update frozen positions<br>            self.equity = self.balance + self.frozen_balance + (self.amount + self.frozen_stocks) * self.last_price<br>            <br>            if not self.init_balance or not self.init_stocks or not self.init_equity:<br>                if _G(&quot;init_balance&quot;) and _G(&quot;init_balance&quot;) &gt; 0 and _G(&quot;init_stocks&quot;) and _G(&quot;init_stocks&quot;) &gt; 0:<br>                    self.init_balance = round(_G(&quot;init_balance&quot;), 2)<br>                    self.init_stocks = round(_G(&quot;init_stocks&quot;), 2)<br>                    self.init_equity = round(_G(&quot;init_equity&quot;), 2)<br>                else:<br>                    self.init_balance = round(self.balance + self.frozen_balance, 2)<br>                    self.init_stocks = self.amount + self.frozen_stocks<br>                    self.init_equity = round(self.init_balance + (self.init_stocks * self.last_price), 2)<br>                    _G(&quot;init_balance&quot;, self.init_balance)<br>                    _G(&quot;init_stocks&quot;, self.init_stocks)<br>                    _G(&quot;init_equity&quot;, self.init_equity)<br><br>                    Log(&#39;Obtaining initial equity&#39;, self.init_equity)<br><br>            self.profit = self.equity - self.init_equity<br>            self.profitratio = round((self.equity - self.init_equity)/self.init_equity, 4) * 100<br><br>            return True<br>        except:<br>            return False  # Failed to obtain account information<br><br>    def get_ticker(self):<br>        &#39;&#39;&#39;<br>        Get market price information (such as bid price, ask price, highest price, lowest price, etc.)<br>        <br>        Returns:<br>            Returns True if the information is successfully obtained, and returns False if the information is failed.<br>        &#39;&#39;&#39;<br>        self.high_price = &#39;---&#39;  # The highest price<br>        self.low_price = &#39;---&#39;  # The lowest price<br>        self.sell_price = &#39;---&#39;  # Ask price<br>        self.buy_price = &#39;---&#39;  # Bid price<br>        self.last_price = &#39;---&#39;  # Latest transaction price<br>        self.volume = &#39;---&#39;  # Trading volume<br>        <br>        try:<br>            ticker_info = self.exchange.GetTicker()  # Get market price information<br>        <br>            self.high_price = ticker_info[&#39;High&#39;]  # Update highest price<br>            self.low_price = ticker_info[&#39;Low&#39;]  # Update lowest price<br>            self.sell_price = ticker_info[&#39;Sell&#39;]  # Update ask price<br>            self.buy_price = ticker_info[&#39;Buy&#39;]  # Update bid price<br>            self.last_price = ticker_info[&#39;Last&#39;]  # Update the latest transaction price<br>            self.volume = ticker_info[&#39;Volume&#39;]  # Update trading volume<br>            return True<br>        except:<br>            return False  # Failed to obtain market price information<br>        <br>    def get_depth(self):<br>        &#39;&#39;&#39;<br>        Get depth information (list of pending orders for buy and sell orders)<br>        <br>        Returns:<br>            Returns True if the information is successfully obtained, and returns False if the information is failed.<br>        &#39;&#39;&#39;<br>        self.ask_orders = &#39;---&#39;  # Ask order list<br>        self.bid_orders = &#39;---&#39;  # Bid order list<br>        <br>        try:<br>            depth_info = self.exchange.GetDepth()  # Get depth information<br>            self.ask_orders = depth_info[&#39;Asks&#39;]  # Update the sell order list<br>            self.bid_orders = depth_info[&#39;Bids&#39;]  # Update buy order list<br>            return True<br>        except:<br>            return False  # Failed to obtain depth information<br>        <br>    def get_ohlc_data(self, period=PERIOD_M5):<br>        &#39;&#39;&#39;<br>        Get K-line information<br>        <br>        Args:<br>            period: K-line period, PERIOD_M1 refers to 1 minute, PERIOD_M5 refers to 5 minutes, PERIOD_M15 refers to 15 minutes,<br>            PERIOD_M30 means 30 minutes, PERIOD_H1 means 1 hour, PERIOD_D1 means one day.<br>        &#39;&#39;&#39;<br>        self.ohlc_data = self.exchange.GetRecords(period)  # Get K-line data<br>        <br>    def create_order(self, order_type, price, amount):<br>        &#39;&#39;&#39;<br>        Submit an order<br>        <br>        Args:<br>            order_type: Order type, &#39;buy&#39; refers to a buy order, &#39;sell&#39; refers to a sell order<br>            price: Order price<br>            amount: Order amount <br>            <br>        Returns:<br>            Order ID number, which can be used to cancel the order<br>        &#39;&#39;&#39;<br>        if order_type == &#39;buy&#39;:<br>            try:<br>                order_id = self.exchange.Buy(price, amount)  # Submit a buy order<br>            except:<br>                return False  # Buy order submission failed<br>            <br>        elif order_type == &#39;sell&#39;:<br>            try:<br>                order_id = self.exchange.Sell(price, amount)  # Submit a sell order<br>            except:<br>                return False  # Sell order submission failed<br>        <br>        return order_id  # Returns the order ID<br>    <br>    def get_orders(self):<br>        &#39;&#39;&#39;<br>        Get a list of uncompleted orders<br>        <br>        Returns:<br>            List of uncompleted orders<br>        &#39;&#39;&#39;<br>        self.open_orders = self.exchange.GetOrders()  # Get uncompleted orders<br>        return self.open_orders<br>    <br>    def cancel_order(self, order_id):<br>        &#39;&#39;&#39;<br>        Cancel a pending order<br>        <br>        Args:<br>            order_id: The ID number of the pending order you wish to cancel<br>            <br>        Returns:<br>            Returns True if the pending order is successfully cancelled, and returns False if the pending order is failed.<br>        &#39;&#39;&#39;<br>        return self.exchange.CancelOrder(order_id)  # Cancel the order<br>        <br>    def refresh_data(self):<br>        &#39;&#39;&#39;<br>        Refresh information (account, market price, depth, K-line)<br>        <br>        Returns:<br>            If the refresh information is successfully returned, &#39;refresh_data_finish!&#39; will be returned. Otherwise, the corresponding refresh failure information prompt will be returned.<br>        &#39;&#39;&#39;<br><br>        if not self.get_ticker():  # Refresh market price information<br>            return &#39;false_get_ticker&#39;<br><br>        if not self.get_account():  # Refresh account information<br>            return &#39;false_get_account&#39;<br>        <br>        if not self.get_depth():  # Refresh depth information<br>            return &#39;false_get_depth&#39;<br>        <br>        try:<br>            self.get_ohlc_data()  # Refresh K-line information<br>        except:<br>            return &#39;false_get_K_line_info&#39;<br>        <br>        return &#39;refresh_data_finish!&#39;  # Refresh successfully<br><br>class MarketMaker:<br>    def __init__(self, mid_class):<br>        &#39;&#39;&#39;<br>        Initialize market making strategy<br>        <br>        Args:<br>            mid_class: Exchange middle layer object<br>        &#39;&#39;&#39;<br>        self.exchange_mid = mid_class  # Exchange middle layer object<br>        self.precision_info = self.exchange_mid.get_precision()  # Get accuracy information<br><br>        self.done_amount = {&#39;dui_qiao&#39;: 0}  # Completed transactions<br>        self.price_precision = self.precision_info[&#39;price_precision&#39;]  # Price precision<br>        self.amount_precision = self.precision_info[&#39;amount_precision&#39;]  # Trading volume precision<br>        <br>        self.traded_pairs = {&#39;dui_qiao&#39;: []}  # Trading pairs with pending orders<br>        self.pending_orders = []  # Uncompleted order status<br>        self.pending_order_count = 0  # Number of pending orders<br><br>        self.buy_amount = 0<br>        self.sell_amount = 0<br><br>        self.fee = 0<br>        self.fee_rate = 0.08 / 100<br><br>        self.chart = {<br>            &quot;__isStock&quot;: True,<br>            &quot;tooltip&quot;: {&quot;xDateFormat&quot;: &quot;%Y-%m-%d %H:%M:%S, %A&quot;},<br>            &quot;title&quot;: {&quot;text&quot;: &quot;Number of pending orders&quot;},<br>            &quot;xAxis&quot;: {&quot;type&quot;: &quot;datetime&quot;},<br>            &quot;yAxis&quot;: {<br>                &quot;title&quot;: {&quot;text&quot;: &quot;Number of pending orders&quot;},<br>                &quot;opposite&quot;: False<br>            },<br>            &quot;series&quot;: [<br>                {&quot;name&quot;: &quot;Buy order quantity&quot;, &quot;id&quot;: &quot;Buy order quantity&quot;, &quot;data&quot;: []},<br>                {&quot;name&quot;: &quot;Sell order quantity&quot;, &quot;id&quot;: &quot;Sell order quantity&quot;, &quot;dashStyle&quot;: &quot;shortdash&quot;, &quot;data&quot;: []}<br>            ]<br>        }<br>    <br>    def refresh_data(self):<br>        &#39;&#39;&#39;<br>        Refresh data (account, market price, depth, K-line)<br>        &#39;&#39;&#39;<br>        self.exchange_mid.refresh_data()  # Refresh exchange data<br>        self.position_amount = 0 if isinstance(self.exchange_mid.amount, str) else self.exchange_mid.amount  # Holding positions<br>        self.available_balance = 0 if isinstance(self.exchange_mid.balance, str) else self.exchange_mid.balance  # Account balance<br>        Log(&#39;Check ticker&#39;, self.exchange_mid.buy_price)<br>        self.can_buy_amount = self.available_balance / float(self.exchange_mid.buy_price)  # Quantity available for purchase<br>        self.mid_price = (self.exchange_mid.sell_price + self.exchange_mid.buy_price) / 2  # Mid Price<br><br>    def make_duiqiao_dict(self, trade_amount):<br>        <br>        &#39;&#39;&#39;<br>        Generate a dictionary of self-matching orders<br>        <br>        Args:<br>            trade_amount: Volume per transaction<br>        <br>        Returns:<br>            Dictionary list of self-matching orders<br>        &#39;&#39;&#39;<br>        Log(&#39;3 Create a dictionary for self-matching orders&#39;)<br><br>        mid_price = self.mid_price  # Mid price<br><br>        trade_price = round(mid_price, self.price_precision)  # Accurate transaction price<br><br>        trade_dict = {<br>            &#39;trade_price&#39;: trade_price,<br>            &#39;amount&#39;: trade_amount<br>        }<br><br>        Log(&#39;Returns the market order dictionary:&#39;, trade_dict)<br>        return trade_dict<br>    <br>    def make_trade_by_dict(self, trade_dict):<br>        &#39;&#39;&#39;<br>        Execute transactions according to the transaction dictionary<br>        <br>        Args:<br>            trade_dict: transaction dictionary<br>        &#39;&#39;&#39;<br>        Log(&#39;4 Start trading by dictionary&#39;)<br>        self.refresh_data()  # Refresh data<br>        <br>        if trade_dict:<br>            Log(&#39;Current account funds: Coin balance: &#39;, self.position_amount, &#39;Funds balance: &#39;, self.can_buy_amount)<br>            Log(&#39;Check open positions: Coin limit: &#39;, self.position_amount &gt; trade_dict[&#39;amount&#39;], &#39;Funding restrictions: &#39;, self.can_buy_amount &gt; trade_dict[&#39;amount&#39;])<br>            if self.position_amount &gt; trade_dict[&#39;amount&#39;] and self.can_buy_amount &gt; trade_dict[&#39;amount&#39;]:<br>                buy_id = self.exchange_mid.create_order(&#39;buy&#39;, trade_dict[&#39;trade_price&#39;], trade_dict[&#39;amount&#39;])  # Pending buy order<br>                sell_id = self.exchange_mid.create_order(&#39;sell&#39;, trade_dict[&#39;trade_price&#39;], trade_dict[&#39;amount&#39;])  # Pending sell order<br>                <br>                self.traded_pairs[&#39;dui_qiao&#39;].append({<br>                    &#39;buy_id&#39;: buy_id, &#39;sell_id&#39;: sell_id, &#39;init_time&#39;: time.time(), &#39;amount&#39;: trade_dict[&#39;amount&#39;]<br>                })<br>                    <br>                self.last_time = time.time()  # Update last transaction time<br>        <br>    def handle_pending_orders(self):<br>        &#39;&#39;&#39;<br>        Processing unfulfilled orders<br>        &#39;&#39;&#39;<br>        pending_orders = self.exchange_mid.get_orders()  # Get uncompleted orders<br>        if len(pending_orders) &gt; 0:<br>            for order in pending_orders:<br>                self.exchange_mid.cancel_order(order[&#39;Id&#39;])  # Cancel uncompleted orders<br><br>    def check_order_status(self, current_time):<br>        &#39;&#39;&#39;<br>        Check order status<br>        current_time: Polling check times<br>        &#39;&#39;&#39;<br>        Log(&#39;1 Start order information check&#39;)<br>        Log(self.traded_pairs[&#39;dui_qiao&#39;])<br>        self.buy_pending = 0<br>        self.sell_pending = 0<br>        for traded_pair in self.traded_pairs[&#39;dui_qiao&#39;].copy():<br>            Log(&#39;Check the order:&#39;, traded_pair[&#39;buy_id&#39;], traded_pair[&#39;sell_id&#39;])<br><br>            try:<br>                buy_order_status = self.exchange_mid.exchange.GetOrder(traded_pair[&#39;buy_id&#39;])  # Get buy order status<br>                sell_order_status = self.exchange_mid.exchange.GetOrder(traded_pair[&#39;sell_id&#39;])  # Get sell order status<br>            except:<br>                Log(traded_pair, &#39;cancel&#39;)<br>                self.exchange_mid.cancel_order(traded_pair[&#39;buy_id&#39;])  # Cancel buy order<br>                self.exchange_mid.cancel_order(traded_pair[&#39;sell_id&#39;])  # Cancel sell order<br>                self.traded_pairs[&#39;dui_qiao&#39;].remove(traded_pair)  # Remove order<br>                return<br><br>            Log(&#39;Check the order:&#39;, traded_pair[&#39;buy_id&#39;], buy_order_status, traded_pair[&#39;sell_id&#39;], sell_order_status, [sell_order_status[&#39;Status&#39;], buy_order_status[&#39;Status&#39;]])<br>            if [sell_order_status[&#39;Status&#39;], buy_order_status[&#39;Status&#39;]] == [0, 0]:<br>                self.buy_pending += 1<br>                self.sell_pending += 1<br>                if current_time % 5 == 0:<br>                    Log(&#39;Check pending orders and cancel pending orders (two unfinished)&#39;, buy_order_status[&#39;Status&#39;], sell_order_status[&#39;Status&#39;], current_time % 5)<br>                    self.exchange_mid.cancel_order(traded_pair[&#39;buy_id&#39;])  # Cancel buy order<br>                    self.exchange_mid.cancel_order(traded_pair[&#39;sell_id&#39;])  # Cancel sell order<br>                    self.pending_order_count += 1  # The number of pending orders increases by 1<br>                    self.traded_pairs[&#39;dui_qiao&#39;].remove(traded_pair)  # Remove order<br><br>            elif {sell_order_status[&#39;Status&#39;], buy_order_status[&#39;Status&#39;]} == {1, 0}:<br>                if buy_order_status[&#39;Status&#39;] == ORDER_STATE_PENDING:<br>                    self.buy_pending += 1<br>                if sell_order_status[&#39;Status&#39;] == ORDER_STATE_PENDING:<br>                    self.sell_pending += 1<br>                if current_time % 5 == 0:<br>                    Log(&#39;Check pending orders and cancel pending orders (part one is not yet completed)&#39;, buy_order_status[&#39;Status&#39;], sell_order_status[&#39;Status&#39;])<br>                    self.done_amount[&#39;dui_qiao&#39;] += traded_pair[&#39;amount&#39;]  # Update transaction volume<br>                    if buy_order_status[&#39;Status&#39;] == ORDER_STATE_PENDING:<br>                        self.sell_amount += traded_pair[&#39;amount&#39;]<br>                        self.fee += sell_order_status[&#39;Amount&#39;] * self.fee_rate * sell_order_status[&#39;Price&#39;]<br>                        Log(&#39;Cancel the buy order and add the unfinished buy list&#39;, traded_pair[&#39;buy_id&#39;])<br>                        self.exchange_mid.cancel_order(traded_pair[&#39;buy_id&#39;])  # Cancel buy order<br>                        self.pending_orders.append([&#39;buy&#39;, buy_order_status[&#39;Status&#39;]])  # Record uncompleted orders<br>                        Log(&#39;Before clearing:&#39;, self.traded_pairs[&#39;dui_qiao&#39;])<br>                        Log(&#39;Clear id:&#39;, traded_pair)<br>                        self.traded_pairs[&#39;dui_qiao&#39;].remove(traded_pair)  # Remove order<br>                        Log(&#39;After clearing:&#39;, self.traded_pairs[&#39;dui_qiao&#39;])<br>                    elif sell_order_status[&#39;Status&#39;] == ORDER_STATE_PENDING:<br>                        self.buy_amount += traded_pair[&#39;amount&#39;]<br>                        self.fee += buy_order_status[&#39;Amount&#39;] * self.fee_rate * buy_order_status[&#39;Price&#39;]<br>                        Log(&#39;Cancel the sell order and add it to the unfinished sell list&#39;, traded_pair[&#39;sell_id&#39;])<br>                        self.exchange_mid.cancel_order(traded_pair[&#39;sell_id&#39;])  # Cancel sell order<br>                        self.pending_orders.append([&#39;sell&#39;, sell_order_status[&#39;Status&#39;]])  # Record uncompleted orders<br>                        Log(&#39;Before clearing:&#39;, self.traded_pairs[&#39;dui_qiao&#39;])<br>                        Log(&#39;Clear id:&#39;, traded_pair)<br>                        self.traded_pairs[&#39;dui_qiao&#39;].remove(traded_pair)  # Remove order<br>                        Log(&#39;After clearing:&#39;, self.traded_pairs[&#39;dui_qiao&#39;])<br>                <br>            elif [sell_order_status[&#39;Status&#39;], buy_order_status[&#39;Status&#39;]] == [1, 1]:<br>                Log(&#39;Both orders have been completed&#39;)<br>                self.buy_amount += traded_pair[&#39;amount&#39;]<br>                self.sell_amount += traded_pair[&#39;amount&#39;]<br>                self.fee += buy_order_status[&#39;Amount&#39;] * self.fee_rate * buy_order_status[&#39;Price&#39;]<br>                self.fee += sell_order_status[&#39;Amount&#39;] * self.fee_rate * sell_order_status[&#39;Price&#39;]<br>                Log(&#39;Completion status:&#39;, buy_order_status[&#39;Status&#39;], sell_order_status[&#39;Status&#39;], traded_pair[&#39;amount&#39;])<br>                self.done_amount[&#39;dui_qiao&#39;] += 2 * traded_pair[&#39;amount&#39;]  # Update transaction volume<br>                self.traded_pairs[&#39;dui_qiao&#39;].remove(traded_pair)  # Remove order<br>            else:<br>                Log(&#39;Two orders are in unknown status:&#39;, buy_order_status, sell_order_status)<br>                Log(&#39;Unknown order status:&#39;, buy_order_status[&#39;Status&#39;], sell_order_status[&#39;Status&#39;])<br>                Log(&#39;Unknown order information:&#39;, traded_pair)<br>        <br>    def update_status(self):<br><br>        self.exchange_mid.refresh_data()<br><br>        table1 = {<br>            &quot;type&quot;: &quot;table&quot;,<br>            &quot;title&quot;: &quot;Account information&quot;,<br>            &quot;cols&quot;: [<br>                &quot;Initial funds&quot;, &quot;Existing funds&quot;, &quot;Self-matching buy amount&quot;, &quot;Self-matching sell  amount&quot;, &quot;Fee rate&quot;, &quot;Total return&quot;, &quot;Rate of return&quot;<br>            ],<br>            &quot;rows&quot;: [<br>                [   <br>                    self.exchange_mid.init_equity,<br>                    self.exchange_mid.equity,<br>                    round(self.buy_amount, 4),<br>                    round(self.sell_amount, 4),<br>                    round(self.fee, 2),<br>                    self.exchange_mid.profit,<br>                    str(self.exchange_mid.profitratio) + &quot;%&quot;<br>                ],<br>            ],<br>        }<br><br>        LogStatus(<br>            f&quot;Initialization time: {time.strftime(&#39;%Y-%m-%d %H:%M:%S&#39;, time.localtime(self.exchange_mid.init_timestamp))}\n&quot;,<br>            f&quot;`{json.dumps(table1)}`\n&quot;,<br>            f&quot;Last execution time: {_D()}\n&quot;<br>        )<br><br>        LogProfit(round(self.exchange_mid.profit, 3), &#39;&amp;&#39;)<br><br>    def plot_pending(self):<br>        <br>        Log(&#39;Number of knock-on orders:&#39;, self.buy_pending, self.sell_pending)<br>        self.obj_chart = Chart(self.chart)<br>        now_time = int(time.time() * 1000)<br>        # Update pending order buy volume data<br>        self.obj_chart.add(0, [now_time, self.buy_pending])<br>        # Update pending order selling volume data<br>        self.obj_chart.add(1, [now_time, self.sell_pending])<br><br><br>def main():<br>    &#39;&#39;&#39;<br>    Main function, running market making strategy<br>    &#39;&#39;&#39;<br>    exchange.IO(&#39;simulate&#39;, True)<br>    exchange.IO(&quot;trade_super_margin&quot;)<br>    <br>    target_amount = 1  # Target transaction volume<br>    trade_amount = 0.01  # Volume per transaction<br>    trade_dict = {}  # Initialize transaction dictionary<br>    <br>    exchange_mid = MidClass(exchange)  # Initialize the exchange middle layer<br>    Log(exchange_mid.refresh_data())  # Refresh data<br>    market_maker = MarketMaker(exchange_mid)  # Initialize market making strategy<br><br>    check_times = 0<br>    <br>    while market_maker.done_amount[&#39;dui_qiao&#39;] &lt; target_amount:  # Loop until the target transaction volume is reached<br>        Log(market_maker.traded_pairs[&#39;dui_qiao&#39;])<br>        market_maker.check_order_status(check_times)  # Check order status<br>        Sleep(1000)  # Wait 1 second<br>        market_maker.refresh_data()  # Refresh data<br>        <br>        if len(market_maker.traded_pairs[&#39;dui_qiao&#39;]) &lt; 1: # Price moves, market orders are cancelled, wait until all orders are completed, and create a new order dictionary<br>            <br>            Log(&#39;2 The number of trading pairs on the market is less than 1&#39;)<br>            trade_dict = market_maker.make_duiqiao_dict(trade_amount)  # Generate a dictionary of pending orders<br>            Log(&#39;New trading dictionary&#39;, trade_dict)<br>        <br>        if trade_dict:  # Check if the dictionary is not empty<br>            market_maker.make_trade_by_dict(trade_dict)  # Execute a trade<br><br>        Log(&#39;Market making quantity:&#39;, market_maker.done_amount[&#39;dui_qiao&#39;])  # Record transaction volume<br><br>        market_maker.plot_pending()<br>        market_maker.update_status()<br><br>        check_times += 1<br>        <br>    Log(market_maker.position_amount, market_maker.can_buy_amount)  # Record holdings and available purchase quantities<br>    Log(&#39;Existing orders:&#39;, exchange.GetOrders())  # Record existing orders<br><br>def onexit():<br>    Log(&quot;Execute the sweep function&quot;)<br><br>    _G(&quot;init_balance&quot;, None)<br>    _G(&quot;init_stocks&quot;, None)<br>    _G(&quot;init_equity&quot;, None)</pre><p>From: <a href="https://www.fmz.com/bbs-topic/10706">An Overview of Market Making Strategies in Crypto: Architecture Design and FMZ Implementation of the Self-Matching Trading Strategy</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=5a2b500984f8" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Multi-Indicator Breakout Trend Following Strategy]]></title>
            <link>https://medium.com/@FMZQuant/multi-indicator-breakout-trend-following-strategy-68c9e26ce2ec?source=rss-b78414ad1c60------2</link>
            <guid isPermaLink="false">https://medium.com/p/68c9e26ce2ec</guid>
            <category><![CDATA[breakout-trading-strategy]]></category>
            <category><![CDATA[fmz-quant]]></category>
            <category><![CDATA[trend-following]]></category>
            <category><![CDATA[multi-indicator]]></category>
            <category><![CDATA[cryptocurrency]]></category>
            <dc:creator><![CDATA[FMZQuant]]></dc:creator>
            <pubDate>Mon, 28 Jul 2025 02:14:29 GMT</pubDate>
            <atom:updated>2025-07-28T02:14:29.882Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*Y1RbApQqRU0JlSM7.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*-itBTZ7Y2i2PTKav.png" /></figure><h4>Overview</h4><p>The Multi-Indicator Breakout Trend Following Strategy is a quantitative trading approach based on the classic Turtle Trading system, designed to capture strong market trends through multi-period breakout signals. The core of this strategy lies in utilizing price breakouts across different time periods as entry and exit signals, while incorporating ATR (Average True Range) for risk control and position sizing. This strategy can function both as an indicator to identify market breakout signals and as a complete automated trading system. Its strength lies in systematically capturing trending opportunities while enhancing capital efficiency through strict risk management.</p><h4>Strategy Principles</h4><p>The fundamental principle of this strategy is to identify potential trend movements by recognizing when prices break through historical highs or lows. The specific implementation logic is as follows:</p><ol><li><strong>Entry Mechanism</strong>: The strategy uses the highest and lowest prices over the N1 period (default 20 periods) as breakout references. When the price breaks above the highest price of the previous N1 periods, a long entry signal is generated; when the price breaks below the lowest price of the previous N1 periods, a short entry signal is generated.</li><li><strong>Exit Mechanism</strong>: The strategy employs a dual exit mechanism:</li></ol><ul><li>Stop Loss Exit: Dynamic stop loss levels are set based on ATR, defaulting to the entry price minus (for longs) or plus (for shorts) 2 times the ATR value.</li><li>Trend Reversal Exit: When the price falls below the lowest price of the N2 period (default 10 periods), long positions are closed; when the price breaks above the highest price of the N2 period, short positions are closed.</li></ul><p><strong>3. Position Management</strong>: The strategy calculates trading unit size based on volatility (ATR) and risk ratio, ensuring that each trade’s risk is controlled at a fixed percentage (default 1%) of account capital. The calculation formula is:</p><ul><li>Trading Units = Risk Amount / (ATR * Value Per Point)</li></ul><p>where Risk Amount equals the initial capital multiplied by the risk percentage.</p><p><strong>4. Trade Execution</strong>: The strategy only executes new entry signals when there are no existing positions, avoiding repeated entries, while recording the entry price for calculating stop loss positions.</p><h4>Strategy Advantages</h4><ol><li><strong>Trend Following Capability</strong>: The strategy is focused on capturing major trends by identifying potential trend starting points through breakout signals, effectively utilizing trending market movements.</li><li><strong>Dynamic Risk Control</strong>: Stop loss positions are calculated using ATR, dynamically adjusting the stop loss distance based on actual market volatility. This approach avoids both the frequent stops caused by fixed stops being too close and the excessive losses from stops being too far.</li><li><strong>Adaptive Position Sizing</strong>: Position size is dynamically adjusted based on market volatility and account risk ratio, automatically reducing positions in highly volatile markets and appropriately increasing positions in low volatility markets, achieving balanced control of risk exposure.</li><li><strong>Parameter Adjustability</strong>: The strategy provides interfaces for adjusting multiple key parameters (N1, N2, ATR period, risk ratio, etc.), allowing users to optimize based on different market environments and personal risk preferences.</li><li><strong>Systematic Trading</strong>: Fully systematized trading rules eliminate emotional interference, strictly following preset entry, exit, and capital management rules, improving trading discipline.</li></ol><h4>Strategy Risks</h4><ol><li><strong>Poor Performance in Ranging Markets</strong>: As a trend following strategy, it tends to generate frequent false breakout signals in sideways, ranging markets, leading to consecutive stop losses. A solution could be to add volatility filtering conditions, considering entry only when volatility exceeds a certain threshold.</li><li><strong>Slippage and Commission Impact</strong>: In high-frequency trading or markets with insufficient liquidity, slippage and commissions may significantly affect strategy performance. This issue can be mitigated by reducing trading frequency or adding signal confirmation mechanisms.</li><li><strong>Parameter Sensitivity</strong>: Strategy performance is relatively sensitive to N1 and N2 parameter settings, with optimal parameters potentially varying greatly across different markets and timeframes. It is recommended to find robust parameter combinations through historical backtesting, avoiding curve-fitting from excessive optimization.</li><li><strong>Gap Risk</strong>: In price gaps caused by sudden major events, stop loss orders may not execute at the expected price, causing losses beyond expectations. Consider adding maximum loss limits or introducing volatility adjustment factors.</li><li><strong>Capital Management Risk</strong>: Despite the strategy’s risk control mechanisms, consecutive stop losses in extreme market conditions may still lead to significant drawdowns in the capital curve. It is advisable to set limits on the maximum number of consecutive losses or introduce overall risk exposure controls.</li></ol><h4>Optimization Directions</h4><ol><li><strong>Multi-Timeframe Confirmation</strong>: Introduce longer period trend confirmation mechanisms, considering entry only when trends across multiple timeframes are consistent, improving signal quality. For example, add conditions to check whether the daily trend direction is consistent with the current trading period’s trend direction.</li><li><strong>Volatility Filtering</strong>: Introduce volatility filtering conditions, executing trade signals only when market volatility is within a reasonable range, avoiding entry in overly calm or excessively volatile markets. Relative ATR values (such as ATR/price ratio) can be used as filtering indicators.</li><li><strong>Signal Confirmation Mechanism</strong>: Add breakout confirmation mechanisms, such as requiring the price to maintain a certain time or amplitude after breakout before confirming signal validity, reducing losses from false breakouts.</li><li><strong>Dynamic Parameter Adjustment</strong>: Dynamically adjust N1 and N2 parameters based on market conditions, using different parameter combinations in different volatility environments, improving the strategy’s adaptability to market environments.</li><li><strong>Incorporate Trend Strength Assessment</strong>: Combine trend strength indicators (such as ADX, linear regression slope, etc.) to evaluate current trend strength, considering entry only when trend strength reaches a certain threshold, improving the accuracy of trend capture.</li><li><strong>Optimize Stop Loss Mechanism</strong>: Consider introducing trailing stops or support/resistance-based stop methods, giving trends more room to develop while maintaining risk control functionality.</li></ol><h4>Summary</h4><p>The Multi-Indicator Breakout Trend Following Strategy is a systematic trading approach that combines classic Turtle Trading concepts with modern risk management techniques. By determining trend direction through multi-period price breakouts and implementing dynamic stop losses and position control with ATR, this strategy can effectively capture significant trending opportunities in the market.</p><p>The core advantages of this strategy lie in its systematic trading rules and strict risk control, avoiding emotional interference while providing high flexibility through parameter adjustments. However, as a trend following strategy, its performance may be poor in ranging markets, requiring users to understand its applicable scenarios and perform appropriate parameter optimization.</p><p>By introducing optimization directions such as multi-timeframe confirmation, volatility filtering, and signal confirmation mechanisms, this strategy has the potential to further improve signal quality and stability, adapting to more diverse market environments. Ultimately, the Multi-Indicator Breakout Trend Following Strategy provides traders with a reliable, systematic method to capture market trends while controlling risk, achieving long-term stable trading performance.</p><p><strong>Strategy source code</strong></p><pre>/*backtest<br>start: 2024-07-03 00:00:00<br>end: 2025-07-01 08:00:00<br>period: 1d<br>basePeriod: 1d<br>exchanges: [{&quot;eid&quot;:&quot;Futures_Binance&quot;,&quot;currency&quot;:&quot;DOGE_USDT&quot;}]<br>*/<br><br>//@version=5<br>strategy(&quot;Turtle Trading Strategy (Simplified)&quot;, overlay=true, initial_capital=10000, default_qty_type=strategy.cash, default_qty_value=1000, commission_type=strategy.commission.cash_per_order, commission_value=1)<br><br>// --- Strategy Inputs ---<br>n1_entry_period = input.int(20, title=&quot;Entry Lookback Period (N1)&quot;, minval=1)<br>n2_exit_period = input.int(10, title=&quot;Exit Lookback Period (N2)&quot;, minval=1)<br>atr_period = input.int(20, title=&quot;ATR Period&quot;, minval=1)<br>atr_multiplier = input.float(2.0, title=&quot;ATR Stop Multiplier&quot;, minval=0.1)<br>risk_per_trade_percent = input.float(1.0, title=&quot;Risk Per Trade (%)&quot;, minval=0.1, maxval=10.0)<br><br>// --- Calculate Channels ---<br>highest_high_n1 = ta.highest(high, n1_entry_period)<br>lowest_low_n1 = ta.lowest(low, n1_entry_period)<br><br>highest_high_n2 = ta.highest(high, n2_exit_period)<br>lowest_low_n2 = ta.lowest(low, n2_exit_period)<br><br>// --- Calculate ATR (Average True Range) ---<br>atr_value = ta.atr(atr_period)<br><br>// --- Position Sizing (Simplified) ---<br>// This aims to calculate units based on a fixed percentage risk per trade.<br>// 1 Unit = 1 ATR worth of movement. Risk 1% of equity per trade.<br>risk_amount = strategy.initial_capital * (risk_per_trade_percent / 100)<br>dollar_per_point = syminfo.mintick // Or your instrument&#39;s specific dollar per point value<br>unit_size = atr_value * dollar_per_point &gt; 0 ? math.round(risk_amount / (atr_value * dollar_per_point)) : 0<br><br>// Ensure unit_size is at least 1 if risk allows, and cap it for realism<br>if unit_size == 0 and risk_amount &gt; 0<br>    unit_size := 1 // Minimum 1 unit if risk allows any trade<br>if unit_size &gt; 10000 // Cap unit size to prevent excessively large positions in backtesting<br>    unit_size := 10000<br><br>// --- Entry Logic ---<br>long_condition = ta.crossover(close, highest_high_n1[1]) // Break above previous N1 high<br>short_condition = ta.crossunder(close, lowest_low_n1[1]) // Break below previous N1 low<br><br>// Variables to store entry information only for the *current* bar<br>var float current_entry_price = na<br>var int current_entry_type = 0 // 1 for long, -1 for short, 0 for no entry<br><br>if long_condition and strategy.opentrades == 0 // Only enter if no open positions<br>    strategy.entry(&quot;Long&quot;, strategy.long, qty=unit_size, comment=&quot;Turtle Long Entry&quot;)<br>    // Store entry details for the current bar<br>    current_entry_price := close // Or strategy.opentrades[0].entry_price if you prefer but close on entry bar is often same<br>    current_entry_type := 1<br><br>if short_condition and strategy.opentrades == 0 // Only enter if no open positions<br>    strategy.entry(&quot;Short&quot;, strategy.short, qty=unit_size, comment=&quot;Turtle Short Entry&quot;)<br>    // Store entry details for the current bar<br>    current_entry_price := close // Or strategy.opentrades[0].entry_price<br>    current_entry_type := -1<br><br>// --- Exit Logic ---<br><br>// Declare persistent variables to store stop prices<br>var float long_stop_price = na<br>var float short_stop_price = na<br><br>// Calculate and store stop price on the bar *after* an entry<br>if current_entry_type[1] == 1 // If a long entry occurred on the previous bar<br>    long_stop_price := current_entry_price[1] - (atr_value[1] * atr_multiplier) // Use values from previous bar<br>    short_stop_price := na // Reset short stop<br><br>if current_entry_type[1] == -1 // If a short entry occurred on the previous bar<br>    short_stop_price := current_entry_price[1] + (atr_value[1] * atr_multiplier) // Use values from previous bar<br>    long_stop_price := na // Reset long stop<br><br>// Stop Loss for Long Positions<br>if strategy.position_size &gt; 0 // We have a long position<br>    strategy.exit(&quot;Long Exit SL&quot;, from_entry=&quot;Long&quot;, stop=long_stop_price, comment=&quot;Long Stop Loss&quot;)<br><br>// Stop Loss for Short Positions<br>if strategy.position_size &lt; 0 // We have a short position<br>    strategy.exit(&quot;Short Exit SL&quot;, from_entry=&quot;Short&quot;, stop=short_stop_price, comment=&quot;Short Stop Loss&quot;)<br><br>// N2 Exit for Long Positions<br>if strategy.position_size &gt; 0 and ta.crossunder(close, lowest_low_n2[1])<br>    strategy.close(&quot;Long&quot;, comment=&quot;Turtle Long N2 Exit&quot;)<br><br>// N2 Exit for Short Positions<br>if strategy.position_size &lt; 0 and ta.crossover(close, highest_high_n2[1])<br>    strategy.close(&quot;Short&quot;, comment=&quot;Turtle Short N2 Exit&quot;)<br><br>// --- Plotting for Visualization ---<br>plot(highest_high_n1, &quot;N1 High&quot;, color=color.green, linewidth=2, style=plot.style_linebr)<br>plot(lowest_low_n1, &quot;N1 Low&quot;, color=color.red, linewidth=2, style=plot.style_linebr)<br>plot(highest_high_n2, &quot;N2 High (Exit)&quot;, color=color.blue, linewidth=1, style=plot.style_linebr)<br>plot(lowest_low_n2, &quot;N2 Low (Exit)&quot;, color=color.orange, linewidth=1, style=plot.style_linebr)</pre><p>Strategy parameters</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*7G3KmwQmay2kx6Yfdzaj-A.png" /></figure><p>The original address: <a href="https://www.fmz.com/strategy/500319">Multi-Indicator Breakout Trend Following Strategy</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=68c9e26ce2ec" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[RAHA Quantitative Dynamic Weight Moving Average Short-Term Trend Strategy]]></title>
            <link>https://medium.com/@FMZQuant/raha-quantitative-dynamic-weight-moving-average-short-term-trend-strategy-7cf826619c83?source=rss-b78414ad1c60------2</link>
            <guid isPermaLink="false">https://medium.com/p/7cf826619c83</guid>
            <category><![CDATA[fmz-quant]]></category>
            <category><![CDATA[moving-average]]></category>
            <category><![CDATA[trading-strategy]]></category>
            <category><![CDATA[cryptocurrency]]></category>
            <category><![CDATA[raha]]></category>
            <dc:creator><![CDATA[FMZQuant]]></dc:creator>
            <pubDate>Mon, 28 Jul 2025 00:49:45 GMT</pubDate>
            <atom:updated>2025-07-28T00:49:45.790Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*JzbyHgYc4Yus0Dek.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*k4ZOCIN55DW6xKmD.png" /></figure><h3>1. Overview</h3><p>The RAHA Quantitative Dynamic Weight Moving Average Short-Term Trend Strategy is a short-term trading system based on the Roni’s Adjusted Hybrid Average (RAHA) indicator. Developed by Aharon Roni Pesach, this strategy’s core is a special moving average calculation method that assigns different weights to outliers, giving extreme values (particularly high or low) a lower weight. RAHA calculation is based on the standard deviation and average of the data, resulting in a more sensitive yet stable moving average that doesn’t ignore outliers but considers them proportionally. The strategy identifies negative trends and enters when clear technical conditions are met, such as a downward slope of RAHA 40, RAHA 10 crossing below RAHA 20, and the absence of a sequence of 3 red candles. Entry is also made in the exceptional case of a red candle above the Bollinger Band. Position size is determined by 1% of capital divided by the stop loss distance, and exits are triggered by a stop above the high or additional conditions below the profit target (TP).</p><h3>2. Strategy Principles</h3><p>The core of the RAHA Quantitative Dynamic Weight Moving Average Short-Term Trend Strategy lies in its unique moving average calculation method. While traditional moving averages give each price point the same weight, RAHA dynamically adjusts weights based on how much price points deviate from the mean. The implementation follows these steps:</p><ol><li>First, calculate standard SMA and standard deviation</li><li>For each price point, calculate weight based on its deviation from the mean: weight = 1 / (1 + sensitivity * |price-mean| / standard deviation)</li><li>Use these weights to calculate the weighted average</li></ol><p>The strategy uses RAHA moving averages of different periods (5, 10, 20, and 40) to capture market trends. Entry signals are based on the following conditions:</p><ul><li>RAHA 40 sloping downward (current value less than previous)</li><li>RAHA 10 crossing under or positioned below RAHA 20</li><li>RAHA 5 sloping downward</li><li>No sequence of 3 consecutive red candles</li><li>Or the special case: price completely above the Bollinger Band with a bearish candle</li></ul><p>After entry, the strategy manages positions using these rules:</p><ul><li>Stop loss set at the highest price at entry</li><li>Profit target (TP) set at entry price minus 3 times the stop loss distance</li><li>Position size calculated as 1% of capital divided by stop loss percentage</li><li>If 3 consecutive red candles appear, stop loss is adjusted to the high of the previous candle</li><li>Exit conditions include: price crossing above RAHA 10, RAHA 10 crossing above RAHA 20, or price breaking through stop loss</li></ul><h3>3. Strategy Advantages</h3><p>The RAHA Quantitative Dynamic Weight Moving Average Short-Term Trend Strategy offers several advantages:</p><ol><li><strong>Dynamic Weight Balance</strong>: The RAHA indicator creates a more sensitive yet stable moving average system by giving extreme values lower weights. This helps reduce false signals while maintaining sensitivity to genuine market changes.</li><li><strong>Multi-level Trend Confirmation</strong>: The strategy uses RAHA indicators of multiple periods (5, 10, 20, and 40) for trend confirmation, and this multi-verification mechanism helps lower the false signal rate.</li><li><strong>Risk Management Adaptation</strong>: Position size automatically adjusts based on stop loss distance, ensuring each trade controls risk at 1% of capital. This mechanism allows the strategy to adapt to different volatility environments.</li><li><strong>Dynamic Stop Loss Adjustment</strong>: The strategy adjusts stop loss based on market conditions during trading, such as raising the stop loss position when 3 consecutive red candles appear, helping to lock in profits and reduce drawdowns.</li><li><strong>Flexible Exit Mechanism</strong>: The strategy combines multiple exit mechanisms including technical indicator reversals and stop loss triggers, providing flexibility that helps optimize exit timing under different market conditions.</li><li><strong>Exceptional Situation Capture</strong>: The strategy pays special attention to sell signals above the Bollinger Band, helping to capture retracement opportunities after excessive market expansion, which often bring significant returns.</li><li><strong>Clear Visualization</strong>: The strategy marks entry and exit points on charts, allowing traders to intuitively understand trading logic, facilitating subsequent analysis and improvement.</li></ol><h3>4. Strategy Risks</h3><p>Despite its many advantages, the RAHA Quantitative Dynamic Weight Moving Average Short-Term Trend Strategy faces several risks:</p><ol><li><strong>Sudden Trend Reversal Risk</strong>: The strategy primarily relies on trend continuation and may lead to significant losses in cases of sudden trend reversals. The solution is to consider adding more sensitive reversal indicators or market sentiment indicators as supplements.</li><li><strong>Parameter Sensitivity</strong>: The sensitivity parameter in RAHA calculation (currently set at 1.5) significantly impacts strategy performance. Different markets or periods may require different parameter settings. Parameter optimization and sensitivity analysis are recommended.</li><li><strong>Consecutive Stop Loss Risk</strong>: In high-volatility or sideways markets, the strategy may trigger consecutive stop losses, causing capital curve decline. Consider adding market environment filters to pause trading under unfavorable market conditions.</li><li><strong>Calculation Complexity</strong>: RAHA indicator calculation is relatively complex and requires loop processing of data, which may cause slight delays in real-time trading. Calculation efficiency should be evaluated in high-frequency trading environments.</li><li><strong>Position Risk</strong>: Although the strategy limits risk per trade, it doesn’t consider overall position risk. Total risk may exceed expectations when multiple trades are open simultaneously. Adding overall risk control mechanisms is recommended.</li><li><strong>Bollinger Band Anomaly Entry Risk</strong>: Entries based on positions above the Bollinger Band may enter too early in extreme market conditions. Consider adding additional filtering conditions, such as volume confirmation or auxiliary judgment from other technical indicators.</li><li><strong>Fixed Multiple Take Profit Risk</strong>: The strategy uses a fixed 3x stop loss distance as profit target, which may not be flexible enough in different market environments. Consider dynamically adjusting profit targets based on market volatility or support/resistance levels.</li></ol><h3>5. Strategy Optimization Directions</h3><p>Based on in-depth analysis of the strategy, here are possible optimization directions:</p><ol><li><strong>Adaptive Sensitivity Parameter</strong>: The strategy currently uses a fixed sensitivity parameter (1.5). Consider automatically adjusting sensitivity based on market volatility, using higher values in low-volatility markets to increase sensitivity, and lower values in high-volatility markets to improve stability.</li><li><strong>Add Market Environment Filter</strong>: Introduce market environment judgment mechanisms, such as trend strength indicators (ADX) or volatility indicators (ATR), to reduce or avoid trading in market environments unsuitable for short-term strategies.</li><li><strong>Optimize Exit Mechanism</strong>: Current strategy exits mainly based on technical indicator reversals and stop losses. Consider adding more flexible partial profit-locking mechanisms, such as moving stop loss to breakeven when reaching 1:1 risk-reward ratio, or setting multiple profit targets based on support/resistance levels.</li><li><strong>Incorporate Volume Confirmation</strong>: Adding volume confirmation when entry signals generate can reduce false breakouts and signals. Volume confirmation is particularly important for special entry conditions above the Bollinger Band.</li><li><strong>Time Filter</strong>: Analyzing strategy performance during different time periods may reveal that the strategy performs better during certain sessions (such as market opening or before closing). Adding time filters can improve overall strategy efficiency.</li><li><strong>Add Fundamental Filters</strong>: For applications to stocks or certain commodities, consider adding fundamental filtering conditions, such as excluding periods before important data releases or periods affected by specific seasonal factors.</li><li><strong>Machine Learning Optimization</strong>: Use machine learning methods to optimize strategy parameter combinations or enhance entry and exit decisions through historical pattern recognition. This can be achieved through deep analysis of historical data to discover patterns that traditional technical analysis might overlook.</li><li><strong>Risk Balancing Mechanism</strong>: Add dynamic risk adjustment mechanisms based on account equity and open positions to ensure total risk doesn’t exceed preset limits, especially in cases of consecutive entries.</li></ol><h3>6. Conclusion</h3><p>The RAHA Quantitative Dynamic Weight Moving Average Short-Term Trend Strategy is an innovative quantitative trading system. Its core lies in using a unique moving average calculation method to process price data, assigning different weights to outliers, thereby creating a more sensitive yet stable moving average indicator. The strategy forms a complete trading decision system through collaborative judgment of multi-period RAHA indicators combined with auxiliary indicators like Bollinger Bands.</p><p>The strategy’s greatest advantage lies in its adaptive risk management and dynamic stop loss adjustment mechanisms, allowing it to maintain stable risk control in different market environments. Meanwhile, multi-level trend confirmation and flexible exit mechanisms also enhance the strategy’s robustness.</p><p>However, the strategy also faces challenges such as parameter sensitivity, trend reversal risk, and consecutive stop loss risk. Performance can be further improved through introducing adaptive parameters, market environment filters, optimizing exit mechanisms, and adding volume confirmation.</p><p>Overall, the RAHA Quantitative Dynamic Weight Moving Average Short-Term Trend Strategy demonstrates the potential of combining innovative technical indicators with traditional trading concepts. Through continuous optimization and adaptation to different market environments, this strategy has the potential to become a powerful tool for short-term traders, helping them achieve more stable returns in the market.</p><p><strong>Strategy source code</strong></p><pre>/*backtest<br>start: 2015-02-22 00:00:00<br>end: 2025-07-02 10:18:36<br>period: 1d<br>basePeriod: 1d<br>*/<br><br>//@version=5<br>strategy(&quot;RAHA Strategy - Short&quot;, overlay=true, default_qty_type=strategy.fixed, default_qty_value=0)<br><br>// === RAHA Weighted Average Function ===<br>raha_weighted(src, len, sensitivity) =&gt;<br>    mean = ta.sma(src, len)<br>    dev = ta.stdev(src, len)<br>    sumWeighted = 0.0<br>    sumWeights = 0.0<br>    for i = 0 to len - 1<br>        val = nz(src[i])<br>        weight = 1 / (1 + sensitivity * math.abs(val - mean) / dev)<br>        sumWeighted += val * weight<br>        sumWeights += weight<br>    sumWeights &gt; 0 ? sumWeighted / sumWeights : na<br><br>// === RAHA Calculations ===<br>sensitivity = 1.5<br>raha5 = raha_weighted(close, 5, sensitivity)<br>raha10 = raha_weighted(close, 10, sensitivity)<br>raha20 = raha_weighted(close, 20, sensitivity)<br>raha40 = raha_weighted(close, 40, sensitivity)<br><br>// === Upper Bollinger Band on RAHA 20 ===<br>bbDev = ta.stdev(raha20, 20)<br>bbUpper = raha20 + 2.0 * bbDev<br><br>// === Short Entry Conditions ===<br>raha40SlopeDown = raha40 &lt; raha40[1]<br>crossoverDownRAHA = ta.crossunder(raha10, raha20) or raha10 &lt; raha20<br>raha5SlopeDown = raha5 &lt; raha5[1]<br>threeRedBars = close &lt; open and close[1] &lt; open[1] and close[2] &lt; open[2]<br>bearishOutsideBollinger = high &gt; bbUpper and low &gt; bbUpper and close &lt; open<br><br>// === Position Management Variables ===<br>var float entryHigh = na<br>var float entryPrice = na<br>var float stop = na<br>var float tp = na<br>var int redCount = 0<br>var int lastEntryBar = na<br><br>// === Enter Only When No Open Trade ===<br>canEnter = strategy.position_size == 0 and ((raha40SlopeDown and crossoverDownRAHA and raha5SlopeDown) or bearishOutsideBollinger)<br>canEnterFiltered = canEnter and (na(lastEntryBar) or strategy.opentrades == 0 or bar_index &gt; lastEntryBar)<br><br>// === Enter Position ===<br>if canEnterFiltered<br>    entryHigh := high<br>    entryPrice := close<br>    stop := entryHigh<br>    if stop &gt; entryPrice<br>        tp := entryPrice - 3 * (stop - entryPrice)<br>        capital = strategy.equity<br>        stopPct = math.max(0.0001, (stop - entryPrice) / entryPrice)<br>        positionValue = 0.01 * capital / stopPct<br>        qty = positionValue / entryPrice<br>        if qty &gt; 0 and qty &lt; 1e12<br>            strategy.entry(&quot;RAHA Short&quot;, strategy.short, qty=qty)<br>            redCount := 0<br>            lastEntryBar := bar_index<br><br>// === Manage Open Position ===<br>if strategy.position_size &lt; 0<br>    redCount := close &lt; open ? redCount + 1 : 0<br>    if redCount &gt;= 3<br>        stop := high[1]<br>        redCount := 0<br><br>// === Exit Conditions ===<br>exit1 = close &gt; raha10 and open &lt; raha10<br>exit2 = ta.crossover(raha10, raha20)<br>exit3 = close &gt; stop<br><br>if low &lt;= tp and (exit1 or exit2)<br>    strategy.close(&quot;RAHA Short&quot;)<br><br>if exit3<br>    strategy.close(&quot;RAHA Short&quot;)<br><br>// === Plot Entry and Exit Arrows ===<br>inPosition = strategy.position_size &lt; 0<br>exitCondition = inPosition and ((low &lt;= tp and (exit1 or exit2)) or exit3)<br><br>plotshape(canEnterFiltered, title=&quot;Short Entry&quot;, location=location.abovebar, style=shape.labeldown, text=&quot;Short&quot;, color=color.red, textcolor=color.white)<br>plotshape(exitCondition, title=&quot;Close Position&quot;, location=location.belowbar, style=shape.labelup, text=&quot;Close&quot;, color=color.green, textcolor=color.white)</pre><p>The original address: <a href="https://www.fmz.com/strategy/500320">RAHA Quantitative Dynamic Weight Moving Average Short-Term Trend Strategy</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=7cf826619c83" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[OBV Oscillator Crossover Strategy with No Same-Bar Exit Mechanism]]></title>
            <link>https://medium.com/@FMZQuant/obv-oscillator-crossover-strategy-with-no-same-bar-exit-mechanism-8fee84a406fc?source=rss-b78414ad1c60------2</link>
            <guid isPermaLink="false">https://medium.com/p/8fee84a406fc</guid>
            <category><![CDATA[oscillator]]></category>
            <category><![CDATA[fmz-quant]]></category>
            <category><![CDATA[trading-strategy]]></category>
            <category><![CDATA[cryptocurrency]]></category>
            <category><![CDATA[crossover]]></category>
            <dc:creator><![CDATA[FMZQuant]]></dc:creator>
            <pubDate>Fri, 25 Jul 2025 03:15:56 GMT</pubDate>
            <atom:updated>2025-07-25T03:15:56.624Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*wBJ6RahgxZI50oiA.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*1NxUxsNlpunUKZB7.png" /></figure><h3>Overview</h3><p>The OBV Oscillator Crossover Strategy with No Same-Bar Exit Mechanism is a quantitative trading system based on the On Balance Volume (OBV) indicator. This strategy monitors the difference between the OBV indicator and its EMA to capture key moments of market momentum shifts. The core of the strategy lies in identifying crossover signals between the OBV oscillator and the zero line, while implementing a mechanism to prevent same-bar exits, avoiding premature exits caused by rapid price fluctuations and effectively improving trade execution quality. The strategy also integrates comprehensive risk management mechanisms, including fixed percentage stop-loss, target profit, and trailing stops, enabling effective risk control while maintaining profit potential.</p><h4>Strategy Principles</h4><p>This strategy generates trading signals based on the oscillator formed by the difference between the On Balance Volume (OBV) indicator and its Exponential Moving Average (EMA). The core calculation process is as follows:</p><ol><li>First, calculate the standard OBV indicator: when price rises, add the day’s volume to the cumulative value; when price falls, subtract the day’s volume from the cumulative value; when price remains unchanged, the cumulative value stays the same.</li><li>Calculate the Exponential Moving Average (EMA) of OBV, with a default period of 20.</li><li>Calculate the OBV Oscillator, which is the difference between OBV and its EMA (obv_osc = obv — obv_ema).</li><li>Generate trading signals:</li></ol><ul><li>Long signal: when the OBV oscillator crosses above the zero line from below and there is currently no position</li><li>Short signal: when the OBV oscillator crosses below the zero line from above and there is currently no position</li></ul><p>A key innovation of the strategy is the implementation of a “No Same-Bar Exit Mechanism,” which records the bar index of entry and ensures that exits are only allowed after subsequent new bars are formed. This mechanism effectively prevents premature triggering of stop-loss or take-profit due to rapid price fluctuations within the same time unit, improving the strategy’s stability.</p><p>In terms of risk management, the strategy sets up a triple protection mechanism:</p><ul><li>Fixed percentage stop-loss (default 1%)</li><li>Target profit take-profit (default 2%)</li><li>Trailing stop (default 0.5%), which provides dynamic protection of profits</li></ul><h4>Strategy Advantages</h4><ol><li><strong>Precise Momentum Capture</strong>: By identifying crossovers between the OBV oscillator and the zero line, the strategy can detect inflection points in market momentum, allowing entry during the early stages of trends and capturing most of the trend movements.</li><li><strong>Volume Confirmation</strong>: The OBV indicator itself integrates price changes and volume information, providing volume confirmation for trading signals and reducing the risk of false breakouts.</li><li><strong>No Same-Bar Exit Protection</strong>: The mechanism that records entry bar indices and prohibits same-bar exits effectively avoids premature stops caused by short-term fluctuations, improving trading stability and completion rates.</li><li><strong>Comprehensive Risk Management System</strong>: The strategy integrates triple protection mechanisms of fixed stop-loss, target profit, and trailing stops, effectively controlling risk exposure while securing profits.</li><li><strong>High Adaptability</strong>: Through parameterized design (OBV EMA period, stop-loss percentage, target profit percentage, trailing stop percentage), the strategy can be flexibly adjusted according to different market environments and trading instruments.</li><li><strong>Automated Execution and Alerts</strong>: The strategy has built-in JSON format alert strings, which can seamlessly connect to automated trading systems for fully automated trading.</li><li><strong>Visualization Aids</strong>: The strategy plots the OBV oscillator and trade labels on the chart, providing intuitive visual feedback for strategy backtesting and real-time monitoring.</li></ol><h4>Strategy Risks</h4><ol><li><strong>Overtrading in Ranging Markets</strong>: In sideways markets, the OBV oscillator may frequently cross the zero line, resulting in excessive trading signals and unnecessary transaction costs. The solution is to add additional filtering conditions, such as only enabling the strategy in clear trend environments or adding signal confirmation mechanisms.</li><li><strong>Parameter Sensitivity</strong>: The period setting of OBV EMA has a significant impact on strategy performance, and different market environments may require different parameter settings. It is recommended to find optimal parameter combinations for specific market environments through backtest optimization.</li><li><strong>Slippage and Execution Risk</strong>: The strategy uses market orders to execute trades, which may face significant slippage in markets with insufficient liquidity. The solution is to consider using limit orders or trading during periods of sufficient liquidity.</li><li><strong>Balance of Stop-Loss Settings</strong>: Fixed percentage stop-losses may be too tight in high-volatility markets or too loose in low-volatility markets. It is recommended to dynamically adjust the stop-loss percentage based on the historical volatility of the underlying asset.</li><li><strong>Signal Dependency</strong>: The strategy relies entirely on crossover signals from the OBV oscillator, which may lag in certain market conditions. Consider adding other technical indicators as confirmation to improve signal quality.</li><li><strong>Disregard for Fundamental Factors</strong>: As a pure technical analysis strategy, it does not consider fundamental factors that may affect the market, such as economic data or policy changes. Consider reducing positions or pausing the strategy before major fundamental events.</li></ol><h4>Strategy Optimization Directions</h4><ol><li><strong>Add Trend Filters</strong>: Introduce ADX or other trend strength indicators to execute trades only in confirmed trend environments, avoiding frequent trading in oscillating markets. This can significantly improve the strategy’s win rate and risk-reward ratio.</li><li><strong>Dynamic Parameter Adjustment</strong>: Automatically adjust OBV EMA periods, stop-loss, and target profit percentages based on market volatility. For example, use longer EMA periods and wider stop-loss ranges in high-volatility environments, and opposite settings in low-volatility environments.</li><li><strong>Multi-Timeframe Confirmation</strong>: Add analysis of higher timeframes and execute trades only when signals across multiple timeframes are consistent, improving signal quality and reliability.</li><li><strong>Volume Quality Filtering</strong>: Add quality assessment of volume, for example, confirming signals only when volume is higher than the N-day average volume, avoiding false breakouts in low-volume environments.</li><li><strong>Optimize Entry Timing</strong>: After the OBV oscillator crosses the zero line, wait for price pullbacks to key support/resistance levels before entering, improving entry price advantage.</li><li><strong>Incorporate Machine Learning Algorithms</strong>: Use machine learning techniques to automatically identify optimal trading parameters for the OBV oscillator in different market environments, achieving adaptive optimization of the strategy.</li><li><strong>Add Time Filters</strong>: Avoid trading during high-volatility periods at market open and close, or pause the strategy before and after important economic data releases to reduce unpredictable risks.</li></ol><h4>Conclusion</h4><p>The OBV Oscillator Crossover Strategy is a quantitative trading system that combines classic technical analysis indicators with modern risk management techniques. By capturing crossover signals between the OBV oscillator and the zero line, while implementing a no same-bar exit protection mechanism, the strategy can identify changes in market momentum while effectively controlling trading risks.</p><p>The core advantage of the strategy lies in incorporating volume factors into the trading decision process, ensuring signals are effectively confirmed by volume, while improving trade execution quality through the no same-bar exit mechanism. The comprehensive risk management system and parameterized design give the strategy high adaptability and stability.</p><p>Although there are potential risks such as overtrading in ranging markets and parameter sensitivity, there is still significant room for performance improvement through optimization directions such as adding trend filters, dynamic parameter adjustment, and multi-timeframe confirmation. Particularly, introducing machine learning techniques for adaptive parameter optimization is expected to further improve the strategy’s performance in different market environments.</p><p>Overall, the OBV Oscillator Crossover Strategy provides an effective framework for quantitative trading based on volume analysis. With reasonable parameter settings and continuous optimization, it has the potential to achieve stable risk-adjusted returns in various market environments.</p><p><strong>Strategy source code</strong></p><pre>/*backtest<br>start: 2024-07-04 00:00:00<br>end: 2025-07-02 08:00:00<br>period: 4h<br>basePeriod: 4h<br>exchanges: [{&quot;eid&quot;:&quot;Futures_Binance&quot;,&quot;currency&quot;:&quot;ETH_USDT&quot;}]<br>*/<br><br>//@version=5<br>strategy(&quot;OBV Osc (No Same-Bar Exit)&quot;, overlay=true, default_qty_type=strategy.percent_of_equity, default_qty_value=100)<br><br>// === JSON ALERT STRINGS ===<br>callBuyJSON  = &#39;ANSHUL \n[{&quot;TT&quot;:&quot;BUY&quot;,&quot;E&quot;:&quot;NFO&quot;,&quot;TS&quot;:&quot;NIFTY2570326200CE&quot;,&quot;Q&quot;:&quot;75&quot;,&quot;OT&quot;:&quot;MARKET&quot;,&quot;P&quot;:&quot;NRML&quot;,&quot;VL&quot;:&quot;DAY&quot;,&quot;AT&quot;:&quot;DHANHQ&quot;}]&#39;<br>callExtJSON  = &#39;ANSHUL \n[{&quot;TT&quot;:&quot;SELL&quot;,&quot;E&quot;:&quot;NFO&quot;,&quot;TS&quot;:&quot;NIFTY2570326200CE&quot;,&quot;Q&quot;:&quot;75&quot;,&quot;OT&quot;:&quot;MARKET&quot;,&quot;P&quot;:&quot;NRML&quot;,&quot;VL&quot;:&quot;DAY&quot;,&quot;AT&quot;:&quot;DHANHQ&quot;}]&#39;<br>putBuyJSON   = &#39;ANSHUL \n[{&quot;TT&quot;:&quot;BUY&quot;,&quot;E&quot;:&quot;NFO&quot;,&quot;TS&quot;:&quot;NIFTY2570325000PE&quot;,&quot;Q&quot;:&quot;75&quot;,&quot;OT&quot;:&quot;MARKET&quot;,&quot;P&quot;:&quot;NRML&quot;,&quot;VL&quot;:&quot;DAY&quot;,&quot;AT&quot;:&quot;DHANHQ&quot;}]&#39;<br>putExtJSON   = &#39;ANSHUL \n[{&quot;TT&quot;:&quot;SELL&quot;,&quot;E&quot;:&quot;NFO&quot;,&quot;TS&quot;:&quot;NIFTY2570325000PE&quot;,&quot;Q&quot;:&quot;75&quot;,&quot;OT&quot;:&quot;MARKET&quot;,&quot;P&quot;:&quot;NRML&quot;,&quot;VL&quot;:&quot;DAY&quot;,&quot;AT&quot;:&quot;DHANHQ&quot;}]&#39;<br><br>// === INPUTS ===<br>length     = input.int(20, title=&quot;OBV EMA Length&quot;)<br>sl_pct     = input.float(1.0, title=&quot;Stop Loss %&quot;, minval=0.1)<br>tp_pct     = input.float(2.0, title=&quot;Take Profit %&quot;, minval=0.1)<br>trail_pct  = input.float(0.5, title=&quot;Trailing Stop %&quot;, minval=0.1)<br><br>// === OBV OSCILLATOR CALC ===<br>src = close<br>obv = ta.cum(ta.change(src) &gt; 0 ? volume : ta.change(src) &lt; 0 ? -volume : 0)<br>obv_ema = ta.ema(obv, length)<br>obv_osc = obv - obv_ema<br><br>// === SIGNALS ===<br>longCondition  = ta.crossover(obv_osc, 0) and strategy.position_size == 0<br>shortCondition = ta.crossunder(obv_osc, 0) and strategy.position_size == 0<br><br>// === RISK SETTINGS ===<br>longStop     = close * (1 - sl_pct / 100)<br>longTarget   = close * (1 + tp_pct / 100)<br>shortStop    = close * (1 + sl_pct / 100)<br>shortTarget  = close * (1 - tp_pct / 100)<br>trailPoints  = close * trail_pct / 100<br><br>// === ENTRY BAR TRACKING TO PREVENT SAME-BAR EXIT ===<br>var int entryBar = na<br><br>// === STRATEGY ENTRY ===<br>if longCondition<br>    strategy.entry(&quot;Long&quot;, strategy.long)<br>    entryBar := bar_index<br>    alert(callBuyJSON, alert.freq_all)<br>    label.new(bar_index, low, text=&quot;BUY CALL&quot;, style=label.style_label_up, color=color.new(color.green, 85), textcolor=color.black)<br><br>if shortCondition<br>    strategy.entry(&quot;Short&quot;, strategy.short)<br>    entryBar := bar_index<br>    alert(putBuyJSON, alert.freq_all)<br>    label.new(bar_index, high, text=&quot;BUY PUT&quot;, style=label.style_label_down, color=color.new(color.red, 85), textcolor=color.black)<br><br>// === EXIT ONLY IF BAR_INDEX &gt; entryBar (NO SAME-BAR EXIT) ===<br>canExitLong  = strategy.position_size &gt; 0  and bar_index &gt; entryBar<br>canExitShort = strategy.position_size &lt; 0  and bar_index &gt; entryBar<br><br>if canExitLong<br>    strategy.exit(&quot;Exit Long&quot;, from_entry=&quot;Long&quot;, stop=longStop, limit=longTarget, trail_points=trailPoints, trail_offset=trailPoints)<br><br>if canExitShort<br>    strategy.exit(&quot;Exit Short&quot;, from_entry=&quot;Short&quot;, stop=shortStop, limit=shortTarget, trail_points=trailPoints, trail_offset=trailPoints)<br><br>// === TRACK ENTRY/EXIT FOR ALERTS ===<br>posNow  = strategy.position_size<br>posPrev = nz(strategy.position_size[1])<br><br>longExit  = posPrev == 1  and posNow == 0<br>shortExit = posPrev == -1 and posNow == 0<br><br>if longExit<br>    alert(callExtJSON, alert.freq_all)<br>    label.new(bar_index, high, text=&quot;EXIT CALL&quot;, style=label.style_label_down, color=color.new(color.blue, 85), textcolor=color.black)<br><br>if shortExit<br>    alert(putExtJSON, alert.freq_all)<br>    label.new(bar_index, low, text=&quot;EXIT PUT&quot;, style=label.style_label_up, color=color.new(color.orange, 85), textcolor=color.black)<br><br>// === PLOTS ===<br>plot(obv_osc, title=&quot;OBV Oscillator&quot;, color=obv_osc &gt; 0 ? color.green : color.red, linewidth=2)<br>hline(0, color=color.gray)</pre><p><strong>Strategy parameters</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*dGEo0X6Lic_-V3l-SXfyfQ.png" /></figure><p>The original address: <a href="https://www.fmz.com/strategy/500477">OBV Oscillator Crossover Strategy with No Same-Bar Exit Mechanism</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=8fee84a406fc" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Multi-Timeframe Liquidity Trap Reversal Quantitative Strategy]]></title>
            <link>https://medium.com/@FMZQuant/multi-timeframe-liquidity-trap-reversal-quantitative-strategy-ccff0d0a7531?source=rss-b78414ad1c60------2</link>
            <guid isPermaLink="false">https://medium.com/p/ccff0d0a7531</guid>
            <category><![CDATA[fmz-quant]]></category>
            <category><![CDATA[reversal]]></category>
            <category><![CDATA[trading-strategy]]></category>
            <category><![CDATA[multi-time-frame]]></category>
            <category><![CDATA[liquidity]]></category>
            <dc:creator><![CDATA[FMZQuant]]></dc:creator>
            <pubDate>Fri, 25 Jul 2025 02:17:52 GMT</pubDate>
            <atom:updated>2025-07-25T02:17:52.918Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*uJk_QoKjdNcLE0bk.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*v-78p6uSkYP_Pn6Y.png" /></figure><h4>Overview</h4><p>The Multi-Timeframe Liquidity Trap Reversal Quantitative Strategy is a lightweight, precision-focused tool designed to identify institutional and market maker liquidity manipulation tactics. This strategy leverages price action analysis to detect key liquidity sweeps and subsequent reversals, effectively capturing market turning points. The core concept revolves around identifying sweeps of prior swing highs/lows and confirming trap reversals when price closes back inside the swept range — a signature move of smart money designed to trap retail breakout traders. The strategy doesn’t rely on complex indicators but instead directly analyzes raw price action and market intent, making it particularly suitable for disciplined traders seeking to trade around liquidity events.</p><h4>Strategy Principles</h4><p>This strategy is built on market structure and liquidity principles, relying on several key components:</p><ol><li><strong>Liquidity Sweep Detection</strong>: Utilizes a custom lookback period (swingLookback = 10) to determine previous price highs and lows. The strategy calculates the highest high (prevHigh) and lowest low (prevLow) over the past 10 periods, then identifies liquidity sweep events (sweepHigh and sweepLow) by comparing current price action against these levels.</li><li><strong>Trap Confirmation Mechanism</strong>: When price retraces back into the previous range after breaking out, the strategy considers this a market maker trap. Specifically, for a short trap (trapShort), price must first break above the previous high and then close below it; for a long trap (trapLong), price must first break below the previous low and then close above it.</li><li><strong>Session Filtering</strong>: The strategy offers a New York session filter option (useSessionFilter), enabled by default. The session is defined as UTC hours 13 to 20, which typically covers the most liquid market periods, helping to avoid false signals during low liquidity times.</li><li><strong>Trade Execution Logic</strong>: When long conditions (longCondition) are met, the strategy enters a long position; when short conditions (shortCondition) are met, it enters a short position. All trades use 5% of account equity as position size.</li></ol><p>The core philosophy is to mirror market maker operational logic, avoid false breakouts, and establish trades with real conviction around liquidity events. By identifying when price breaks key levels and quickly retraces, the strategy can capture market reversals, particularly targeting price movements that are often misinterpreted by retail traders as trend confirmations.</p><h4>Strategy Advantages</h4><ol><li><strong>Simplicity and Clarity</strong>: The strategy doesn’t rely on complex technical indicators but is directly based on price action and market structure, making it easy to understand and implement. This simplicity reduces the risk of overfitting and enhances strategy robustness.</li><li><strong>Institution-Based Approach</strong>: The strategy mimics the operational logic of institutions and market makers, focusing on liquidity traps — a proven market pattern. By understanding and identifying the behavior of large market participants, retail investors can avoid becoming victims of these traps.</li><li><strong>Precise Trading Conditions</strong>: The strategy provides clear entry conditions, reducing the need for subjective judgment. Price must first break key levels and then retrace, a double confirmation mechanism that significantly reduces false signals.</li><li><strong>Session Optimization</strong>: Through New York session filtering, the strategy focuses on trading during the most active and liquid market periods, improving signal quality and execution efficiency.</li><li><strong>Position Management Integration</strong>: The strategy defaults to using a fixed percentage (5%) of account equity as position size, incorporating a basic risk management mechanism that prevents excessive leverage-induced losses.</li><li><strong>Adaptability</strong>: Through adjustable parameters such as swing lookback period (swingLookback) and trap confirmation period (retestBars), the strategy can adapt to different market conditions and trading instruments.</li><li><strong>Visualization Support</strong>: The strategy includes clear graphical indications, plotting key price levels and trade signals, helping traders better understand market dynamics and strategy logic.</li></ol><h4>Strategy Risks</h4><ol><li><strong>False Breakout Risk</strong>: While the strategy is designed to identify false breakouts, the market may experience genuine breakouts after multiple false ones, in which case the strategy might incorrectly enter counter positions. The solution is to incorporate additional confirmation indicators or implement stricter confirmation conditions.</li><li><strong>Parameter Sensitivity</strong>: Strategy performance heavily depends on parameter settings such as swingLookback and retestBars. Inappropriate parameters may result in excessive trading signals or missed opportunities. It&#39;s recommended to optimize these parameters through backtesting under different market conditions.</li><li><strong>Market Environment Dependency</strong>: In strong trending markets, liquidity traps may be less frequent or effective. This strategy performs best in ranging or transitional markets and may underperform in one-directional trending markets. Consider adding trend filters to avoid counter-trend trading in strong trends.</li><li><strong>Timeframe Limitation</strong>: The strategy, in its current implementation, applies to a single timeframe and may miss important liquidity levels from larger timeframes. Integrating multi-timeframe analysis can enhance strategy robustness.</li><li><strong>Stop Loss Absence</strong>: The current strategy lacks explicit stop loss mechanisms, which could lead to excessive losses on incorrect signals. Appropriate stop loss and take profit logic should be added to protect capital.</li><li><strong>Execution Slippage</strong>: In highly volatile markets, actual execution prices may differ significantly from expected prices at signal triggering. Slippage factors should be considered in live trading and strategy adjustments made accordingly.</li></ol><h4>Strategy Optimization Directions</h4><ol><li><strong>Multi-Timeframe Integration</strong>: The strategy can be enhanced by analyzing liquidity levels across multiple timeframes, ensuring trades align with larger market structure. For example, adding checks for the dominant trend in larger timeframes and only accepting trap signals in the trend direction.</li><li><strong>Volume Confirmation</strong>: Adding volume analysis can significantly improve strategy quality. Liquidity sweeps are often accompanied by sudden volume increases, while genuine reversals typically have sustained volume support. Adding volume filters can reduce false signals.</li><li><strong>Dynamic Parameter Adjustment</strong>: Implement adaptive parameter mechanisms that automatically adjust swingLookback and other key parameters based on market volatility. Longer lookback periods may be needed in high-volatility markets, while shorter ones work better in low-volatility environments.</li><li><strong>Stop Loss/Take Profit Mechanisms</strong>: Add intelligent stop loss strategies, such as setting stops beyond sweep highs/lows, or using ATR (Average True Range) to dynamically determine stop levels. Similarly, implement structure-based take profit targets, such as the next significant support/resistance level.</li><li><strong>Market State Filtering</strong>: Develop a market state classifier to distinguish between trending, ranging, and transitional market environments, and adjust strategy parameters or pause trading based on the current market state. This can be achieved by adding trend indicators like moving averages or ADX.</li><li><strong>Signal Quality Scoring</strong>: Implement a signal quality scoring system considering factors such as price retracement degree, candle pattern strength, and price momentum. Execute trades only on high-quality signals or adjust position sizing based on signal quality.</li><li><strong>Correlated Asset Synergy</strong>: Look for confirmation signals across correlated assets. For example, in forex trading, correlations between currency pairs can provide additional layers of confirmation, enhancing strategy reliability.</li></ol><h4>Conclusion</h4><p>The Multi-Timeframe Liquidity Trap Reversal Quantitative Strategy offers a concise yet powerful approach to identifying institutional market maker liquidity manipulation behaviors and profiting from them. By focusing on price patterns that break key support/resistance levels and then retrace, the strategy can capture significant market reversals. Its core strength lies in being directly based on raw price action and market structure without complex indicators, while improving trading quality through session filtering.</p><p>However, the strategy also faces challenges such as false breakout risks, parameter sensitivity, and lack of comprehensive risk management. By integrating multi-timeframe analysis, adding volume confirmation, implementing dynamic parameter adjustment, and establishing robust stop loss/take profit mechanisms, strategy performance and robustness can be significantly enhanced.</p><p>Ultimately, this strategy represents an effective approach to understanding market microstructure, offering traders a framework to align with “smart money” in the market by understanding and identifying the intentions of large market participants. With the suggested optimizations implemented, the strategy has the potential to become a powerful weapon in a trader’s toolkit, especially for those focusing on market structure and liquidity events.</p><p><strong>Strategy source code</strong></p><pre>/*backtest<br>start: 2025-06-03 00:00:00<br>end: 2025-07-03 00:00:00<br>period: 5m<br>basePeriod: 5m<br>exchanges: [{&quot;eid&quot;:&quot;Futures_Binance&quot;,&quot;currency&quot;:&quot;ETH_USDT&quot;}]<br>*/<br><br>//@version=5<br>strategy(&quot;Market Maker Trap Reversal V1&quot;, overlay=true, default_qty_type=strategy.percent_of_equity, default_qty_value=5)<br><br>// === INPUTS === //<br>swingLookback = input.int(10, &quot;Swing High/Low Lookback&quot;)<br>retestBars = input.int(5, &quot;Bars to Confirm Trap After Sweep&quot;)<br>sessionStart = input.int(13, &quot;Session Start Hour (UTC)&quot;)<br>sessionEnd = input.int(20, &quot;Session End Hour (UTC)&quot;)<br>useSessionFilter = input.bool(true, &quot;Use NY Session Only&quot;)<br><br>// === SESSION LOGIC === //<br>inSession = (hour &gt;= sessionStart and hour &lt; sessionEnd)<br><br>// === SWEEP LOGIC === //<br>prevHigh = ta.highest(high[1], swingLookback)<br>prevLow = ta.lowest(low[1], swingLookback)<br><br>sweepHigh = high &gt; prevHigh<br>sweepLow = low &lt; prevLow<br><br>// === TRAP CONFIRMATION === //<br>// After sweep, price must close back inside the range (fakeout)<br>trapShort = sweepHigh and close &lt; prevHigh<br>trapLong = sweepLow and close &gt; prevLow<br><br>// === TRIGGER LOGIC === //<br>longCondition = trapLong and (not useSessionFilter or inSession)<br>shortCondition = trapShort and (not useSessionFilter or inSession)<br><br>// === EXECUTE TRADES === //<br>if longCondition<br>    strategy.entry(&quot;Trap Long&quot;, strategy.long)<br><br>if shortCondition<br>    strategy.entry(&quot;Trap Short&quot;, strategy.short)<br><br>// === PLOT ZONES === //<br>plotshape(trapLong, title=&quot;Trap Long&quot;, location=location.belowbar, style=shape.triangleup, color=color.green, size=size.small)<br>plotshape(trapShort, title=&quot;Trap Short&quot;, location=location.abovebar, style=shape.triangledown, color=color.red, size=size.small)<br><br>plot(prevHigh, &quot;Swing High&quot;, color=color.red, linewidth=1, style=plot.style_linebr)<br>plot(prevLow, &quot;Swing Low&quot;, color=color.green, linewidth=1, style=plot.style_linebr)</pre><p><strong>Strategy parameters</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*RgP5xTWQvFD_ceLgUbfjtA.png" /></figure><p>The original address: <a href="https://www.fmz.com/strategy/500480">Multi-Timeframe Liquidity Trap Reversal Quantitative Strategy</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=ccff0d0a7531" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[VWAP-Enhanced Bollinger Bands Momentum Reversal Strategy]]></title>
            <link>https://medium.com/@FMZQuant/vwap-enhanced-bollinger-bands-momentum-reversal-strategy-570b86982021?source=rss-b78414ad1c60------2</link>
            <guid isPermaLink="false">https://medium.com/p/570b86982021</guid>
            <category><![CDATA[fmz-quant]]></category>
            <category><![CDATA[reversal]]></category>
            <category><![CDATA[trading-strategy]]></category>
            <category><![CDATA[momentum]]></category>
            <category><![CDATA[bollinger-bands]]></category>
            <dc:creator><![CDATA[FMZQuant]]></dc:creator>
            <pubDate>Fri, 25 Jul 2025 01:02:12 GMT</pubDate>
            <atom:updated>2025-07-25T01:02:12.178Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*df4kSxsPP5kw4_zq.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*oQStnVIpBW5F1xG0.png" /></figure><h3>Overview</h3><p>The VWAP-Enhanced Bollinger Bands Momentum Reversal Strategy is a quantitative trading system designed specifically for short-term cryptocurrency trading, primarily applied to 1-hour to 4-hour timeframes. This strategy cleverly combines three major technical indicators: Relative Strength Index (RSI), Bollinger Bands (BB), and Volume Weighted Average Price (VWAP) to form a comprehensive trading signal system. The core of the strategy is to capture potential reversal points during market overbought and oversold conditions, using VWAP as a trend confirmation tool, while incorporating precise risk control mechanisms to achieve efficient short-term trading.</p><h3>Strategy Principles</h3><p>The trading logic of this strategy is based on a multi-indicator confirmation mechanism, with specific principles as follows:</p><ol><li><strong>Buy Signal Conditions</strong>:</li></ol><ul><li>Price crosses above the lower Bollinger Band (ta.crossover(close, bb_lower)) or RSI below 25 (oversold level)</li><li>Current closing price is above VWAP, confirming effective uptrend</li></ul><p><strong>2. Sell Signal Conditions</strong>:</p><ul><li>Price crosses above the upper Bollinger Band (ta.crossover(close, bb_upper)) or RSI above 75 (overbought level)</li><li>Current closing price is below VWAP, confirming effective downtrend</li></ul><p><strong>3. Position Management</strong>:</p><ul><li>Risk control for each trade is limited to 1% of total account funds</li><li>Position size is dynamically calculated based on the preset 1.5% stop-loss rate</li></ul><p><strong>4. Money Management</strong>:</p><ul><li>Stop-loss is set at 1.5% of the entry price</li><li>Take-profit target is set at 2.25% of the entry price (1.5 times the stop-loss), maintaining a favorable risk-reward ratio</li></ul><p>The strategy uses precise parameter settings internally: RSI period of 14, Bollinger Bands period of 20, standard deviation multiplier of 2.0, overbought threshold of 75, and oversold threshold of 25. This parameter combination ensures that the strategy can capture important turning points in short-term price fluctuations.</p><h3>Strategy Advantages</h3><ol><li><strong>Multiple Confirmation Mechanism</strong>: The strategy combines RSI, Bollinger Bands, and VWAP indicators to form a multiple confirmation mechanism, effectively reducing false signals and improving trading success rates. When multiple indicators point to the same trading direction simultaneously, the reliability of the signal is significantly enhanced.</li><li><strong>Flexible Market Adaptability</strong>: Through adjustable parameter settings (such as RSI overbought/oversold levels, Bollinger Bands length and multiplier), the strategy can adapt to different market environments and volatility characteristics, making it perform well across different cryptocurrencies and timeframes.</li><li><strong>Strict Risk Control</strong>: Each trade risk is limited to 1% of the total account funds, coupled with a precise 1.5% stop-loss setting, effectively controlling the maximum loss per trade and protecting trading capital.</li><li><strong>Optimized Risk-Reward Ratio</strong>: The strategy sets the take-profit target at 1.5 times the stop-loss (2.25%), ensuring a positive risk-reward ratio and increasing the probability of long-term profitability.</li><li><strong>Quantified Position Management</strong>: The dynamic position calculation method based on risk percentage ensures that risk exposure remains consistent regardless of account size, achieving effective fund management.</li><li><strong>Trend Confirmation Mechanism</strong>: Using VWAP as a trend confirmation tool helps avoid entering positions against the main trend, reducing the risk of counter-trend trading.</li></ol><h3>Strategy Risks</h3><ol><li><strong>Short-term Volatility Risk</strong>: As an active short-term trading strategy, it may trigger frequent trades in highly volatile markets, increasing transaction costs and potentially facing more false breakout signals. Consider adding additional filtering conditions or extending confirmation time.</li><li><strong>Parameter Sensitivity</strong>: Strategy performance is highly dependent on the parameter settings of RSI, Bollinger Bands, and VWAP. Inappropriate parameters may lead to overtrading or missing important signals. It is recommended to optimize parameter settings for different market environments through historical backtesting.</li><li><strong>Market Sudden Change Risk</strong>: During major news events or black swan events, cryptocurrency markets may experience gaps or extreme volatility, and fixed stop-losses may not execute effectively, resulting in actual losses exceeding expectations. Consider implementing dynamic stop-losses or market volatility filters.</li><li><strong>Liquidity Risk</strong>: When trading small-cap cryptocurrencies or during low liquidity periods, slippage issues may arise, affecting actual execution prices. It is recommended to prioritize testing and applying this strategy on mainstream cryptocurrencies with high liquidity (such as BTC/ETH).</li><li><strong>Technical Indicator Lag</strong>: Both RSI and Bollinger Bands have certain lag, which may cause signal delays in rapidly changing markets. Consider introducing more sensitive indicators or reducing calculation periods to improve response speed.</li></ol><h3>Strategy Optimization Directions</h3><ol><li><strong>Add Market Environment Filters</strong>: Introduce trend strength indicators (such as ADX) or volatility indicators (such as ATR) to dynamically adjust strategy parameters or selectively execute trading signals in different market environments. This will help the strategy better adapt to the different characteristics of ranging and trending markets.</li><li><strong>Optimize Indicator Parameters</strong>: Based on historical data from different timeframes and different cryptocurrencies, optimize RSI periods and Bollinger Bands parameters to find the best parameter combinations for various market environments. Consider implementing an adaptive parameter adjustment mechanism.</li><li><strong>Enhanced Stop-Loss Mechanism</strong>: Implement trailing stop-loss functionality to protect realized profits in profitable trades while allowing trends to continue developing. Dynamic stop-loss levels can be designed based on ATR or volatility percentages.</li><li><strong>Integrate Volume Analysis</strong>: Add volume confirmation conditions to ensure sufficient market participation when signals occur, reducing low-quality signals. Volume expansion, especially when breaking through Bollinger Band boundaries, can increase signal reliability.</li><li><strong>Add Time Filters</strong>: Analyze market performance during different time periods, avoid unfavorable trading sessions with low activity or high volatility, and focus on time windows where the strategy has historically performed best.</li><li><strong>Develop Signal Quality Scoring System</strong>: Score the quality of each signal based on multiple factors (such as indicator divergence degree, market structure, volume support, etc.), only execute high-quality signals or dynamically adjust position size according to signal quality.</li><li><strong>Implement Machine Learning Enhancement</strong>: Use machine learning algorithms to analyze historical trading data, identify characteristic patterns of the most successful signals, and dynamically optimize the trading decision process.</li></ol><h3>Summary</h3><p>The VWAP-Enhanced Bollinger Bands Momentum Reversal Strategy is a well-structured, logically clear short-term cryptocurrency trading system. By capturing potential reversal points through RSI and Bollinger Bands, and using VWAP as a trend confirmation tool, it forms a multi-layered trading signal system. The built-in risk control mechanisms ensure capital safety, while the dynamic position calculation method guarantees consistency in risk exposure.</p><p>Although this strategy demonstrates good capture ability in short-term price fluctuations, users still need to be aware of potential risks such as market environment changes, parameter sensitivity, and liquidity issues. Performance can be further improved by adding market environment filters, optimizing indicator parameters, and enhancing stop-loss mechanisms.</p><p>For traders, it is recommended to first conduct thorough testing in high-liquidity markets such as BTC/ETH, and consider applying it to other crypto assets after becoming familiar with the strategy characteristics. Meanwhile, maintaining continuous observation of the market and regular optimization of the strategy will help maintain a competitive edge in the ever-changing cryptocurrency market.</p><p><strong>Strategy source code</strong></p><pre>/*backtest<br>start: 2024-07-04 00:00:00<br>end: 2025-07-02 08:00:00<br>period: 1d<br>basePeriod: 1d<br>exchanges: [{&quot;eid&quot;:&quot;Futures_Binance&quot;,&quot;currency&quot;:&quot;ETH_USDT&quot;}]<br>*/<br><br>// @version=5<br>// @title Crypto Pulse Strategy Active<br>// @description A more active short-term trading strategy for cryptocurrencies using RSI, Bollinger Bands, and VWAP on 1h to 4h timeframes.<br><br>strategy(&quot;Crypto Pulse Strategy Active&quot;, overlay=true)<br><br>// === INPUTS ===<br>overbought = input.int(75, title=&quot;RSI Overbought Level&quot;, minval=60, maxval=90)<br>oversold = input.int(25, title=&quot;RSI Oversold Level&quot;, minval=10, maxval=40)<br>length_rsi = input.int(14, title=&quot;RSI Length&quot;, minval=5, maxval=30)<br>length_bb = input.int(20, title=&quot;Bollinger Bands Length&quot;, minval=10, maxval=50)<br>mult_bb = input.float(2.0, title=&quot;Bollinger Bands Multiplier&quot;, minval=1.0, maxval=5.0, step=0.1)<br>vwap_source = input.source(close, title=&quot;VWAP Source&quot;)<br>risk_per_trade = input.float(1.0, title=&quot;Risk Per Trade (%)&quot;, minval=0.1, maxval=5.0, step=0.1)<br>stop_loss = input.float(0.015, title=&quot;Stop Loss (%)&quot;, minval=0.001, maxval=0.05, step=0.001)<br><br>// === INDICATORS ===<br>rsi = ta.rsi(close, length_rsi)<br>[bb_middle, bb_upper, bb_lower] = ta.bb(close, length_bb, mult_bb)<br>vwap = ta.vwap(vwap_source)<br><br>// === CONDITIONS ===<br>buy_signal = (ta.crossover(close, bb_lower) or rsi &lt; oversold) and close &gt; vwap  // Buy with VWAP confirmation<br>sell_signal = (ta.crossover(close, bb_upper) or rsi &gt; overbought) and close &lt; vwap  // Sell with VWAP confirmation<br><br>// === POSITION SIZING ===<br>account_balance = strategy.equity<br>risk_amount = account_balance * (risk_per_trade / 100)<br>position_size = risk_amount / (stop_loss * close)<br><br>// === ENTRY LOGIC ===<br>if (buy_signal)<br>    strategy.entry(&quot;Long&quot;, strategy.long, qty=position_size)<br>    strategy.exit(&quot;Exit Long&quot;, &quot;Long&quot;, stop=close * (1 - stop_loss), limit=close * (1 + stop_loss * 1.5))<br><br>if (sell_signal)<br>    strategy.entry(&quot;Short&quot;, strategy.short, qty=position_size)<br>    strategy.exit(&quot;Exit Short&quot;, &quot;Short&quot;, stop=close * (1 + stop_loss), limit=close * (1 - stop_loss * 1.5))<br><br>// === PLOTTING ===<br>plot(rsi, title=&quot;RSI&quot;, color=color.blue)<br>plot(bb_upper, title=&quot;BB Upper&quot;, color=color.red)<br>plot(bb_middle, title=&quot;BB Middle&quot;, color=color.gray)<br>plot(bb_lower, title=&quot;BB Lower&quot;, color=color.green)<br>plot(vwap, title=&quot;VWAP&quot;, color=color.purple)<br>hline(overbought, &quot;Overbought&quot;, color=color.red, linestyle=hline.style_dashed)<br>hline(oversold, &quot;Oversold&quot;, color=color.green, linestyle=hline.style_dashed)<br>plotshape(buy_signal, title=&quot;Buy Signal&quot;, location=location.belowbar, color=color.green, style=shape.triangleup, size=size.small)<br>plotshape(sell_signal, title=&quot;Sell Signal&quot;, location=location.abovebar, color=color.red, style=shape.triangledown, size=size.small)</pre><p><strong>Strategy parameters</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*_lw0wB12m48E9MmDb93rsw.png" /></figure><p>The original address: <a href="https://www.fmz.com/strategy/500481">VWAP-Enhanced Bollinger Bands Momentum Reversal Strategy</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=570b86982021" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Enhanced Cloud Momentum Trend Following Strategy]]></title>
            <link>https://medium.com/@FMZQuant/enhanced-cloud-momentum-trend-following-strategy-bfa56720145b?source=rss-b78414ad1c60------2</link>
            <guid isPermaLink="false">https://medium.com/p/bfa56720145b</guid>
            <category><![CDATA[trading-strategy]]></category>
            <category><![CDATA[fmz-quant]]></category>
            <category><![CDATA[source-code]]></category>
            <category><![CDATA[trend-following]]></category>
            <category><![CDATA[momentum]]></category>
            <dc:creator><![CDATA[FMZQuant]]></dc:creator>
            <pubDate>Thu, 24 Jul 2025 03:15:01 GMT</pubDate>
            <atom:updated>2025-07-24T03:15:01.972Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*aCNrYdfNMyVfl4aB.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*zzeTzbMBYM8X2sBq.png" /></figure><p>I’ll analyze the provided trading strategy code and create a comprehensive article in both Chinese and English according to your requirements.</p><h3>Strategy Overview</h3><p>The Enhanced Cloud Momentum Trend Following Strategy is a powerful trend-following system that combines the Ichimoku Kinko Hyo system with a 171-period Exponential Moving Average (EMA) filter. This strategy is designed for traders looking to capture strong momentum moves while utilizing the cloud structure to identify optimal entry and exit points. It is a patient, low-frequency trading system that prioritizes quality over quantity. The strategy employs non-standard Ichimoku parameters (Conversion Line: 7 periods, Base Line: 211 periods, Lagging Span 2: 120 periods, Displacement: 41 periods) and combines them with a 171-period EMA as an additional trend confirmation layer, enabling precise capture of strong trends.</p><h4>Strategy Principles</h4><p>The core of this strategy lies in the synergistic action of carefully adjusted Ichimoku Cloud components and a long-term EMA filter:</p><ol><li><strong>Ichimoku Cloud Core Components</strong>:</li></ol><ul><li>Conversion Line (Tenkan-sen): 7-period Donchian channel midpoint, more sensitive than the traditional 9-period</li><li>Base Line (Kijun-sen): 211-period Donchian channel midpoint, providing stronger trend confirmation</li><li>Span A (Senkou Span A): Average of Conversion and Base lines, projected 41 periods ahead</li><li>Span B (Senkou Span B): 120-period Donchian channel midpoint, projected 41 periods ahead</li><li>Lagging Span (Chikou Span): Current close plotted 41 periods back</li></ul><p><strong>2. Entry Logic (Default “Ichi” Mode)</strong>:<br>A long position is triggered when ALL of the following conditions are met:</p><ul><li>Cloud Bullish: Span A &gt; Span B (41 periods ago)</li><li>Breakout Confirmation: Current close &gt; 25-period high</li><li>Ichimoku Bullish: Conversion Line &gt; Base Line</li><li>Trend Alignment: Current close &gt; 171-period EMA</li><li>State Memory: No previous buy signal is still active</li></ul><p><strong>3. Exit Logic</strong>:<br>Positions are closed when Ichimoku turns bearish: Conversion Line &lt; Base Line</p><p><strong>4. Alternative “Cloud” Mode</strong>:</p><ul><li>Entry: Span A crosses above Span B with additional cloud and EMA confirmations</li><li>Exit: Span A crosses below Span B with cloud and EMA confirmations</li></ul><p><strong>5. State Memory System</strong>:<br>The strategy implements a sophisticated memory system to track buy/sell states and prevent false signals.</p><h4>Strategy Advantages</h4><ol><li><strong>High-Quality Signal Filtering</strong>:<br>The strategy’s strict entry conditions ensure that it only enters the market when high-probability trends are forming, avoiding market noise and the cost losses associated with frequent trading. By requiring a bullish cloud, price breakout above the 25-period high, bullish Ichimoku, and price above the long-term EMA, the strategy effectively filters out weak signals.</li><li><strong>Multi-Layer Confirmation Mechanism</strong>:<br>Combining the Ichimoku Cloud system with the 171-period EMA provides multiple layers of trend confirmation, significantly reducing the risk of false breakouts and signals. This multi-filter mechanism is particularly suitable for capturing major trend movements.</li><li><strong>Flexible Trading Modes</strong>:<br>The strategy offers two trading modes (“Ichi” and “Cloud”), catering to different trader preferences and market condition requirements. This flexibility allows traders to adapt the strategy based on market characteristics.</li><li><strong>Robust State Memory System</strong>:<br>The implemented state memory system effectively prevents repeated triggering of consecutive signals, improving trading efficiency and reducing unnecessary trading costs.</li><li><strong>Optimized Parameter Settings</strong>:<br>The non-standard Ichimoku parameters (Conversion: 7, Base: 211, Lagging Span 2: 120, Displacement: 41) are optimized to better adapt to modern market conditions and specific asset price characteristics.</li></ol><h4>Strategy Risks</h4><ol><li><strong>Lag Risk</strong>:<br>Like all Ichimoku strategies, signals may lag significant price moves. Especially in rapidly changing market environments, the strategy may miss optimal entry points or delay exits, resulting in reduced gains or increased losses.</li><li><strong>Choppy Market Risk</strong>:<br>While the strategy is designed for trending markets, it may generate false signals in sideways or choppy markets. Extended periods of price consolidation may lead to multiple entries and exits, causing “whipsaw” losses.</li><li><strong>Parameter Sensitivity</strong>:<br>The custom parameters used in the strategy may not be equally effective across all market conditions. Different market environments and assets may require different parameter settings, which necessitates continuous monitoring and adjustment by traders.</li><li><strong>Entry Delay</strong>:<br>The 25-period high breakout confirmation requirement may delay entries in fast-moving markets, causing the strategy to miss a portion of the initial price movement.</li><li><strong>Money Management Risk</strong>:<br>The strategy uses a default 100% equity allocation, which may be too aggressive for actual trading. The lack of proper position sizing control may lead to excessive risk exposure.</li></ol><h4>Optimization Directions</h4><ol><li><strong>Dynamic Parameter Adjustment</strong>:<br>Implement an adaptive parameter system that automatically adjusts Ichimoku periods and EMA length based on market volatility and current trend strength. For example, shortening the Conversion Line period in high volatility markets and extending it in low volatility markets. This would improve the strategy’s adaptability across different market conditions.</li><li><strong>Improved Money Management</strong>:<br>Introduce a more sophisticated money management system that dynamically adjusts position size based on market volatility, current trend strength, and risk metrics. For instance, position size could be adjusted according to ATR (Average True Range) or cloud thickness, increasing positions in strong trends and reducing them in weak trends.</li><li><strong>Add Risk Control Mechanisms</strong>:<br>Implement stop-loss and profit target settings that can be automatically set based on cloud structure, key support/resistance levels, or volatility indicators. For example, using the bottom of the cloud as a stop-loss point for long positions, or using multiples of ATR to set trailing stops.</li><li><strong>Optimize Short-Term Trading Capability</strong>:<br>The current strategy is primarily aimed at long-term trends. Adding short-term indicators (such as RSI or stochastic) could improve performance in short-term market conditions. This would enable the strategy to profit even when trends are not obvious.</li><li><strong>Add Market State Classification</strong>:<br>Add a market state recognition system that automatically distinguishes between trending and ranging markets, and applies different trading rules based on different market states. For example, raising entry thresholds or avoiding trading altogether when a ranging market is identified.</li></ol><h4>Summary</h4><p>The Enhanced Cloud Momentum Trend Following Strategy is a meticulously designed trend-following system that combines customized Ichimoku Cloud parameters with a long-term EMA filter, providing traders with a powerful tool for capturing major trend movements. Through its multi-layer confirmation mechanism, state memory system, and strict entry conditions, the strategy effectively filters out market noise and identifies high-probability trading opportunities.</p><p>While the strategy excels in trending markets, traders should be aware of its potential limitations in choppy markets and its lagging signal characteristics. By introducing dynamic parameter adjustment, improved money management, enhanced risk control mechanisms, optimized short-term trading capability, and market state classification, the strategy can further enhance its adaptability and robustness across different market environments.</p><p>Most importantly, traders should optimize parameters and control position sizing according to their risk tolerance and specific asset characteristics when applying this strategy in practice, and combine it with other technical and fundamental analyses for comprehensive decision-making. The strategy provides a solid trend-following framework, but successful trading still requires discipline, patience, and continuous market observation.</p><p><strong>Strategy source code</strong></p><pre>/*backtest<br>start: 2024-07-07 00:00:00<br>end: 2025-07-04 08:00:00<br>period: 1h<br>basePeriod: 1h<br>exchanges: [{&quot;eid&quot;:&quot;Futures_Binance&quot;,&quot;currency&quot;:&quot;BNB_USDT&quot;}]<br>*/<br><br>//@version=6<br>//Quant Trading<br>strategy(&quot;Enhanced Ichimoku Cloud Strategy V1 [Quant Trading]&quot;, overlay=true,<br>     default_qty_type=strategy.percent_of_equity,<br>     default_qty_value=100,<br>     commission_type=strategy.commission.percent,<br>     commission_value=0.1,<br>     slippage=3,<br>     initial_capital=1000,<br>     margin_long=0,<br>     margin_short=0)<br><br>// === DESCRIPTION ===<br>// Enhanced Ichimoku Cloud Strategy with 171-Day EMA<br>// Original logic preserved with proper formatting and structure<br><br>// === INPUT PARAMETERS ===<br><br>// Ichimoku Settings<br>conversionPeriods = input.int(7, minval=1, title=&quot;Conversion Line Periods&quot;, group=&quot;Ichimoku Settings&quot;)<br>basePeriods = input.int(211, minval=1, title=&quot;Base Line Periods&quot;, group=&quot;Ichimoku Settings&quot;)<br>laggingSpan2Periods = input.int(120, minval=1, title=&quot;Lagging Span 2 Periods&quot;, group=&quot;Ichimoku Settings&quot;)<br>displacement = input.int(41, minval=1, title=&quot;Displacement&quot;, group=&quot;Ichimoku Settings&quot;)<br><br>// EMA Settings<br>emaPeriod = input.int(171, minval=1, title=&quot;EMA Period&quot;, group=&quot;EMA Settings&quot;)<br><br>// Trade Settings<br>tradeModeOptions = input.string(defval=&quot;Ichi&quot;, title=&quot;Trade Setup&quot;, options=[&quot;Ichi&quot;, &quot;Cloud&quot;], group=&quot;Trade Settings&quot;)<br>allowShortTrades = input.bool(false, &quot;Allow Short Trades?&quot;, group=&quot;Trade Settings&quot;)<br><br>// === 1️⃣ CALCULATIONS ===<br><br><br>// EMA Calculation<br>ema171 = ta.ema(close, emaPeriod)<br><br>// Donchian Channel Function<br>f_donchian(len) =&gt;<br>    l = ta.lowest(low, len)<br>    h = ta.highest(high, len)<br>    (l + h) / 2<br><br>// Ichimoku Components<br>conversionLine = f_donchian(conversionPeriods)<br>baseLine = f_donchian(basePeriods)<br>spanA = (conversionLine + baseLine) / 2<br>spanB = f_donchian(laggingSpan2Periods)<br><br>// === 2️⃣ ENTRY &amp; EXIT LOGIC ===<br><br>// Original Ichimoku Conditions (preserved exactly)<br>idealbuy = (spanA[displacement - 1] &gt; spanB[displacement - 1]) and <br>           (close &gt; high[25]) and <br>           (conversionLine &gt; baseLine) and <br>           (close &gt; ema171)<br><br>idealsell = (conversionLine &lt; baseLine)<br><br>// State Tracking (preserved exactly)<br>var bool buymem = false<br>var bool sellmem = false<br><br>if idealbuy<br>    buymem := true<br>else if idealsell<br>    buymem := false<br>else<br>    buymem := buymem[1]<br><br>if idealsell<br>    sellmem := true<br>else if idealbuy<br>    sellmem := false<br>else<br>    sellmem := sellmem[1]<br><br>// Signal Generation (preserved exactly)<br>longCond = idealbuy and not buymem[1]<br>shortCond = idealsell and not sellmem[1]<br><br>// Determine Buy and Sell Signals (preserved exactly)<br>buySignal = (tradeModeOptions == &quot;Ichi&quot;) ? longCond : ta.crossover(spanA, spanB) and (low &gt; spanA[25]) and (low &gt; spanB[25]) and (close &gt; ema171)<br>sellSignal = (tradeModeOptions == &quot;Ichi&quot;) ? shortCond : ta.crossunder(spanA, spanB) and (high &lt; spanA[25]) and (high &lt; spanB[25]) and (close &lt; ema171)<br><br>// === 3️⃣ TRADE EXECUTIONS ===<br><br>// Original Trade Logic (preserved exactly)<br>forced_slippage = close + (3 * syminfo.mintick)<br><br><br>if strategy.position_size == 0 and buySignal<br>    strategy.entry(&quot;Long&quot;, strategy.long, limit=forced_slippage)<br><br>if sellSignal<br>    strategy.close(&quot;Long&quot;)<br><br>// === 4️⃣ VISUALIZATIONS ===<br><br>// Ichimoku Cloud Components<br>plot(conversionLine, color=color.yellow, title=&quot;Conversion Line&quot;)<br>plot(baseLine, color=color.blue, title=&quot;Base Line&quot;)<br><br>p1 = plot(spanA, offset=displacement - 1, color=color.green, title=&quot;Span A&quot;)<br>p2 = plot(spanB, offset=displacement - 1, color=color.red, title=&quot;Span B&quot;)<br>plot(close, offset=-displacement + 1, color=color.gray, title=&quot;Lagging Span&quot;)<br><br>// Cloud Fill<br>fill(p1, p2, color=spanA &gt; spanB ? color.new(color.green, 80) : color.new(color.red, 80))<br><br>// EMA<br>plot(ema171, color=color.orange, title=&quot;171-Day EMA&quot;)<br><br>// Entry and Exit Signals (commented out as in original)<br>// plotshape(series=buySignal, title=&quot;Buy Entry&quot;, location=location.belowbar, style=shape.labelup, color=color.lime, text=&quot;BUY&quot;, size=size.small)<br>// plotshape(series=sellSignal, title=&quot;Sell Exit&quot;, location=location.abovebar, style=shape.labeldown, color=color.red, text=&quot;SELL&quot;, size=size.small)</pre><p><strong>Strategy parameters</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*cNV12g4-Dg8Ezm4Rle0v5A.png" /></figure><p>The original address: <a href="https://www.fmz.com/strategy/500767">Enhanced Cloud Momentum Trend Following Strategy</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=bfa56720145b" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Adaptive Renko Momentum Trend Following Strategy with ADX Filter]]></title>
            <link>https://medium.com/@FMZQuant/adaptive-renko-momentum-trend-following-strategy-with-adx-filter-35755d2310f2?source=rss-b78414ad1c60------2</link>
            <guid isPermaLink="false">https://medium.com/p/35755d2310f2</guid>
            <category><![CDATA[momentum]]></category>
            <category><![CDATA[fmz-quant]]></category>
            <category><![CDATA[trend-following]]></category>
            <category><![CDATA[trading-strategy]]></category>
            <category><![CDATA[cryptocurrency]]></category>
            <dc:creator><![CDATA[FMZQuant]]></dc:creator>
            <pubDate>Thu, 24 Jul 2025 02:16:45 GMT</pubDate>
            <atom:updated>2025-07-24T02:16:45.279Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*lxb6Oo6JxNH31fJ8.png" /></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*YUo8fJnABEqiTIKk.png" /></figure><h3>Strategy Overview</h3><p>The Adaptive Renko Momentum Trend Following Strategy is a trading system based on Renko charts and the UT Bot method, combining an adaptive ATR (Average True Range) trailing stop with an ADX (Average Directional Index) momentum filter. The strategy primarily triggers trading signals when price and EMA (Exponential Moving Average) cross the adaptive trailing stop line and ADX/DI+/DI- conditions are met. This combination is designed to help traders operate in strong trending markets while avoiding choppy, low-momentum market environments, thereby improving trading success rates.</p><p>The core logic revolves around a dynamically adjusting trailing stop line that automatically adapts to market volatility, providing clear entry signals for both long and short positions. Meanwhile, the ADX filter ensures trading only occurs when the market has sufficient directionality and momentum, significantly reducing the possibility of false signals in ranging markets.</p><h3>Strategy Principles</h3><p>The core principles of this strategy are based on several key components:</p><ol><li><strong>ATR Trailing Stop Line</strong>: Uses the ATR indicator to calculate volatility and applies a multiplier factor to create a dynamic stop line. This line can adaptively adjust according to market conditions, widening the stop distance when volatility increases and narrowing it when volatility decreases.</li><li><strong>EMA and Stop Line Crossovers</strong>: When price and EMA cross the trailing stop line, potential trading signals are generated. Specifically, a buy signal is produced when the EMA crosses above the stop line, and a sell signal is produced when the stop line crosses above the EMA.</li><li><strong>ADX Momentum Filter</strong>: Calculates ADX and its related indicators DI+ and DI- to evaluate market trend strength and direction. Trade signals are only confirmed when the ADX value exceeds a set threshold, and the corresponding directional indicator (DI+ for long trades, DI- for short trades) meets its condition.</li><li><strong>Renko Chart Application</strong>: The strategy is specifically designed for Renko charts, leveraging their ability to filter market noise and provide clearer trend signals.</li></ol><p>In its implementation, the strategy first calculates the ATR value, determining whether to use smoothing and adaptive multipliers based on settings. It then constructs the UT Bot trailing stop line, which dynamically adjusts according to price movement. Next, it calculates the EMA and detects crossovers with the stop line. Simultaneously, the strategy manually calculates ADX, DI+, and DI- indicators and sets filter conditions. Ultimately, actual trading signals are only triggered when price/EMA crossovers with the stop line occur and ADX filter conditions are satisfied.</p><h3>Strategy Advantages</h3><p>This strategy offers the following significant advantages:</p><ol><li><strong>Strong Adaptability</strong>: The stop line calculated through ATR can dynamically adjust according to market volatility, allowing the strategy to operate effectively in different market environments. The adaptive ATR multiplier option, in particular, enables automatic adjustment of stop distances based on changes in short-term volatility relative to long-term volatility.</li><li><strong>Dual Trend Confirmation Mechanism</strong>: The combination of EMA crossovers and ADX filtering provides a dual verification mechanism for trend confirmation, significantly reducing the possibility of false breakouts and erroneous signals.</li><li><strong>Avoids Low-Quality Markets</strong>: The ADX and directional indicator filters effectively avoid choppy, directionless market environments, allowing the strategy to focus on high-momentum, clearly directional trading opportunities.</li><li><strong>Clear Visual Feedback</strong>: The strategy provides intuitive stop line displays and trade labels, allowing traders to clearly see entry points and stop loss positions, facilitating real-time decision-making and risk management.</li><li><strong>Highly Customizable</strong>: The strategy offers multiple parameter setting options, including ATR period, multiplier, EMA period, ADX thresholds, etc., allowing traders to optimize and adjust according to personal preferences and different market characteristics.</li><li><strong>Optimized for Renko Charts</strong>: The strategy is specifically designed for Renko charts, fully utilizing their characteristics of reducing noise and highlighting trends, which highly aligns with the strategy’s trend-following nature.</li></ol><h3>Strategy Risks</h3><p>Despite its sophisticated design, this strategy still presents the following potential risks:</p><ol><li><strong>Parameter Sensitivity</strong>: Strategy performance is highly dependent on parameter settings such as ATR period, multiplier, ADX threshold, etc. Inappropriate parameters may lead to excessive false signals or missed important trading opportunities. The solution is comprehensive backtesting and parameter optimization under different market conditions.</li><li><strong>Trend Reversal Risk</strong>: Despite the ADX filter, the strategy may still incur losses when strong trends suddenly reverse. This risk can be mitigated by setting additional stop loss conditions or incorporating other reversal indicators.</li><li><strong>Low Liquidity Market Risk</strong>: In low liquidity markets, price movements may be irregular, leading to inaccurate ATR calculations and trailing stop lines. It is recommended to apply this strategy in markets with adequate liquidity.</li><li><strong>Market Intermittency</strong>: Markets frequently switch between trending and oscillating phases, and even with the ADX filter, false signals may occur during these transitions. Consider adding market structure analysis or time filters to optimize strategy performance.</li><li><strong>Over-Optimization Risk</strong>: With multiple adjustable parameters, there is a risk of over-optimization, which may lead to poor strategy performance in actual trading. Walk-forward testing and out-of-sample testing are recommended to verify the robustness of the strategy.</li></ol><h3>Strategy Optimization Directions</h3><p>Based on code analysis, this strategy can be optimized in the following directions:</p><ol><li><strong>Integrate Multi-Timeframe Analysis</strong>: Introducing trend confirmation from higher timeframes and only trading in the direction of larger trends can improve win rates. This can be implemented by adding long-period moving averages or other trend indicators.</li><li><strong>Dynamically Adjust ADX Thresholds</strong>: The current ADX threshold is fixed; consider dynamically adjusting thresholds based on market volatility or cyclical characteristics to adapt to different market environments. For example, raise the ADX threshold in high volatility markets and lower it in low volatility markets.</li><li><strong>Add Profit Targets and Stop Loss Management</strong>: The current strategy focuses on entry signals; consider adding ATR-based dynamic profit targets and more refined stop loss management, such as trailing stops or partial profit-taking strategies.</li><li><strong>Integrate Volume-Price Relationship Analysis</strong>: Include volume analysis in signal confirmation, only trading when volume confirms the trend, which can further improve signal quality.</li><li><strong>Seasonality and Time Filters</strong>: Add seasonality filters based on historical statistics or specific time period filters to avoid known inefficient trading periods.</li><li><strong>Machine Learning Optimization</strong>: Use machine learning techniques to optimize parameter selection and signal confirmation processes, which can improve strategy adaptability and performance. This involves training models using historical data to predict optimal parameter combinations or directly predict signal reliability.</li><li><strong>Improve Renko Settings</strong>: Explore different Renko brick sizes and construction methods to find the most suitable settings for specific markets. Consider using adaptive Renko brick sizes that dynamically adjust based on market volatility.</li></ol><h3>Summary</h3><p>The Adaptive Renko Momentum Trend Following Strategy is a well-designed trading system combining various technical analysis tools and filtering methods. Through the combination of adaptive ATR trailing stops, EMA crossover signals, and ADX momentum filters, the strategy can effectively identify trading opportunities in strong trending markets while avoiding low-quality oscillating markets.</p><p>The strategy’s main advantages lie in its adaptability and dual confirmation mechanism, allowing it to maintain relatively stable performance across different market environments. Additionally, through clear visual feedback and highly customizable parameter settings, traders can optimize and adjust according to personal preferences and specific market characteristics.</p><p>However, when using this strategy, attention must be paid to parameter sensitivity, trend reversal risks, and over-optimization issues. The strategy’s performance can be further improved by adding multi-timeframe analysis, dynamically adjusting parameters, improving stop loss management, and integrating other analytical tools.</p><p>Overall, this is a trend-following strategy with solid theoretical foundations and reasonable design, particularly suitable for traders interested in Renko charts and momentum trading. Through a thorough understanding of the strategy principles and appropriate parameter optimization, it has the potential to become an effective tool in trading systems.</p><p><strong>Strategy source code</strong></p><pre>/*backtest<br>start: 2025-06-06 00:00:00<br>end: 2025-07-05 10:00:00<br>period: 1h<br>basePeriod: 1h<br>exchanges: [{&quot;eid&quot;:&quot;Futures_Binance&quot;,&quot;currency&quot;:&quot;BNB_USDT&quot;}]<br>*/<br><br>//@version=6<br>strategy(&quot;Renko UT Bot Strategy v6 - ADX Filter&quot;, overlay=true, default_qty_type=strategy.percent_of_equity, default_qty_value=1)<br><br>// === Inputs ===<br>atrPeriod       = input.int(5,    &quot;ATR Period&quot;,               minval=1)<br>atrMult         = input.float(3.5, &quot;ATR Multiplier&quot;,           step=0.1)<br>useAtrSmooth    = input.bool(false,&quot;Use Wilder ATR Smooth&quot;)<br>adaptiveAtr     = input.bool(false,&quot;Adaptive ATR Multiplier&quot;)<br>adaptiveFactor  = input.float(1.0, &quot;Adaptive Mult Factor&quot;,    step=0.1)<br>emaPeriod       = input.int(1,    &quot;EMA Period for Crossover&quot;, minval=1)<br>showStopLine    = input.bool(true, &quot;Show Trailing Stop&quot;)<br>showStopLabel   = input.bool(true, &quot;Show Stop Label&quot;)<br>labelOffset     = input.int(2,    &quot;Label Horizontal Offset&quot;,  minval=-10, maxval=10)<br>labelSizeOpt    = input.string(&quot;small&quot;,&quot;Label Text Size&quot;,     options=[&quot;tiny&quot;,&quot;small&quot;,&quot;normal&quot;,&quot;large&quot;])<br>arrowOffset     = input.int(0,    &quot;Arrow Offset&quot;,             minval=-10, maxval=10)<br><br>// === ADX Filter Inputs ===<br>adxLen      = input.int(14, &quot;ADX Length&quot;, minval=1)<br>adxThresh   = input.float(20, &quot;ADX Threshold&quot;, step=0.1)<br>diplusThresh= input.float(20, &quot;DI+ Threshold&quot;, step=0.1)<br>diminusThresh=input.float(20, &quot;DI- Threshold&quot;, step=0.1)<br><br>// === Price &amp; ATR ===<br>src      = close<br>atrRaw   = useAtrSmooth ? ta.rma(ta.tr, atrPeriod) : ta.atr(atrPeriod)<br>mult     = adaptiveAtr    ? atrMult * (atrRaw / ta.atr(atrPeriod)) * adaptiveFactor : atrMult<br>loss     = atrRaw * mult<br><br>// === UT Bot Trailing Stop ===<br>var float stopLine = na<br>prevStop        = nz(stopLine[1], src)<br>stp1            = src &gt; prevStop ? src - loss : src + loss<br>stp2            = (src &lt; prevStop and src[1] &lt; prevStop) ? math.min(prevStop, src + loss) : stp1<br>stopLine        := (src &gt; prevStop and src[1] &gt; prevStop) ? math.max(prevStop, src - loss) : stp2<br><br>plot(showStopLine ? stopLine : na, title=&quot;Trailing Stop&quot;, color=color.orange)<br><br>// === Signals ===<br>ema1    = ta.ema(src, emaPeriod)<br>buyX    = ta.crossover(ema1, stopLine)<br>sellX   = ta.crossover(stopLine, ema1)<br><br>// === Manual ADX and DI Calculation ===<br>upMove   = high - high[1]<br>downMove = low[1] - low<br>plusDM   = (upMove &gt; downMove and upMove &gt; 0) ? upMove : 0<br>minusDM  = (downMove &gt; upMove and downMove &gt; 0) ? downMove : 0<br>trur     = ta.rma(ta.tr, adxLen)<br>plusDI   = 100 * ta.rma(plusDM, adxLen) / trur<br>minusDI  = 100 * ta.rma(minusDM, adxLen) / trur<br>dx       = 100 * math.abs(plusDI - minusDI) / (plusDI + minusDI)<br>adx      = ta.rma(dx, adxLen)<br><br>// === ADX Filter ===<br>adxFilterLong  = adx &gt; adxThresh and plusDI &gt; diplusThresh<br>adxFilterShort = adx &gt; adxThresh and minusDI &gt; diminusThresh<br><br>// === Filtered Entry Signals ===<br>signalLongEntry  = buyX and src &gt; stopLine and adxFilterLong<br>signalShortEntry = sellX and src &lt; stopLine and adxFilterShort<br><br>// === Entries &amp; Labels ===<br>if signalLongEntry<br>    strategy.entry(&quot;Long&quot;, strategy.long)<br>    if showStopLabel<br>        label.new(bar_index + labelOffset, stopLine,<br>           text=&quot;Stop: &quot; + str.tostring(stopLine, &quot;#.#####&quot;), xloc=xloc.bar_index,<br>           style=label.style_label_left, color=color.orange, textcolor=color.white,<br>           size = labelSizeOpt == &quot;tiny&quot;  ? size.tiny  :<br>                  labelSizeOpt == &quot;small&quot; ? size.small :<br>                  labelSizeOpt == &quot;normal&quot;? size.normal : size.large)<br><br>if signalShortEntry<br>    strategy.entry(&quot;Short&quot;, strategy.short)<br>    if showStopLabel<br>        label.new(bar_index + labelOffset, stopLine,<br>           text=&quot;Stop: &quot; + str.tostring(stopLine, &quot;#.#####&quot;), xloc=xloc.bar_index,<br>           style=label.style_label_left, color=color.orange, textcolor=color.white,<br>           size = labelSizeOpt == &quot;tiny&quot;  ? size.tiny  :<br>                  labelSizeOpt == &quot;small&quot; ? size.small :<br>                  labelSizeOpt == &quot;normal&quot;? size.normal : size.large)<br><br>plotshape(signalLongEntry,  title=&quot;Buy&quot;,  style=shape.triangleup,   location=location.belowbar, color=color.green,  offset=arrowOffset)<br>plotshape(signalShortEntry, title=&quot;Sell&quot;, style=shape.triangledown, location=location.abovebar, color=color.red,    offset=arrowOffset)<br><br>// === Alerts ===<br>alertcondition(signalLongEntry,  title=&quot;UT Bot Long&quot;,  message=&quot;UT Bot Long Signal&quot;)<br>alertcondition(signalShortEntry, title=&quot;UT Bot Short&quot;, message=&quot;UT Bot Short Signal&quot;)<br>if signalLongEntry<br>    alert(&quot;Long @&quot; + str.tostring(close), alert.freq_once_per_bar_close)<br>if signalShortEntry<br>    alert(&quot;Short @&quot; + str.tostring(close), alert.freq_once_per_bar_close)</pre><p><strong>Strategy parameters</strong></p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*PEErlngS9gmgxumsoKA6yQ.png" /></figure><p>The original address: <a href="https://www.fmz.com/strategy/500769">Adaptive Renko Momentum Trend Following Strategy with ADX Filter</a></p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=35755d2310f2" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>