-- Id: 7652 -- More information about this indicator can be found at: -- http://fxcodebase.com/ --+------------------------------------------------------------------+ --| Copyright © 2019, 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() strategy:name("Candle patterns signal"); strategy:setTag("NonOptimizableParameters", "Email,SendEmail,SoundFile,RecurrentSound,PlaySound,ShowAlert"); strategy:description("Candle patterns signal"); strategy.parameters:addInteger("EQ", "Maximum of pips distance between equal prices", "", 1, 0, 100); strategy.parameters:addBoolean("PAT_DOUBLE_INSIDE", "Enable Double Inside", "", true); strategy.parameters:addBoolean("PAT_INSIDE", "Enable Inside", "", true); strategy.parameters:addBoolean("PAT_OUTSIDE", "Enable Outside", "", true); strategy.parameters:addBoolean("PAT_PINUP", "Enable Pin Up", "", true); strategy.parameters:addBoolean("PAT_PINDOWN", "Enable Pin Down", "", true); strategy.parameters:addBoolean("PAT_PPRUP", "Enable Pivot Point Reversal Up", "", true); strategy.parameters:addBoolean("PAT_PPRDN", "Enable Pivot Point Reversal Down", "", true); strategy.parameters:addBoolean("PAT_DBLHC", "Enable Double Bar Low With A Higher Close", "", true); strategy.parameters:addBoolean("PAT_DBHLC", "Enable Double Bar High With A Lower Close", "", true); strategy.parameters:addBoolean("PAT_CPRU", "Enable Close Price Reversal Up", "", true); strategy.parameters:addBoolean("PAT_CPRD", "Enable Close Price Reversal Down", "", true); strategy.parameters:addBoolean("PAT_NB", "Enable Neutral Bar", "", true); strategy.parameters:addBoolean("PAT_NB2", "Enable 2 Neutral Bars", "", true); strategy.parameters:addBoolean("PAT_FBU", "Enable Force Bar Up", "", true); strategy.parameters:addBoolean("PAT_FBD", "Enable Force Bar Down", "", true); strategy.parameters:addBoolean("PAT_MB", "Enable Mirror Bar", "", true); strategy.parameters:addBoolean("PAT_HAMMER", "Enable Hammer", "", true); strategy.parameters:addBoolean("PAT_SHOOTSTAR", "Enable Shooting Star", "", true); strategy.parameters:addBoolean("PAT_EVSTAR", "Enable Evening Star", "", true); strategy.parameters:addBoolean("PAT_MORNSTAR", "Enable Morning Star", "", true); strategy.parameters:addBoolean("PAT_EVDJSTAR", "Enable Evening Doji Star", "", true); strategy.parameters:addBoolean("PAT_MORNDJSTAR", "Enable Morning Doji Star", "", true); strategy.parameters:addBoolean("PAT_BEARHARAMI", "Enable Bearish Harami", "", true); strategy.parameters:addBoolean("PAT_BEARHARAMICROSS", "Enable Bearish Harami Cross", "", true); strategy.parameters:addBoolean("PAT_BULLHARAMI", "Enable Bullish Harami", "", true); strategy.parameters:addBoolean("PAT_BULLHARAMICROSS", "Enable Bullish Harami Cross", "", true); strategy.parameters:addBoolean("PAT_DARKCLOUD", "Enable Dark Cloud Cover", "", true); strategy.parameters:addBoolean("PAT_DOJISTAR", "Enable Doji Star", "", true); strategy.parameters:addBoolean("PAT_ENGBEARLINE", "Enable Engulfing Bearish Line", "", true); strategy.parameters:addBoolean("PAT_ENGBULLLINE", "Enable Engulfing Bullish Line", "", true); strategy.parameters:addString("Period", "Time frame", "", "m1"); strategy.parameters:setFlag("Period", core.FLAG_PERIODS); strategy.parameters:addBoolean("ShowAlert", "Show Alert", "", true); strategy.parameters:addBoolean("PlaySound", "Play Sound", "", false); strategy.parameters:addFile("SoundFile", "Sound file", "", ""); end local SoundFile; local gSource = nil; local PAT_NONE = 0; local PAT_DOUBLE_INSIDE = 1; local PAT_INSIDE = 2; local PAT_OUTSIDE = 4; local PAT_PINUP = 5; local PAT_PINDOWN = 6; local PAT_PPRUP = 7; local PAT_PPRDN = 8; local PAT_DBLHC = 9; local PAT_DBHLC = 10; local PAT_CPRU = 11; local PAT_CPRD = 12; local PAT_NB = 13; local PAT_FBU = 14; local PAT_FBD = 15; local PAT_MB = 16; local PAT_HAMMER=17; local PAT_SHOOTSTAR=18; local PAT_EVSTAR=19; local PAT_MORNSTAR=20; local PAT_BEARHARAMI=21; local PAT_BEARHARAMICROSS=22; local PAT_BULLHARAMI=23; local PAT_BULLHARAMICROSS=24; local PAT_DARKCLOUD=25; local PAT_DOJISTAR=26; local PAT_ENGBEARLINE=27; local PAT_ENGBULLLINE=28; local PAT_EVDJSTAR=29; local PAT_MORNDJSTAR=30; local PAT_NB2 = 31; local EQ; function DecodePattern(pattern) if pattern == PAT_NONE then return nil, nil, nil, nil; elseif pattern == PAT_DOUBLE_INSIDE and instance.parameters:getBoolean("PAT_DOUBLE_INSIDE")==true then return "DblIn", "Double Inside", true, 3; elseif pattern == PAT_INSIDE and instance.parameters:getBoolean("PAT_INSIDE")==true then return "In", "Inside", true, 2; elseif pattern == PAT_OUTSIDE and instance.parameters:getBoolean("PAT_OUTSIDE")==true then return "Out", "Outside", true, 2; elseif pattern == PAT_PINUP and instance.parameters:getBoolean("PAT_PINUP")==true then return "PnUp", "Pin Up", true, 2; elseif pattern == PAT_PINDOWN and instance.parameters:getBoolean("PAT_PINDOWN")==true then return "PnDn", "Pin Down", false, 2; elseif pattern == PAT_PPRUP and instance.parameters:getBoolean("PAT_PPRUP")==true then return "PPRU", "Pivot Point Reversal Up", false, 3; elseif pattern == PAT_PPRDN and instance.parameters:getBoolean("PAT_PPRDN")==true then return "PPRD", "Pivot Point Reversal Down", true, 3; elseif pattern == PAT_DBLHC and instance.parameters:getBoolean("PAT_DBLHC")==true then return "DBLHC", "Double Bar Low With A Higher Close", false, 2; elseif pattern == PAT_DBHLC and instance.parameters:getBoolean("PAT_DBHLC")==true then return "DBHLC", "Double Bar High With A Lower Close", true, 2; elseif pattern == PAT_CPRU and instance.parameters:getBoolean("PAT_CPRU")==true then return "CPRU", "Close Price Reversal Up", false, 3; elseif pattern == PAT_CPRD and instance.parameters:getBoolean("PAT_CPRD")==true then return "CPRD", "Close Price Reversal Down", true, 3; elseif pattern == PAT_NB and instance.parameters:getBoolean("PAT_NB")==true then return "NB", "Neutral Bar", true, 1; elseif pattern == PAT_FBU and instance.parameters:getBoolean("PAT_FBU")==true then return "FBU", "Force Bar Up", false, 1; elseif pattern == PAT_FBD and instance.parameters:getBoolean("PAT_FBD")==true then return "FBD", "Force Bar Down", true, 1; elseif pattern == PAT_MB and instance.parameters:getBoolean("PAT_MB")==true then return "MB", "Mirror Bar", true, 2; elseif pattern == PAT_HAMMER and instance.parameters:getBoolean("PAT_HAMMER")==true then return "HAMMER", "Hammer Pattern", true, 1; elseif pattern == PAT_SHOOTSTAR and instance.parameters:getBoolean("PAT_SHOOTSTAR")==true then return "SHOOTSTAR", "Shooting Star", true, 1; elseif pattern == PAT_EVSTAR and instance.parameters:getBoolean("PAT_EVSTAR")==true then return "EVSTAR", "Evening Star", true, 3; elseif pattern == PAT_MORNSTAR and instance.parameters:getBoolean("PAT_MORNSTAR")==true then return "MORNSTAR", "Morning Star", true, 3; elseif pattern == PAT_EVDJSTAR and instance.parameters:getBoolean("PAT_EVDJSTAR")==true then return "EVDJSTAR", "Evening Doji Star", true, 3; elseif pattern == PAT_MORNDJSTAR and instance.parameters:getBoolean("PAT_MORNDJSTAR")==true then return "MORNDJSTAR", "Morning Doji Star", true, 3; elseif pattern == PAT_BEARHARAMI and instance.parameters:getBoolean("PAT_BEARHARAMI")==true then return "BEARHARAMI", "Bearish Harami", true, 2; elseif pattern == PAT_BEARHARAMICROSS and instance.parameters:getBoolean("PAT_BEARHARAMICROSS")==true then return "BEARHARAMICROSS", "Bearish Harami Cross", true, 2; elseif pattern == PAT_BULLHARAMI and instance.parameters:getBoolean("PAT_BULLHARAMI")==true then return "BULLHARAMI", "Bullish Harami", true, 2; elseif pattern == PAT_BULLHARAMICROSS and instance.parameters:getBoolean("PAT_BULLHARAMICROSS")==true then return "BULLHARAMICROSS", "Bullish Harami Cross", true, 2; elseif pattern == PAT_DARKCLOUD and instance.parameters:getBoolean("PAT_DARKCLOUD")==true then return "DARKCLOUD", "Dark Cloud Cover", true, 2; elseif pattern == PAT_DOJISTAR and instance.parameters:getBoolean("PAT_DOJISTAR")==true then return "DOJISTAR", "Doji Star", true, 2; elseif pattern == PAT_ENGBEARLINE and instance.parameters:getBoolean("PAT_ENGBEARLINE")==true then return "ENGBEARLINE", "Engulfing Bearish Line", true, 2; elseif pattern == PAT_ENGBULLLINE and instance.parameters:getBoolean("PAT_ENGBULLLINE")==true then return "ENGBULLLINE", "Engulfing Bullish Line", true, 2; elseif pattern == PAT_NB2 and instance.parameters:getBoolean("PAT_NB2")==true then return "NB2", "2 Neutral Bar", true, 2; else return nil, nil, nil, nil; end end function RegisterPattern(period, pattern) local short, long, up, length; local price; short, long, up, length = DecodePattern(pattern); if length~=nil then if up then ExtSignal(gSource.high, period, long, SoundFile); else ExtSignal(gSource.low, period, long, SoundFile); end end end function Cmp(price1, price2) if math.abs(price1 - price2) < EQ then return 0; elseif price1 > price2 then return 1; else return -1; end end function Prepare() ShowAlert = instance.parameters.ShowAlert; if instance.parameters.PlaySound then SoundFile = instance.parameters.SoundFile; else SoundFile = nil; end assert(not(PlaySound) or (PlaySound and SoundFile ~= ""), "Sound file must be specified"); ExtSetupSignal(profile:id() .. ":", ShowAlert); assert(instance.parameters.Period ~= "t1", "Can't be applied on ticks!"); gSource = ExtSubscribe(1, nil, instance.parameters.Period, true, "bar"); EQ = instance.parameters.EQ * gSource:pipSize(); local name = profile:id() .. "(" .. instance.bid:instrument() .. "(" .. instance.parameters.Period .. ")" .. ")"; instance:name(name); end local O, H, L, C, T, B, BL, US, LS; local O1, H1, L1, C1, T1, B1, BL1, US1, LS1; local O2, H2, L2, C2, T2, B2, BL2, US2, LS2; -- when tick source is updated function ExtUpdate(id, source, period) if period <= 3 then return ; end O=gSource.open[period]; H=gSource.high[period]; L=gSource.low[period]; C=gSource.close[period]; T=math.max(O,C); B=math.min(O,C); BL=T-B; US=H-T; LS=B-L; O1=gSource.open[period-1]; H1=gSource.high[period-1]; L1=gSource.low[period-1]; C1=gSource.close[period-1]; T1=math.max(O1,C1); B1=math.min(O1,C1); BL1=T1-B1; US1=H1-T1; LS1=B1-L1; O2=gSource.open[period-2]; H2=gSource.high[period-2]; L2=gSource.low[period-2]; C2=gSource.close[period-2]; T2=math.max(O2,C2); B2=math.min(O2,C2); BL2=T2-B2; US2=H2-T2; LS2=B2-L2; -- 1 - candle patterns if Cmp(O, C) == 0 and US > math.max(EQ * 4, gSource:pipSize() * 4) and LS > math.max(EQ * 4, gSource:pipSize() * 4) then RegisterPattern(period, PAT_NB); end if C == H then RegisterPattern(period, PAT_FBU); end if C == L then RegisterPattern(period, PAT_FBD); end if US <= math.max(EQ, gSource:pipSize()) and LS>2.*BL then RegisterPattern(period, PAT_HAMMER); end if LS <= math.max(EQ, gSource:pipSize()) and US>2.*BL then RegisterPattern(period, PAT_SHOOTSTAR); end -- 2 - candle patterns if Cmp(H, H1) < 0 and Cmp(L, L1) > 0 then RegisterPattern(period, PAT_INSIDE); end if Cmp(H, H1) > 0 and Cmp(L, L1) < 0 then RegisterPattern(period, PAT_OUTSIDE); end if Cmp(H, H1) == 0 and Cmp(C, C1) < 0 and Cmp(L, L1) <= 0 then RegisterPattern(period, PAT_DBHLC); end if Cmp(L, L1) == 0 and Cmp(C, C1) > 0 and Cmp(H, H1) >= 0 then RegisterPattern(period, PAT_DBLHC); end if Cmp(BL1, BL) == 0 and Cmp(O1, C) == 0 then RegisterPattern(period, PAT_MB); end if Cmp(H,H1)<0 and Cmp(L,L1)>0 and Cmp(C1,O1)>0 and Cmp(C,O)<0 and Cmp(BL1,BL)>0 and Cmp(C1,O)>0 and Cmp(O1,C)<0 then RegisterPattern(period, PAT_BEARHARAMI); end if Cmp(H,H1)<0 and Cmp(L,L1)>0 and Cmp(C1,O1)>0 and Cmp(O,C)==0 and Cmp(BL1,BL)>0 and Cmp(C1,O)>0 and Cmp(O1,C)<0 then RegisterPattern(period, PAT_BEARHARAMICROSS); end if Cmp(H,H1)<0 and Cmp(L,L1)>0 and Cmp(C1,O1)<0 and Cmp(C,O)>0 and Cmp(BL1,BL)>0 and Cmp(C1,O)<0 and Cmp(O1,C)>0 then RegisterPattern(period, PAT_BULLHARAMI); end if Cmp(H,H1)<0 and Cmp(L,L1)>0 and Cmp(C1,O1)<0 and Cmp(O,C)==0 and Cmp(BL1,BL)>0 and Cmp(C1,O)<0 and Cmp(O1,C)>0 then RegisterPattern(period, PAT_BULLHARAMICROSS); end if Cmp(C1,O1)>0 and Cmp(C,O)<0 and Cmp(H1,O)<0 and Cmp(C,C1)<0 and Cmp(C,O1)>0 then RegisterPattern(period, PAT_DARKCLOUD); end if Cmp(O,C)==0 and ((Cmp(C1,O1)>0 and Cmp(O,H1)>0) or (Cmp(C1,O1)<0 and Cmp(O,L1)<0)) then RegisterPattern(period, PAT_DOJISTAR); end if Cmp(C1,O1)>0 and Cmp(C,O)<0 and Cmp(O,C1)>0 and Cmp(C,O1)<0 then RegisterPattern(period, PAT_ENGBEARLINE); end if Cmp(C1,O1)<0 and Cmp(C,O)>0 and Cmp(O,C1)<0 and Cmp(C,O1)>0 then RegisterPattern(period, PAT_ENGBULLLINE); end if Cmp(O, C) == 0 and US > math.max(EQ * 4, gSource:pipSize() * 4) and LS > math.max(EQ * 4, gSource:pipSize() * 4) and Cmp(O1, C1) == 0 and US1 > math.max(EQ * 4, gSource:pipSize() * 4) and LS1 > math.max(EQ * 4, gSource:pipSize() * 4) then RegisterPattern(period, PAT_NB2); end -- 3 - candle patterns if Cmp(H, H1) < 0 and Cmp(L, L1) > 0 and Cmp(H1, H2) < 0 and Cmp(L1, L2) > 0 then RegisterPattern(period, PAT_DOUBLE_INSIDE); end if Cmp(H1, H2) > 0 and Cmp(H1, H) > 0 and Cmp(L1, L2) > 0 and Cmp(L1, L) > 0 and BL1 * 2 < US1 then RegisterPattern(period, PAT_PINUP); end if Cmp(H1, H2) < 0 and Cmp(H1, H) < 0 and Cmp(L1, L2) < 0 and Cmp(L1, L) < 0 and BL1 * 2 < LS1 then RegisterPattern(period, PAT_PINDOWN); end if Cmp(H1, H2) > 0 and Cmp(H1, H) > 0 and Cmp(L1, L2) > 0 and Cmp(L1, L) > 0 and Cmp(C, L1) < 0 then RegisterPattern(period, PAT_PPRDN); end if Cmp(H1, H2) < 0 and Cmp(H1, H) < 0 and Cmp(L1, L2) < 0 and Cmp(L1, L) < 0 and Cmp(C, H1) > 0 then RegisterPattern(period, PAT_PPRUP); end if Cmp(H1, H2) < 0 and Cmp(L1, L2) < 0 and Cmp(H, H1) < 0 and Cmp(L, L1) < 0 and Cmp(C, C1) > 0 and Cmp(O, C) < 0 then RegisterPattern(period, PAT_CPRU); end if Cmp(H1, H2) > 0 and Cmp(L1, L2) > 0 and Cmp(H, H1) > 0 and Cmp(L, L1) > 0 and Cmp(C, C1) < 0 and Cmp(O, C) > 0 then RegisterPattern(period, PAT_CPRD); end if Cmp(C2,O2)>0 and Cmp(C1,O1)>0 and Cmp(C,O)<0 and Cmp(C2,O1)<0 and Cmp(BL2,BL1)>0 and Cmp(BL1,BL)<0 and Cmp(C,O2)>0 and Cmp(C,C2)<0 then RegisterPattern(period, PAT_EVSTAR); end if Cmp(C2,O2)<0 and Cmp(C1,O1)>0 and Cmp(C,O)>0 and Cmp(C2,O1)>0 and Cmp(BL2,BL1)>0 and Cmp(BL1,BL)<0 and Cmp(C,C2)>0 and Cmp(C,O2)<0 then RegisterPattern(period, PAT_MORNSTAR); end if Cmp(C2,O2)>0 and Cmp(C1,O1)==0 and Cmp(C,O)<0 and Cmp(C2,O1)<0 and Cmp(BL2,BL1)>0 and Cmp(BL1,BL)<0 and Cmp(C,O2)>0 and Cmp(C,C2)<0 then RegisterPattern(period, PAT_EVDJSTAR); end if Cmp(C2,O2)<0 and Cmp(C1,O1)==0 and Cmp(C,O)>0 and Cmp(C2,O1)>0 and Cmp(BL2,BL1)>0 and Cmp(BL1,BL)<0 and Cmp(C,C2)>0 and Cmp(C,O2)<0 then RegisterPattern(period, PAT_MORNDJSTAR); end end dofile(core.app_path() .. "\\strategies\\standard\\include\\helper.lua");