WSA SMA M: Exact Stage Rules and the Zero-Threshold Gap
WSA SMA M compares close with an SMA and compares that SMA’s one-bar change with a threshold. Its four labels are code conditions, not observations of institutional accumulation or distribution. At the supplied threshold of zero, Stage 1 is unreachable, and some valid bars match none of the four conditions.
Inspect the Pine ScriptInspect the implementation before relying on its name
Pineify names this configuration WSA SMA M and associates it with Weinstein Stage Analysis. The implementation below is a specific two-variable classifier; the name does not establish equivalence with a complete historical trading method. It reads only close, computes an SMA, and returns four Boolean fields.
Let C be current close, A = SMA(close, N), and s = A − previous A. The fixed call uses N = 150 and threshold t = 0. The source contains no volume analysis, relative-strength comparison, base-duration test, breakout test or memory of a preceding stage. It can move directly between conditions and does not enforce a four-stage cycle.
The SMA uses the active chart timeframe. On a daily chart it averages 150 daily closes; on a weekly chart it averages 150 weekly closes. There is no weekly data request. Even 150 daily closes and 30 weekly closes are different samples: weekly closes omit the other daily observations, so their averages are not generally equal.
Read the four Boolean rules literally
| Label in this script | Condition | Boundary |
|---|---|---|
| Stage 1, light green | C < A and abs(s) < t | Impossible when t = 0. |
| Stage 2, green | C > A and s > t | A current state, not necessarily a fresh crossing. |
| Stage 3, yellow | C > A and s < t | At positive t, can include a rising SMA. |
| Stage 4, red | C < A and s < −t | Strictly below the negative threshold. |
With t = 0, abs(s) < 0 cannot be true, including when s equals zero. This means the light-green Stage 1 branch never activates in the supplied copy. A rule requiring twenty preceding Stage 1 bars cannot be satisfied with this default. The code is retained here for inspection; this limitation has not been silently repaired or redefined.
When close equals the SMA, all four conditions are false. At t = 0, a flat SMA also yields no stage; price below a rising SMA is another unclassified combination. The script passes na to its barcolor calls in those cases, leaving the chart’s ordinary candle coloring rather than inventing a neutral stage.
For a positive t, equality still matters. Above the SMA with s = t is neither Stage 2 nor Stage 3. Below the SMA with s = −t is neither Stage 1 nor Stage 4. Below the SMA with s ≥ t is also unclassified. Thus these predicates do not form a complete four-way partition of valid inputs.
Use small counterexamples to verify stage meaning
With N = 3, previous closes 90, 100 and 110 average 100. After a new close of 90, the window is 100, 110 and 90, still averaging 100. Price is below a flat SMA, yet Stage 1 remains false when t = 0. This is a complete-price example of the unreachable default branch.
For another window, previous closes 90, 100 and 110 again average 100, but the new close is 108. The new average is (100 + 110 + 108) / 3 = 106, giving slope 6. At t = 0, the bar is Stage 2 because 108 exceeds 106 and the SMA rises. The latest close nevertheless fell from 110 to 108. A Stage 2 label does not mean the latest price change was positive.
Consider an assumed state C = 101, A = 100 and s = 0.2. At t = 0 it is Stage 2; at t = 0.5 it is Stage 3 even though the SMA still rises. Increasing the threshold does not simply hold an existing bullish state longer. There is no retained-state variable. These examples test conditions; they establish no market win rate.
Slope units change how thresholds behave
With complete, equally spaced observations and fixed N, the SMA change is (current close − close leaving the window) / N. It is measured in chart price units per bar, not percent, angle or ATR. The SMA guide explains the rolling-window calculation; TradingView documents the underlying average.
Scaling every price by ten scales A and s by ten. If t stays 0.5, the preceding assumed slope 0.2 becomes 2 and the classification changes from Stage 3 to Stage 2, despite the identical proportionate price path. To preserve this price-unit rule under positive scaling, the threshold must scale too. A numerical threshold cannot be transferred indiscriminately between currencies, share prices or split-adjusted histories.
The helper does not restrict negative thresholds. Those values alter the meaning further: Stage 1 remains impossible, and a negative t can let Stage 4 include a positive slope because −t is positive. Treat any proposed normalized or nonnegative-threshold variant as an explicitly different rule, with its own equality and missing-data policies.
Current colors are not confirmed orders
The pasted code contains no input functions. Its two helper arguments are fixed at 150 and 0; changing them requires editing the call or adding inputs. The separate Visual Editor configuration has SMA Period and Minimum Slope fields, which do not turn into controls in this fixed standalone copy.
There is no bar-close gate. Current close changes the SMA and its slope during an open bar, so a color can change before close. Unused time-range helpers in the listing do not create a session filter. There are no alerts, entries, exits or backtest results. An SMA seed also needs history; comparing two successive valid averages needs another observation beyond the first complete window.
Before adapting this into a regime filter, specify whether every valid bar must receive a category, how equalities work, whether a flat band is symmetric, and whether state persists through unclassified bars. A rising-average condition alone does not identify who is buying, establish a base or demonstrate that a decline has ended. Additional indicators cannot establish those conclusions without a separately tested rule.
Use TradingView’s realtime calculation guidance when deciding when to observe the condition. A closed-bar signal still requires an execution model, costs and risk rules before it becomes a strategy test.
Pine Script v6: implementation and limits
The calculation is retained exactly, including the unreachable Stage 1 branch at the supplied zero threshold. The code’s field names describe predicates rather than verified market regimes. The preview is not proof that all four branches can occur with this fixed call.
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © Pineify
//======================================================================//
// ____ _ _ __ //
// | _ (_)_ __ ___(_)/ _|_ _ //
// | |_) | | '_ / _ | |_| | | | //
// | __/| | | | | __/ | _| |_| | //
// |_| |_|_| |_|___|_|_| __, | //
// |___/ //
//======================================================================//
//@version=6
indicator(title="WSA SMA M", overlay=true, max_labels_count=500)
//#region Custom Code
//#endregion
//#region Common Dependence
p_comm_time_range_to_unix_time(string time_range, int date_time = time, string timezone = syminfo.timezone) =>
int start_unix_time = na
int end_unix_time = na
int start_time_hour = na
int start_time_minute = na
int end_time_hour = na
int end_time_minute = na
if str.length(time_range) == 11
start_time_hour := math.floor(str.tonumber(str.substring(time_range, 0, 2)))
start_time_minute := math.floor(str.tonumber(str.substring(time_range, 3, 5)))
end_time_hour := math.floor(str.tonumber(str.substring(time_range, 6, 8)))
end_time_minute := math.floor(str.tonumber(str.substring(time_range, 9, 11)))
else if str.length(time_range) == 9
start_time_hour := math.floor(str.tonumber(str.substring(time_range, 0, 2)))
start_time_minute := math.floor(str.tonumber(str.substring(time_range, 2, 4)))
end_time_hour := math.floor(str.tonumber(str.substring(time_range, 5, 7)))
end_time_minute := math.floor(str.tonumber(str.substring(time_range, 7, 9)))
start_unix_time := timestamp(timezone, year(date_time, timezone), month(date_time, timezone), dayofmonth(date_time, timezone), start_time_hour, start_time_minute, 0)
end_unix_time := timestamp(timezone, year(date_time, timezone), month(date_time, timezone), dayofmonth(date_time, timezone), end_time_hour, end_time_minute, 0)
[start_unix_time, end_unix_time]
p_comm_time_range_to_start_unix_time(string time_range, int date_time = time, string timezone = syminfo.timezone) =>
int start_time_hour = na
int start_time_minute = na
if str.length(time_range) == 11
start_time_hour := math.floor(str.tonumber(str.substring(time_range, 0, 2)))
start_time_minute := math.floor(str.tonumber(str.substring(time_range, 3, 5)))
else if str.length(time_range) == 9
start_time_hour := math.floor(str.tonumber(str.substring(time_range, 0, 2)))
start_time_minute := math.floor(str.tonumber(str.substring(time_range, 2, 4)))
timestamp(timezone, year(date_time, timezone), month(date_time, timezone), dayofmonth(date_time, timezone), start_time_hour, start_time_minute, 0)
p_comm_time_range_to_end_unix_time(string time_range, int date_time = time, string timezone = syminfo.timezone) =>
int end_time_hour = na
int end_time_minute = na
if str.length(time_range) == 11
end_time_hour := math.floor(str.tonumber(str.substring(time_range, 6, 8)))
end_time_minute := math.floor(str.tonumber(str.substring(time_range, 9, 11)))
else if str.length(time_range) == 9
end_time_hour := math.floor(str.tonumber(str.substring(time_range, 5, 7)))
end_time_minute := math.floor(str.tonumber(str.substring(time_range, 7, 9)))
timestamp(timezone, year(date_time, timezone), month(date_time, timezone), dayofmonth(date_time, timezone), end_time_hour, end_time_minute, 0)
p_comm_timeframe_to_seconds(simple string tf) =>
float seconds = 0
tf_lower = str.lower(tf)
value = str.tonumber(str.substring(tf_lower, 0, str.length(tf_lower) - 1))
if str.endswith(tf_lower, 's')
seconds := value
else if str.endswith(tf_lower, 'd')
seconds := value * 86400
else if str.endswith(tf_lower, 'w')
seconds := value * 604800
else if str.endswith(tf_lower, 'm')
seconds := value * 2592000
else
seconds := str.tonumber(tf_lower) * 60
seconds
p_custom_sources() =>
[open, high, low, close, volume]
//#endregion
//#region Ta Dependence
p_ta_wsa_sma_m(simple int sma_length, simple float slope_threshold) =>
sma = ta.sma(close, sma_length)
sma_slope = sma - sma[1]
stage_1 = close < sma and math.abs(sma_slope) < slope_threshold
stage_2 = close > sma and sma_slope > slope_threshold
stage_3 = close > sma and sma_slope < slope_threshold
stage_4 = close < sma and sma_slope < -slope_threshold
[sma, stage_1, stage_2, stage_3, stage_4]
//#endregion
//#region Constants
string P_GP_1 = ""
//#endregion
//#region Inputs
//#endregion
//#region Price Data
//#endregion
//#region Indicators
[p_ind_1_sma, p_ind_1_stage_1, p_ind_1_stage_2, p_ind_1_stage_3, p_ind_1_stage_4] = p_ta_wsa_sma_m(150, 0)
//#endregion
//#region Conditions
//#endregion
//#region Indicator Plots
plot(p_ind_1_sma, title="WSA SMA M - SMA", color=color.rgb(120, 123, 134, 0), linewidth=2)
barcolor(p_ind_1_stage_1 ? color.rgb(176, 243, 200, 0) : na, title="WSA SMA M - Stage 1: Accumulation")
barcolor(p_ind_1_stage_2 ? color.rgb(76, 175, 80, 0) : na, title="WSA SMA M - Stage 2: Bullish")
barcolor(p_ind_1_stage_3 ? color.rgb(253, 216, 53, 0) : na, title="WSA SMA M - Stage 3: Distribution")
barcolor(p_ind_1_stage_4 ? color.rgb(242, 54, 69, 0) : na, title="WSA SMA M - Stage 4: Bearish")
//#endregion
//#region Custom Plots
//#endregion
//#region Alert
//#endregion
Specify a checkable adaptation in Pineify
Give the Pine Script AI Coding Agent an explicit classification table covering price above, equal to and below the SMA, and slope below, inside and above a stated flat band. Ask it to distinguish a proposed correction from this retained helper, expose the compared values, and test equality cases. Validate the final source and inspect chart values before adding trading rules; this page does not claim the shared product helper has been corrected.
Open Pine Script AI Coding AgentEducational indicator analysis. No measured trading performance is established here. Syntax validation does not prove formula equivalence, execution assumptions or profitability.