|sdi_seaproj of 10, year-long seasons anchored 20 weeks before current bar.|
- plots on a regular chart - no need to switch to a special charting mode.
- has choice of anchor date - tos seasonality chart mode is permanently anchored to january 1, whereas sdi_seaproj can anchor to a variable date trailing a parameter number of bars in the past or a fixed date of one's choosing. anchoring near the last bar of the chart plots the projection mostly into the right extension area leaving the main chart relatively uncluttered for technical analysis.
- provides reliability indicator - tos seasonality provides no statistical measure of the distribution of seasonal data whereas sdi_seaproj provides a reliability indicator based on standard deviation to show when seasonality is reliable or not.
- can skip an anomalous season - sdi_seaproj has a parameter one can specify to remove an anomalous season from the average. this was mentioned by larry williams (of williams %r fame) as being crucial to utilizing seasonality charting.
- can explore subcycles - sdi_seapro has parameters one can specify to define the season length and number to average. this frees one to explore cycles in the chart data on any scale, whereas tos seasonality is limited to a season length of one year and season number defined by the chart duration.
- variable number of seasons -previously, sdi_seapro5 was limited to a fixed five-season average. now, in sdi_seaproj, i utilize the fold statement of thinkscript to process a user specified number of seasons. as a consequence sdi_seaproj cannot show individual season projections which require a separate, valid, plot object to be statically declared for each season. this turns out to be a minor detraction since there is a reliability indication in the sdi studies.
- flat line color tied to projection average color. previously one had to change the color of both of these plots separately.
- plot starts on anchor date close. previously, in sdi_seapro5, the plot of the average started on the bar after the anchor date. now, in sdi_seaproj, the plot starts on the close price of the anchor date to provide confidence in the correct date selection.
- reliability indicator color chooser. previously, in sdi_seaproj5, the color of the reliability indicator was fixed to green/red, now, in sdi_seaproj, one can choose the up/down colors for ri.
- simplified reliability indicator. previously, in sdi_seapro5, there were indicators that decorated the top edge of the reliability indicator that did not provide much in the way of actionable information. now, in sdi_seaproj, the reliability indicator is simplified to one job: showing where the standard deviation bands cross the flatline. there is a straightforward parameter called, ri factor, that determines the multiple of standard deviation to utilize in the reliability indicator.
# sdi_seaproj: Season Seasonal Projection Of Price
#hint: Displays a seasonal projection of price based on the average percentage price move between the anchor date and same seasonal dates in the past. Also shows a reliability indicator to help discern which stocks have seasons reliable enough to trade. sdi_seaproj revision: 1.0 source: http://www.smalldoginvestor.com
# author: allen everhart
# rev 1.0 date: 28sep2013
# copylefts reserved. This is free software. That means you are free
# to use or modify it for your own usage but not for resale.
# Help me get the word out about my blog by keeping this header
# in place.
input trailAnchor = 0; #hint trailAnchor: Sets Moving anchor date to n-bars ago. FixedAnchorDate takes precedence over trailAnchor. The plot of the seasonal average always starts on the close of the anchorDate bar. sdi_seaproj revision: 1.0 source: http://www.smalldoginvestor.com
input fixedAnchorDate = 0; #hint fixedAnchorDate: Sets an anchor date that does not move. Format: YYYYMMDD. FixedAnchorDate takes precedence over trailAnchor. The plot of the seasonal average always starts on the close of the anchorDate bar.
input numSeasons = 5 ; #hint numSeasons: Number of seasons to average.<br><br>note: On the shorter chart durations (1-5 years) thinkscript can access data beyond the scope of the chart. If the projection is not displaying then select fewer seasons and/or increase the chart duration.
input lenSeason = 52 ; #hint lenSeason: Sets number of bars in a season. <br><br>note: There are about 252 trading days per year for US stocks and about 260/year for futures and forex.
input skipSeason = 0 ; #hint skipSeason: Suppress an anomalous season from the average. Skipping a season causes the average to look back an extra season so as to preserve the numSeasons in the average.
input riFactor = 0.3 ; #hint riFactor:multiple of standard deviation to use for ri (reliability indicator.) the ri shows when there might be a reliable trade based on seasonality. the up-ri shows when the lower band line (riFactor*stdev) tracks above the flat line. the down-ri shows when the upper band line tracks below the flat line. <br><br>note: 54% of the individual year projections are above the 0.1*stdev band, 62% above 0.3*stdev, 73% above 0.6*stdev and 84% above 1.0*stdev.
def anchorDate =
if fixedAnchorDate > 0 then
else if trailAnchor > 0 && !IsNaN(close[-trailAnchor]) && IsNaN(close[-trailAnchor - 1]) then
else if trailAnchor > 0 && anchorDate > 0 then # 1.5.2 added  to originDate
#plot od = originDate;
### pn tells us how many bars we are past the originDate
def pn =
if !pn && GetYYYYMMDD() == anchorDate then
else if !pn && IsNaN(close) && !IsNaN(close) then
else if pn > 0 then
pn + 1
#number of seasons we are skipping
def skipNum = if skipSeason > 0 && skipSeason <= numSeasons then 1 else 0 ;
def avgPctMove =
if pn > 0 then
fold sn = 1 to numSeasons + skipNum + 1 with psum=0 do
if sn != skipSeason then
psum + ((GetValue(close, sn * lenSeason) / GetValue(close, sn * lenSeason + pn)) / numSeasons)
def flatLine =
if pn[-1] == 1 then close
else if pn >= 1 then flatLine
plot pa =
if pn[-1] == 1 then close
else if pn > 0 then avgPctMove * flatLine
else Double.NaN ;
plot fl = if pn[-1] > 0 then flatLine else Double.NaN; # flat line
def variance =
if pn > 0 then
fold ssn = 1 to numSeasons + skipNum + 1 with pvar=0 do
if ssn != skipSeason then
pvar + (Sqr(GetValue(close, ssn * lenSeason) - pa) / numSeasons)
def pstd = Sqrt(variance);
def hpul = pa + (riFactor * pstd);
def hpll = pa - (riFactor * pstd);
#plot ul = hpul ;
#plot ll = hpll ;
plot ri = # High Probability indicator
if riFactor == 0.0 then
else if pn > 0 && hpll > flatLine then
else if pn > 0 && hpul < flatLine then
AddCloud( ri, fl, ri.Color("Up"), ri.Color("Down") );