214 lines
7.3 KiB
C#
214 lines
7.3 KiB
C#
using SignalsTest;
|
|
|
|
public static class Confirmations
|
|
{
|
|
public static int GetTWSConfirmation(List<TAReport> reports, int i)
|
|
{
|
|
int TWSHeightIncrement = 0;
|
|
|
|
if (i > 22)
|
|
{
|
|
bool hasCrossedST = false;
|
|
bool hasCrossedMA = false;
|
|
for (int z = 0; z < 20; z++)
|
|
{
|
|
if (!reports[i - z].STUp && reports[i].STUp)
|
|
{
|
|
hasCrossedST = true;
|
|
}
|
|
|
|
if (reports[i - z].SMA20 < reports[i - z].Open && reports[i].SMA20 > reports[i].Open)
|
|
{
|
|
hasCrossedMA = true;
|
|
}
|
|
}
|
|
|
|
if (hasCrossedMA) TWSHeightIncrement += 1;
|
|
if (hasCrossedST) TWSHeightIncrement += 1;
|
|
}
|
|
|
|
return TWSHeightIncrement;
|
|
}
|
|
|
|
public static int GetTBCConfirmation(List<TAReport> reports, int i)
|
|
{
|
|
int HeightIncrement = 0;
|
|
|
|
if (i > 22)
|
|
{
|
|
bool hasCrossedST = false;
|
|
bool hasCrossedMA = false;
|
|
for (int z = 0; z < 20; z++)
|
|
{
|
|
if (reports[i - z].STUp && !reports[i].STUp)
|
|
{
|
|
hasCrossedST = true;
|
|
}
|
|
|
|
if (reports[i - z].SMA20 > reports[i - z].Open && reports[i].SMA20 < reports[i].Open)
|
|
{
|
|
hasCrossedMA = true;
|
|
}
|
|
}
|
|
|
|
if (hasCrossedMA) HeightIncrement += 1;
|
|
if (hasCrossedST) HeightIncrement += 1;
|
|
}
|
|
|
|
return HeightIncrement;
|
|
}
|
|
|
|
public static List<decimal> GetSupportiveLevels(List<TAReport> reports, float tolerance = 0.1f, int steps = 5, string SMA="SMA20"){
|
|
List<decimal> allSups = new List<decimal>();
|
|
|
|
decimal highest = 0;
|
|
decimal lowest = 1000000000000000;
|
|
|
|
int lastMACross = 0;
|
|
for(int k =0; k < reports.Count; k++){
|
|
if(highest < reports[k].candle.High){
|
|
highest = reports[k].candle.High;
|
|
}
|
|
|
|
if(lowest > reports[k].candle.Low){
|
|
lowest = reports[k].candle.Low;
|
|
}
|
|
|
|
if(k <steps * 3){continue;} //not enough history
|
|
|
|
bool MATopNow = decimal.Parse(Utils.GetPropByName(reports[k], SMA).ToString() ?? "0") > reports[k].candle.High;
|
|
bool MATopBefore = decimal.Parse(Utils.GetPropByName(reports[k-1], SMA).ToString() ?? "0") > reports[k-1].candle.High;
|
|
|
|
bool MACrossed = MATopBefore!=MATopNow;
|
|
if(!MACrossed){continue;}//No cross
|
|
if(lastMACross == 0){
|
|
lastMACross = k;
|
|
continue; //First Cross
|
|
}
|
|
|
|
//Get lowest point between this and last cross
|
|
decimal lowestInPeriod = 1000000;
|
|
for(int i=lastMACross; i < k; i++ ){
|
|
if(reports[i].candle.Low < lowestInPeriod){
|
|
decimal candleBot = reports[i].candle.Open < reports[i].candle.Close ? reports[i].candle.Open : reports[i].candle.Close;
|
|
|
|
lowestInPeriod=candleBot;
|
|
}
|
|
}
|
|
|
|
allSups.Add(lowestInPeriod);
|
|
}
|
|
|
|
List<decimal> formattedSups = new List<decimal>();
|
|
decimal range = highest-lowest;
|
|
foreach(decimal sup in allSups){
|
|
formattedSups.Add(sup);
|
|
}
|
|
|
|
return formattedSups;
|
|
}
|
|
|
|
public static List<decimal> GetResistanceLevels(List<TAReport> reports, float tolerance = 0.1f, int steps = 5, string SMA="SMA20"){
|
|
List<decimal> allResistances = new List<decimal>();
|
|
|
|
decimal highest = 0;
|
|
decimal lowest = 1000000000000000;
|
|
|
|
int lastMACross = 0;
|
|
for(int k =0; k < reports.Count; k++){
|
|
if(highest < reports[k].candle.High){
|
|
highest = reports[k].candle.High;
|
|
}
|
|
|
|
if(lowest > reports[k].candle.Low){
|
|
lowest = reports[k].candle.Low;
|
|
}
|
|
|
|
if(k <steps * 3){continue;} //not enough history
|
|
|
|
bool MATopNow = decimal.Parse(Utils.GetPropByName(reports[k], SMA).ToString() ?? "0") > reports[k].candle.High;
|
|
bool MATopBefore = decimal.Parse(Utils.GetPropByName(reports[k-1], SMA).ToString() ?? "0") > reports[k-1].candle.High;
|
|
|
|
bool MACrossed = MATopBefore!=MATopNow;
|
|
if(!MACrossed){continue;}//No cross
|
|
if(lastMACross == 0){
|
|
lastMACross = k;
|
|
continue; //First Cross
|
|
}
|
|
|
|
//Get lowest point between this and last cross
|
|
decimal highestInPeriod = 0;
|
|
for(int i=lastMACross; i < k; i++ ){
|
|
if(reports[i].candle.High > highestInPeriod){
|
|
decimal candleTop = reports[i].candle.Open > reports[i].candle.Close ? reports[i].candle.Open : reports[i].candle.Close;
|
|
highestInPeriod=candleTop;
|
|
}
|
|
}
|
|
|
|
allResistances.Add(highestInPeriod);
|
|
}
|
|
|
|
List<decimal> formattedResistances = new List<decimal>();
|
|
decimal range = highest-lowest;
|
|
foreach(decimal resistance in allResistances){
|
|
formattedResistances.Add(resistance);
|
|
}
|
|
|
|
return formattedResistances;
|
|
}
|
|
|
|
public static float GetRelativeVolumeIndex(List<TAReport> reports, int currentIndex){
|
|
decimal totalVolume = 0;
|
|
foreach(TAReport report in reports){
|
|
totalVolume+=report.candle.Volume;
|
|
}
|
|
|
|
float avgVol = (float)totalVolume/(float)reports.Count;
|
|
|
|
return (float)reports[currentIndex].candle.Volume / avgVol;
|
|
}
|
|
|
|
public static bool IsBullFlag(List<TAReport> reports, int currentIndex, int lookbackPeriod = 20)
|
|
{
|
|
if (currentIndex < lookbackPeriod) return false;
|
|
|
|
// Find the flagpole
|
|
decimal highestPoint = 0;
|
|
decimal lowestPoint = decimal.MaxValue;
|
|
int highestPointIndex = 0;
|
|
|
|
// Look for a sharp upward move (flagpole)
|
|
for (int i = currentIndex - lookbackPeriod; i <= currentIndex; i++)
|
|
{
|
|
if (reports[i].candle.High > highestPoint)
|
|
{
|
|
highestPoint = reports[i].candle.High;
|
|
highestPointIndex = i;
|
|
}
|
|
if (reports[i].candle.Low < lowestPoint)
|
|
{
|
|
lowestPoint = reports[i].candle.Low;
|
|
}
|
|
}
|
|
|
|
// Calculate flagpole height
|
|
decimal flagpoleHeight = highestPoint - lowestPoint;
|
|
if (flagpoleHeight / lowestPoint < 0.03m) return false; // Minimum 3% move
|
|
|
|
// Check for consolidation pattern after flagpole
|
|
decimal upperTrendStart = highestPoint;
|
|
decimal lowerTrendStart = reports[highestPointIndex].candle.Low;
|
|
|
|
decimal upperTrendEnd = reports[currentIndex].candle.High;
|
|
decimal lowerTrendEnd = reports[currentIndex].candle.Low;
|
|
|
|
// Verify parallel downward sloping trend lines
|
|
bool isDownwardSloping = upperTrendEnd < upperTrendStart && lowerTrendEnd < lowerTrendStart;
|
|
bool isParallel = Math.Abs((upperTrendEnd - upperTrendStart) - (lowerTrendEnd - lowerTrendStart)) / flagpoleHeight < 0.2m;
|
|
|
|
// Volume should typically decrease during flag formation
|
|
bool isVolumeDecreasing = reports[currentIndex].candle.Volume < reports[highestPointIndex].candle.Volume;
|
|
|
|
return isDownwardSloping && isParallel && isVolumeDecreasing;
|
|
}
|
|
} |