-- More information about this indicator can be found at:
-- http://fxcodebase.com/code/viewtopic.php?f=17&t=26414
-- Id: 7926

--+------------------------------------------------------------------+
--|                               Copyright © 2018, Gehtsoft USA LLC |
--|                                            http://fxcodebase.com |
--+------------------------------------------------------------------+
--|                                 Support our efforts by donating  |
--|                                  Paypal : https://goo.gl/9Rj74e  |
--|                                 Patreon : https://goo.gl/GdXWeN  |
--|                    BitCoin : 15VCJTLaz12Amr7adHSBtL9v8XomURo9RF  |
--|               BitCoin Cash : 1BEtS465S3Su438Kc58h2sqvVvHK9Mijtg  |
--|           Ethereum : 0x8C110cD61538fb6d7A2B47858F0c0AaBd663068D  |
--|                   LiteCoin : LLU8PSY2vsq7B9kRELLZQcKf5nJQrdeqwD  |
--+------------------------------------------------------------------+

function Init()
    indicator:name("TAT oscillator");
    indicator:description("TAT oscillator");
    indicator:requiredSource(core.Bar);
    indicator:type(core.Oscillator);

    indicator.parameters:addGroup("Calculation");
    indicator.parameters:addInteger("MACD_Fast_Period", "MACD fast period", "", 12);
    indicator.parameters:addInteger("MACD_Slow_Period", "MACD slow period", "", 26);
    indicator.parameters:addInteger("MACD_Signal_Period", "MACD signal period", "", 9);
    indicator.parameters:addDouble("SAR_Step", "SAR step", "", 0.02);
    indicator.parameters:addDouble("SAR_Max", "SAR maximum", "", 0.2);
    indicator.parameters:addDouble("TAT_MACD_Mult", "TAT MACD multiplier", "", 66.67);
    indicator.parameters:addDouble("TAT_SAR_Mult", "TAT SAR multiplier", "", 6.67);
    indicator.parameters:addInteger("TAT_Signal_Period", "TAT signal period", "", 12);
    indicator.parameters:addDouble("Overbought_Level", "Overbought level", "", 10);
    indicator.parameters:addDouble("Oversold_Level", "Oversold level", "", -10);

    indicator.parameters:addGroup("Style");
    indicator.parameters:addColor("MainClr", "Main color", "Main color", core.rgb(0, 255, 0));
    indicator.parameters:addColor("SignalClr", "Signal color", "Signal color", core.rgb(255, 0, 0));
    indicator.parameters:addColor("LevelsClr", "Levels color", "Levels color", core.rgb(128, 128, 128));
end

local first;
local source = nil;
local MACD_Fast_Period;
local MACD_Slow_Period;
local MACD_Signal_Period;
local SAR_Step;
local SAR_Max;
local TAT_MACD_Mult;
local TAT_SAR_Mult;
local TAT_Signal_Period;
local TAT=nil;
local Signal=nil;
local FastEMA, SlowEMA;
local MACD_Main;
local MACD_Signal;
local IsLong;
local af, extreme, sar;
local TAT_EMA;

function Prepare(nameOnly)
    source = instance.source;
    MACD_Fast_Period=instance.parameters.MACD_Fast_Period;
    MACD_Slow_Period=instance.parameters.MACD_Slow_Period;
    MACD_Signal_Period=instance.parameters.MACD_Signal_Period;
    SAR_Step=instance.parameters.SAR_Step;
    SAR_Max=instance.parameters.SAR_Max;
    TAT_MACD_Mult=instance.parameters.TAT_MACD_Mult;
    TAT_SAR_Mult=instance.parameters.TAT_SAR_Mult;
    TAT_Signal_Period=instance.parameters.TAT_Signal_Period;
    local name = profile:id() .. "(" .. source:name() .. ", " .. instance.parameters.MACD_Fast_Period .. ", " .. instance.parameters.MACD_Slow_Period .. ", " .. instance.parameters.MACD_Signal_Period .. ", " .. instance.parameters.SAR_Step .. ", " .. instance.parameters.SAR_Max .. ", " .. instance.parameters.TAT_MACD_Mult .. ", " .. instance.parameters.TAT_SAR_Mult .. ", " .. instance.parameters.TAT_Signal_Period .. ")";
    instance:name(name);
    if nameOnly then
        return;
    end
    
    FastEMA = core.indicators:create("EMA", source.close, MACD_Fast_Period);
    SlowEMA = core.indicators:create("EMA", source.close, MACD_Slow_Period);
    MACD_Main = instance:addInternalStream(0, 0);
    MACD_Signal = core.indicators:create("EMA", MACD_Main, MACD_Signal_Period);
	
	first = MACD_Signal.DATA:first();
	
    IsLong = instance:addInternalStream(0, 0);
    af = instance:addInternalStream(0, 0);
    extreme = instance:addInternalStream(0, 0);
    sar = instance:addInternalStream(0, 0);
    TAT = instance:addStream("TAT", core.Bar, name .. ".TAT", "TAT", instance.parameters.MainClr, first);
    TAT:setPrecision(math.max(2, instance.source:getPrecision()));
    TAT_EMA = core.indicators:create("EMA", TAT, TAT_Signal_Period);
    Signal = instance:addStream("Signal", core.Line, name .. ".Signal", "Signal", instance.parameters.SignalClr, first);
    Signal:setPrecision(math.max(2, instance.source:getPrecision()));
    TAT:addLevel(0, core.LINE_DASH, 1, instance.parameters.LevelsClr);
    TAT:addLevel(instance.parameters.Overbought_Level, core.LINE_DASH, 1, instance.parameters.LevelsClr);
    TAT:addLevel(instance.parameters.Oversold_Level, core.LINE_DASH, 1, instance.parameters.LevelsClr);
end

function Update(period, mode)
   
    FastEMA:update(mode);
    SlowEMA:update(mode);
	
	if  period<math.max(FastEMA.DATA:first(),SlowEMA.DATA:first() ) then
	return;
	end
    MACD_Main[period]=FastEMA.DATA[period]-SlowEMA.DATA[period];
    MACD_Signal:update(mode);
	
	if (period<first) then
	return;
	end
	
    IsLong[period] = IsLong[period-1];
    af[period] = af[period-1];
    extreme[period] = extreme[period-1];
    sar[period] = sar[period-1]+af[period-1]*(extreme[period-1]-sar[period-1]);
   if IsLong[period-1] == 1 then
			 if source.low[period]<sar[period] then
			  IsLong[period] = 0;
			  af[period] = SAR_Step;
			  sar[period] = extreme[period-1];
			  extreme[period] = source.low[period];
			 else
			  if extreme[period-1]<source.high[period] then
			   extreme[period] = source.high[period];
			   af[period] = af[period-1]+SAR_Step;
			   if af[period]>SAR_Max then
				af[period] = SAR_Max;
			   end
			  end
			 end 
    else 
			 if source.high[period]>sar[period] then
			  IsLong[period] = 1;
			  af[period] = SAR_Step;
			  sar[period] = extreme[period-1];
			  extreme[period] = source.high[period];
			 else
			  if extreme[period-1]>source.low[period] then
			   extreme[period] = source.low[period];
			   af[period] = af[period-1]+SAR_Step;
			   if af[period]>SAR_Max then
				af[period] = SAR_Max;
			   end
			  end
			 end
   
   end
   
    local TAT_SAR = 0;
    local TAT_MACD = 0;
		if sar[period]~=0 then
		 TAT_SAR = (source.close[period]-sar[period])/sar[period];
		end
    TAT_MACD = (MACD_Main[period]-MACD_Signal.DATA[period])/source.close[period];
    TAT[period] = 50*(TAT_SAR*TAT_SAR_Mult+TAT_MACD*TAT_MACD_Mult);
    TAT_EMA:update(mode);
    Signal[period] = TAT_EMA.DATA[period];
   
    
end

