using BinanceExchange.API.Models.Response; public static class Patterns{ public static bool GetTGOR(List responses, int curIndex){ if(curIndex < 10){ return false; } int greenCount =0; for(int i=curIndex-4; i <= curIndex; i++){ if(responses[i].Close < responses[i].Open){ if(greenCount > 2){ //Red after 3 greens int bullRunFlag = 0; //This is an abomniation if(responses[i-1].Close > responses[i-2].Close){ bullRunFlag++; } if(responses[i-2].Close > responses[i-3].Close){ bullRunFlag++; } if(responses[i-3].Close > responses[i-4].Close){ bullRunFlag++; } if(responses[i-4].Close > responses[i-5].Close){ bullRunFlag++; } if(responses[i-5].Close > responses[i-6].Close){ bullRunFlag++; } if(bullRunFlag > 2 && responses[i-1].Close > responses[i-1].Open){//It was a bull run return true; } } greenCount =0; }else{ greenCount++; } } return false; } public static int GetThreeWhiteSoldiers(List responses, int curIndex){ if(curIndex < 10){ return 0; } KlineCandleStickResponse candle1 = responses[curIndex]; KlineCandleStickResponse candle2 = responses[curIndex-1]; KlineCandleStickResponse candle3 = responses[curIndex-2]; bool isAllGreen = candle1.isGreen() && candle2.isGreen() && candle3.isGreen(); //LP:using average shadow is a bad idea, check each shadow // float averageShadowRatio = (candle1.getShadowRatio() + candle2.getShadowRatio() + candle3.getShadowRatio())/3f; bool areSoldiers = AreAllSolid([candle1,candle2, candle3],0.6f); bool areSoldiersThin = AreAllSolid([candle1,candle2, candle3], 0.4f); bool areSameSize = AreSameCandleSizes([candle1,candle2,candle3]); if(isAllGreen && areSoldiers && areSameSize){ //Best return 3; }else if(isAllGreen&& areSoldiersThin && areSameSize){ //Not strong return 2; }else if(isAllGreen){ //Meh return 1; } return 0; } public static int GetThreeBlackCrows(List responses, int curIndex){ if(curIndex < 10){ return 0; } KlineCandleStickResponse candle1 = responses[curIndex]; KlineCandleStickResponse candle2 = responses[curIndex-1]; KlineCandleStickResponse candle3 = responses[curIndex-2]; bool isAllRed = !candle1.isGreen() && !candle2.isGreen() && !candle3.isGreen(); //LP:using average shadow is a bad idea, check each shadow // float averageShadowRatio = (candle1.getShadowRatio() + candle2.getShadowRatio() + candle3.getShadowRatio())/3f; bool areSoldiers = AreAllSolid([candle1,candle2, candle3],0.6f); bool areSoldiersThin = AreAllSolid([candle1,candle2, candle3], 0.4f); bool areSameSize = AreSameCandleSizes([candle1,candle2,candle3]); if(isAllRed && areSoldiers && areSameSize){ //Best return 3; }else if(isAllRed&& areSoldiersThin && areSameSize){ //Not strong return 2; }else if(isAllRed){ //Meh return 1; } return 0; } public static bool AreSameCandleSizes(List responses, float tolerance= 0.5f){ float totalHeight = 0; foreach(KlineCandleStickResponse response in responses){ totalHeight+= response.getCandleLength(); } float avgHeight = totalHeight / (float)responses.Count; foreach(KlineCandleStickResponse response in responses){ float diff = Math.Abs(avgHeight - response.getCandleLength()); if(diff > tolerance){ return false; //One failed to match size } } return true; } public static bool AreAllSolid(List responses, float tolerance= 0.75f){ foreach(KlineCandleStickResponse response in responses){ if(response.getShadowRatio() < tolerance){ return false; } } return true; } public static bool isHammer(KlineCandleStickResponse response, float bodyToShadowRatio = 0.3f){ // Check if the candle has a small body compared to total length float bodyLength = response.getCandleLength(); float totalLength = response.getTotalLength(); // Body should be small compared to total length if (bodyLength / totalLength > bodyToShadowRatio) { return false; } // Lower shadow should be at least twice the body length float lowerShadow = (float)Math.Min(response.Open, response.Close) - (float)response.Low; if (lowerShadow < bodyLength * 2) { return false; } // Upper shadow should be minimal (less than 10% of total length) float upperShadow = (float)(response.High - Math.Max(response.Open, response.Close)); if (upperShadow > totalLength * 0.1) { return false; } return true; } public static bool isInverseHammer(KlineCandleStickResponse response, float bodyToShadowRatio = 0.3f){ // Check if the candle has a small body compared to total length float bodyLength = response.getCandleLength(); float totalLength = response.getTotalLength(); // Body should be small compared to total length if (bodyLength / totalLength > bodyToShadowRatio) { return false; } // Upper shadow should be at least twice the body length float upperShadow = (float)response.High - (float)Math.Max(response.Open, response.Close); if (upperShadow < bodyLength * 2) { return false; } // Lower shadow should be minimal (less than 10% of total length) float lowerShadow = (float)Math.Min(response.Open, response.Close) - (float)response.Low; if (lowerShadow > totalLength * 0.1) { return false; } return true; } }