Merge pull request #19 from zhutoutoutousan/develop

Develop
This commit is contained in:
zhutoutoutousan
2025-08-29 04:29:58 +02:00
committed by GitHub
2 changed files with 234 additions and 0 deletions
+32
View File
@@ -0,0 +1,32 @@
SSE Index Multi-Timeframe RSI Momentum Strategy with EMA Distance Trading
Strategy Overview:
This advanced momentum-based trading system is specifically designed for the Shanghai Stock Exchange (SSE) Index, capturing RSI bounce opportunities across multiple timeframes while incorporating sophisticated EMA distance-based entries. The strategy combines traditional RSI oversold/overbought analysis with modern volatility-adjusted position management.
Core Trading Logic:
Weekly RSI Signals: Large position entries (10% equity) when weekly RSI crosses above 30 after being oversold, targeting major trend reversals
Daily RSI Signals: Medium position entries (5% equity) when daily RSI crosses above 30, capturing short-term momentum shifts
EMA Distance Entries: Strategic entries (7.5% equity) when price extends 50+ pips from 200 EMA while remaining above it, exploiting mean reversion opportunities
Risk Management System:
Partial Profit Taking: Both RSI positions scale out 25% when daily RSI becomes overbought (>70), allowing multiple profit captures
Complete Weekly Exits: All weekly positions close when weekly RSI becomes overbought, ensuring trend-following discipline
EMA Crossover Exits: EMA distance trades exit cleanly when price crosses below 50 EMA, providing responsive trend change detection
Emergency Exit: Master exit when EMA crosses above price, protecting all positions during major trend reversals
Advanced Features:
Concurrent Position Management: Up to 100 pyramiding positions across three distinct entry strategies
Multi-Timeframe Analysis: Seamlessly integrates weekly and daily RSI data regardless of chart timeframe
Real-Time Monitoring: Comprehensive information table displaying RSI levels, EMA distances, position quantities, and trade counts
Visual Feedback System: Color-coded entry/exit signals with background highlighting for immediate market condition recognition
Ideal Market Conditions:
Optimized for volatile, emotion-driven markets like Chinese equities where RSI bounces from oversold levels frequently create profitable momentum shifts. The strategy's multiple entry mechanisms ensure comprehensive market coverage while sophisticated exit rules protect capital during adverse conditions.
Technical Requirements:
Recommended for SSE Composite Index, SSE 50, or related Chinese equity ETFs
Best performance on daily charts with sufficient historical data
Suitable for accounts with minimum $10,000 capital for effective position sizing
This strategy represents a complete trading system combining technical analysis fundamentals with modern risk management principles, specifically calibrated for the unique characteristics of Chinese equity markets.
+202
View File
@@ -0,0 +1,202 @@
//@version=6
strategy("SSE Index RSI Bounce Strategy", overlay=true, default_qty_type=strategy.percent_of_equity, initial_capital=10000, pyramiding=100, calc_on_every_tick=false, calc_on_order_fills=false)
// Input parameters
rsi_length = input.int(17, "RSI Length", minval=1)
rsi_oversold = input.int(27, "RSI Oversold Level", minval=1, maxval=50)
rsi_overbought = input.int(86, "RSI Overbought Level", minval=50, maxval=100)
ema_length = input.int(177, "EMA Length", minval=1)
weekly_position_size = input.float(14.0, "Weekly Signal Position Size (%)", minval=0.1, maxval=100)
daily_position_size = input.float(11.0, "Daily Signal Position Size (%)", minval=0.1, maxval=100)
partial_exit_percent = input.float(41.0, "Partial Exit Percentage on Daily RSI Overbought (%)", minval=10.0, maxval=50.0)
// New EMA Distance Trading Parameters
ema_distance_threshold = input.float(16.0, "EMA Distance Threshold (Pips)", minval=1.0, maxval=1000.0)
ema_distance_position_size = input.float(53, "EMA Distance Position Size (%)", minval=0.1, maxval=100)
// EMA Distance Exit Parameters
ema_exit_period = input.int(34, "EMA Exit Period", minval=10, maxval=200)
enable_volume_confirmation = input.bool(true, "Require Volume Confirmation for EMA Exit")
// Calculate indicators
rsi_daily = ta.rsi(close, rsi_length)
rsi_weekly = request.security(syminfo.tickerid, "1W", ta.rsi(close, rsi_length))
ema_200 = ta.ema(close, ema_length)
ema_exit = ta.ema(close, ema_exit_period)
// EMA Distance Trading Logic
pip_size = syminfo.mintick * 10 // Adjust pip size based on instrument
price_ema_distance = math.abs(close - ema_200) / pip_size
ema_distance_entry = price_ema_distance >= ema_distance_threshold * 100 and close > ema_200 // Only enter when price above EMA
// RSI bounce conditions - back to original crossover logic
// Weekly RSI bounce: RSI was below 30 and now crosses above 30
rsi_weekly_prev = request.security(syminfo.tickerid, "1W", ta.rsi(close, rsi_length)[1])
weekly_bounce = rsi_weekly_prev < rsi_oversold and rsi_weekly > rsi_oversold
// Daily RSI bounce: RSI was below 30 and now crosses above 30
daily_bounce = rsi_daily[1] < rsi_oversold and rsi_daily > rsi_oversold
// Overbought conditions for exits - keep as crossovers for exits
daily_rsi_overbought = rsi_daily > rsi_overbought and rsi_daily[1] <= rsi_overbought
weekly_rsi_overbought = rsi_weekly > rsi_overbought and rsi_weekly_prev <= rsi_overbought
// EMA exit condition: EMA was above price but now below price
ema_above_price_prev = ema_200[1] > close[1]
ema_below_price_now = ema_200 < close
ema_exit_condition = ema_above_price_prev and ema_below_price_now
// EMA Distance exit condition - EMA crossover exit
// Price crosses below shorter period EMA (more responsive than 200 EMA)
price_above_ema_exit_prev = close[1] > ema_exit[1]
price_below_ema_exit_now = close < ema_exit
ema_crossover_exit = price_above_ema_exit_prev and price_below_ema_exit_now
// Optional volume confirmation
volume_confirmation = not enable_volume_confirmation or volume > ta.sma(volume, 20)
ema_distance_exit_condition = ema_crossover_exit and volume_confirmation
// Track positions separately with counters for multiple trades
var int weekly_trade_count = 0
var int daily_trade_count = 0
var int ema_distance_trade_count = 0
var float weekly_position_qty = 0.0
var float daily_position_qty = 0.0
var float ema_distance_position_qty = 0.0
// Entry conditions - allow multiple concurrent trades
weekly_entry = weekly_bounce
daily_entry = daily_bounce
// Strategy execution - ensure ALL signals result in trades
if weekly_entry
strategy.entry("Weekly_Long", strategy.long, qty=weekly_position_size, comment="Weekly RSI Bounce #" + str.tostring(weekly_trade_count + 1), alert_message="Weekly Entry")
weekly_trade_count := weekly_trade_count + 1
weekly_position_qty := weekly_position_qty + weekly_position_size
if daily_entry
strategy.entry("Daily_Long", strategy.long, qty=daily_position_size, comment="Daily RSI Bounce #" + str.tostring(daily_trade_count + 1), alert_message="Daily Entry")
daily_trade_count := daily_trade_count + 1
daily_position_qty := daily_position_qty + daily_position_size
if ema_distance_entry
strategy.entry("EMA_Distance_Long", strategy.long, qty=ema_distance_position_size, comment="EMA Distance Entry #" + str.tostring(ema_distance_trade_count + 1), alert_message="EMA Distance Entry")
ema_distance_trade_count := ema_distance_trade_count + 1
ema_distance_position_qty := ema_distance_position_qty + ema_distance_position_size
// Debug - show actual entry attempts
if weekly_entry
label.new(bar_index, high + (high - low) * 0.1, "WEEKLY ENTRY ATTEMPT",
color=color.green, textcolor=color.white, size=size.normal, style=label.style_label_down)
if daily_entry
label.new(bar_index, high + (high - low) * 0.15, "DAILY ENTRY ATTEMPT",
color=color.blue, textcolor=color.white, size=size.normal, style=label.style_label_down)
if ema_distance_entry
label.new(bar_index, high + (high - low) * 0.2, "EMA DISTANCE: " + str.tostring(price_ema_distance, "#.#") + " pips",
color=color.purple, textcolor=color.white, size=size.normal, style=label.style_label_down)
// Partial exit for weekly positions on daily RSI overbought
if daily_rsi_overbought and weekly_position_qty > 0
exit_qty = weekly_position_qty * (partial_exit_percent / 100)
strategy.close("Weekly_Long", qty=exit_qty, comment="Weekly Partial Exit Daily OB")
weekly_position_qty := math.max(0, weekly_position_qty - exit_qty)
// Partial exit for daily positions on daily RSI overbought
if daily_rsi_overbought and daily_position_qty > 0
exit_qty_daily = daily_position_qty * (partial_exit_percent / 100)
strategy.close("Daily_Long", qty=exit_qty_daily, comment="Daily Partial Exit OB")
daily_position_qty := math.max(0, daily_position_qty - exit_qty_daily)
// Complete exit for weekly positions on weekly RSI overbought
if weekly_rsi_overbought and weekly_position_qty > 0
strategy.close("Weekly_Long", comment="Complete Exit Weekly OB")
weekly_position_qty := 0.0
weekly_trade_count := 0
// Exit all positions when EMA crosses from above price to below price
if ema_exit_condition and strategy.position_size > 0
strategy.close_all("EMA Cross Exit")
weekly_position_qty := 0.0
daily_position_qty := 0.0
ema_distance_position_qty := 0.0
weekly_trade_count := 0
daily_trade_count := 0
ema_distance_trade_count := 0
// Exit EMA distance positions when price crosses below EMA (anti-crossover)
if ema_distance_exit_condition and ema_distance_position_qty > 0
strategy.close("EMA_Distance_Long", comment="EMA Distance Anti-Cross Exit")
ema_distance_position_qty := 0.0
ema_distance_trade_count := 0
// Plotting
plot(ema_200, "200 EMA", color=color.orange, linewidth=2)
plot(ema_exit, "EMA Exit", color=color.purple, linewidth=1, style=plot.style_line)
plot(rsi_daily, "Daily RSI", color=color.blue, display=display.data_window)
plot(rsi_weekly, "Weekly RSI", color=color.red, display=display.data_window)
// Plot RSI levels
hline(rsi_oversold, "Oversold Level", color=color.red, linestyle=hline.style_dashed)
hline(rsi_overbought, "Overbought Level", color=color.green, linestyle=hline.style_dashed)
// Background color for RSI conditions
bgcolor(weekly_bounce ? color.new(color.green, 90) : na, title="Weekly RSI Bounce")
bgcolor(daily_bounce ? color.new(color.blue, 90) : na, title="Daily RSI Bounce")
bgcolor(daily_rsi_overbought and (weekly_position_qty > 0 or daily_position_qty > 0) ? color.new(color.yellow, 90) : na, title="Daily RSI Overbought (Partial Exit)")
bgcolor(weekly_rsi_overbought and weekly_position_qty > 0 ? color.new(color.orange, 90) : na, title="Weekly RSI Overbought (Complete Exit)")
bgcolor(ema_exit_condition and strategy.position_size > 0 ? color.new(color.red, 90) : na, title="EMA Cross Exit")
bgcolor(ema_distance_exit_condition and ema_distance_position_qty > 0 ? color.new(color.maroon, 90) : na, title="EMA Distance Anti-Cross Exit")
bgcolor(ema_distance_entry ? color.new(color.purple, 90) : na, title="EMA Distance Entry")
// Plot entry and exit signals with enhanced debugging
plotshape(weekly_entry, "Weekly Entry", shape.triangleup, location.belowbar, color.green, size=size.normal)
plotshape(daily_entry, "Daily Entry", shape.triangleup, location.belowbar, color.blue, size=size.small)
plotshape(ema_distance_entry, "EMA Distance Entry", shape.triangleup, location.belowbar, color.purple, size=size.normal)
plotshape(daily_rsi_overbought and (weekly_position_qty > 0 or daily_position_qty > 0), "Partial Exit Both", shape.circle, location.abovebar, color.yellow, size=size.small)
plotshape(weekly_rsi_overbought and weekly_position_qty > 0, "Complete Exit Weekly OB", shape.triangledown, location.abovebar, color.orange, size=size.normal)
plotshape(ema_exit_condition and strategy.position_size > 0, "EMA Cross Exit", shape.triangledown, location.abovebar, color.red, size=size.large)
plotshape(ema_distance_exit_condition and ema_distance_position_qty > 0, "EMA Distance Anti-Cross Exit", shape.triangledown, location.abovebar, color.maroon, size=size.normal)
// Debug labels to show when conditions are met
if weekly_bounce
label.new(bar_index, low - (high - low) * 0.1, "W-RSI: " + str.tostring(rsi_weekly, "#.##"),
color=color.green, textcolor=color.white, size=size.small, style=label.style_label_up)
if daily_bounce
label.new(bar_index, low - (high - low) * 0.05, "D-RSI: " + str.tostring(rsi_daily, "#.##"),
color=color.blue, textcolor=color.white, size=size.small, style=label.style_label_up)
// Table to show current status
var table info_table = table.new(position.top_right, 2, 12, bgcolor=color.white, border_width=1)
if barstate.islast
table.cell(info_table, 0, 0, "Indicator", bgcolor=color.gray, text_color=color.white)
table.cell(info_table, 1, 0, "Value", bgcolor=color.gray, text_color=color.white)
table.cell(info_table, 0, 1, "Daily RSI", bgcolor=color.white)
table.cell(info_table, 1, 1, str.tostring(rsi_daily, "#.##"), bgcolor=color.white)
table.cell(info_table, 0, 2, "Weekly RSI", bgcolor=color.white)
table.cell(info_table, 1, 2, str.tostring(rsi_weekly, "#.##"), bgcolor=color.white)
table.cell(info_table, 0, 3, "200 EMA", bgcolor=color.white)
table.cell(info_table, 1, 3, str.tostring(ema_200, "#.##"), bgcolor=color.white)
table.cell(info_table, 0, 4, "EMA Distance", bgcolor=color.white)
table.cell(info_table, 1, 4, str.tostring(price_ema_distance, "#.#") + " pips", bgcolor=color.white)
table.cell(info_table, 0, 5, "EMA Exit Level", bgcolor=color.white)
table.cell(info_table, 1, 5, str.tostring(ema_exit, "#.##"), bgcolor=color.white)
table.cell(info_table, 0, 6, "Total Position", bgcolor=color.white)
table.cell(info_table, 1, 6, strategy.position_size > 0 ? "Long" : "None",
bgcolor=strategy.position_size > 0 ? color.green : color.white)
table.cell(info_table, 0, 7, "Total Size", bgcolor=color.white)
table.cell(info_table, 1, 7, str.tostring(strategy.position_size, "#.####"), bgcolor=color.white)
table.cell(info_table, 0, 8, "Weekly Qty", bgcolor=color.white)
table.cell(info_table, 1, 8, str.tostring(weekly_position_qty, "#.####"),
bgcolor=weekly_position_qty > 0 ? color.green : color.white)
table.cell(info_table, 0, 9, "Daily Qty", bgcolor=color.white)
table.cell(info_table, 1, 9, str.tostring(daily_position_qty, "#.####"),
bgcolor=daily_position_qty > 0 ? color.blue : color.white)
table.cell(info_table, 0, 10, "EMA Distance Qty", bgcolor=color.white)
table.cell(info_table, 1, 10, str.tostring(ema_distance_position_qty, "#.####"),
bgcolor=ema_distance_position_qty > 0 ? color.purple : color.white)
table.cell(info_table, 0, 11, "Trade Counts", bgcolor=color.white)
table.cell(info_table, 1, 11, "W:" + str.tostring(weekly_trade_count) + " D:" + str.tostring(daily_trade_count) + " E:" + str.tostring(ema_distance_trade_count), bgcolor=color.white)