#
# TD Ameritrade IP Company, Inc. (c) 2008-2021
#
input accelerationFactor = 0.02;
input accelerationLimit = 0.2;
Assert(accelerationFactor > 0, "'acceleration factor' must be positive: " + accelerationFactor);
Assert(accelerationLimit >= accelerationFactor, "'acceleration limit' (" + accelerationLimit + ") must be greater than or equal to 'acceleration factor' (" + accelerationFactor + ")");
def state = {default init, long, short};
def extreme;
def SAR;
def acc;
switch (state[1]) {
case init:
    state = state.long;
    acc = accelerationFactor;
    extreme = high;
    SAR = low;
case short:
    if (SAR[1] < high)
    then {
        state = state.long;
        acc = accelerationFactor;
        extreme = high;
        SAR = extreme[1];
    } else {
        state = state.short;
        if (low < extreme[1])
        then {
            acc = Min(acc[1] + accelerationFactor, accelerationLimit);
            extreme = low;
        } else {
            acc = acc[1];
            extreme = extreme[1];
        }
        SAR = Max(Max(high, high[1]), SAR[1] + acc * (extreme - SAR[1]));
    }
case long:
    if (SAR[1] > low)
    then {
        state = state.short;
        acc = accelerationFactor;
        extreme = low;
        SAR = extreme[1];
    } else {
        state = state.long;
        if (high > extreme[1])
        then {
            acc = Min(acc[1] + accelerationFactor, accelerationLimit);
            extreme = high;
        } else {
            acc = acc[1];
            extreme = extreme[1];
        }
        SAR = Min(Min(low, low[1]), SAR[1] + acc * (extreme - SAR[1]));
    }
}
input Count = 2;
def bear =  state[1] == state.long and state == state.short;
def bull =  state == state.long and state[1] == state.short;
def cond = bull or bear;
def dataCount = CompoundValue(1, if (cond) then dataCount[1] + 1 else dataCount[1], 0);
plot parSAR =  if HighestAll(dataCount) - dataCount <= Count - 1 then SAR else Double.NaN;
parSAR.SetPaintingStrategy(PaintingStrategy.POINTS);
parSAR.SetDefaultColor(GetColor(5));
input alerts = yes;
Alert(alerts and bear, "BEAR", Alert.ONCE, Sound.Bell);
Alert(alerts and bull, "BULL", Alert.ONCE, Sound.Bell);
input label = yes;
def lastbullbear = if bull then 1 else if bear then -1 else lastbullbear[1];
AddLabel(label and lastbullbear == 1, "Bull" , Color.GREEN);
AddLabel(label and lastbullbear == -1, "Bear" , Color.RED);
input bubbles = yes;
AddChartBubble(bubbles and bear, parSAR, "BEAR", Color.RED);
AddChartBubble(bubbles and bull, parSAR, "BULL", Color.LIGHT_GREEN, no);