Analyzing the "Santa Rally" in Pine Script

This lesson demonstrates how to build a date-range analysis indicator to calculate the average return over a seasonal time of year.

Check out my other free lessons!

Source Code

// This Pine Script™ code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © ZenAndTheArtOfTrading
// @version=6
indicator("Christmas Performance", overlay=true)

// Get date inputs
startMonth  = input.int(12, "Start Month",  inline="1")
startDay    = input.int(1,  "Start Day",    inline="2")
endMonth    = input.int(12, "End Month",    inline="1")
endDay      = input.int(31, "End Day",      inline="2")

// Combine month and day into a single composite value for comparison
// This creates a value like 315 for March 15, or 410 for April 10
// This ensures dates are compared sequentially, so the order of days and months is respected
int currentDate = month(time) * 100 + dayofmonth(time)
int startDate = startMonth * 100 + startDay
int endDate = endMonth * 100 + endDay

// Prepare tracking variables
var int startIndex = na
var float startingPrice = 0

// Check if the current date is in the window
bool inWindow = currentDate >= startDate and currentDate <= endDate
bool isStartTime = inWindow and na(startingPrice)
bool isEndTime = inWindow[1] and not inWindow

// Prepare array
var array<float> rateOfReturn = array.new<float>()

// Start of date range - save starting price and bar index
if (isStartTime)
    startingPrice := open
    startIndex := bar_index

// End of date range - analyze ROC
if (isEndTime)
    roc = ((close[1] - startingPrice) / startingPrice) * 100
    rateOfReturn.push(roc)
    line.new(startIndex, startingPrice, bar_index - 1, close[1], color=color.gray, width=2)
    startingPrice := na
    label.new(bar_index - 1, high[1], "ROC: " + str.tostring(roc, "#.##") + "%", color=color.red, textcolor=color.white)
    
// Display table 
var table displayTable = table.new(position.top_right, 1, 2, color.gray, color.black)
if (barstate.islastconfirmedhistory and rateOfReturn.size() > 0)
    displayTable.cell(0, 0, "Avg Return: " + str.tostring(rateOfReturn.size()) + "yr / " + str.tostring(rateOfReturn.avg(), "#.##") + "%", text_color=color.white)
    int positivePeriods = 0
    for i = 0 to rateOfReturn.size() - 1
        if (rateOfReturn.get(i) > 0)
            positivePeriods := positivePeriods + 1
    displayTable.cell(0, 1, "Chance of Gain: " + str.tostring((positivePeriods / rateOfReturn.size()) * 100, "#.##") + "%", tooltip="Positive Periods: " + str.tostring(positivePeriods) + "/" + str.tostring(rateOfReturn.size()), text_color=color.white)

// Debug plots
plot(startingPrice, "Starting Price", color=color.lime, style=plot.style_linebr)
bgcolor(isStartTime ? color.new(color.green, 50) : na)
bgcolor(isEndTime ? color.new(color.red, 50) : na, offset=-1)