Initial commit

This commit is contained in:
Michael Schimmel
2026-01-28 09:10:52 +01:00
commit a1d2e96f8a
513 changed files with 19503 additions and 0 deletions
@@ -0,0 +1,22 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.30011.22
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HmaMitigationCount", "HmaMitigationCount\HmaMitigationCount.csproj", "{a7f42ba9-479c-418c-83b4-228416c67510}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{a7f42ba9-479c-418c-83b4-228416c67510}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{a7f42ba9-479c-418c-83b4-228416c67510}.Debug|Any CPU.Build.0 = Debug|Any CPU
{a7f42ba9-479c-418c-83b4-228416c67510}.Release|Any CPU.ActiveCfg = Release|Any CPU
{a7f42ba9-479c-418c-83b4-228416c67510}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
@@ -0,0 +1,162 @@
using cAlgo.API;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;
using System.Collections.Generic;
using System.Linq;
using System;
namespace cAlgo.Indicators
{
[Indicator(IsOverlay = true, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
public class HmaMitigationCount : Indicator
{
[Parameter("HMA Period", DefaultValue = 20, MinValue = 2)]
public int HmaPeriod { get; set; }
[Parameter("Session Close Time (UTC)", DefaultValue = "17:30")]
public TimeSpan SessionCloseTimeUtc { get; set; }
[Output("HMA", LineColor = "Orange")]
public IndicatorDataSeries HmaOutput { get; set; }
private HullMovingAverage _hma;
private Stack<double> _peakStack;
private Stack<double> _troughStack;
private int lblCnt = 0;
private int mitigatedPeaks = 0;
private int mitigatedTroughs = 0;
private int dir = 0;
private DateTime _currentSessionEndTimeUtc = DateTime.MinValue;
protected override void Initialize()
{
_hma = Indicators.HullMovingAverage(Bars.ClosePrices, HmaPeriod);
_peakStack = new Stack<double>();
_troughStack = new Stack<double>();
}
public override void Calculate(int index)
{
HmaOutput[index] = _hma.Result[index];
DateTime barOpenTime = Bars.OpenTimes[index]; // This is UTC
// --- Session Initialization (run once) ---
if (_currentSessionEndTimeUtc == DateTime.MinValue)
{
// Find the session close time for the *current* bar's day
DateTime sessionCloseToday = barOpenTime.Date.Add(SessionCloseTimeUtc);
// If the bar is already *after* today's close, the session ends *tomorrow*
if (barOpenTime >= sessionCloseToday)
{
_currentSessionEndTimeUtc = sessionCloseToday.AddDays(1);
}
// If the bar is *before* today's close, the session ends *today*
else
{
_currentSessionEndTimeUtc = sessionCloseToday;
}
}
// --- Session Check ---
// Check if the current bar has crossed the session boundary
if (barOpenTime >= _currentSessionEndTimeUtc)
{
// New session starts, clear stacks
_peakStack.Clear();
_troughStack.Clear();
//Chart.RemoveAllObjects(); // Optional: Clear old session text
// Set the *next* session end time, looping in case of market gaps (weekends)
while (barOpenTime >= _currentSessionEndTimeUtc)
{
_currentSessionEndTimeUtc = _currentSessionEndTimeUtc.AddDays(1);
}
}
// Stop logic from running on the forming bar
if (IsLastBar)
{
return;
}
// We need at least 3 bars to identify a peak/trough at index - 1
if (index < 2)
{
return;
}
// --- 1. Identify new peaks/troughs at index - 1 AND check mitigation ---
// All HMA values are now based on closed bars (index, index-1, index-2).
double prevHma = _hma.Result[index - 1];
double prevHma2 = _hma.Result[index - 2];
double currentHma = _hma.Result[index];
// A peak at index-1
bool isPeak = (prevHma > prevHma2) && (prevHma > currentHma);
// A trough at index-1
bool isTrough = (prevHma < prevHma2) && (prevHma < currentHma);
if (isPeak)
{
// New Peak: Check if it mitigates any *previous Peaks*
if( dir < 0 )
{
mitigatedPeaks = 0;
lblCnt++;
}
// A new peak (prevHma) mitigates old peaks that are *lower*
while (_peakStack.Count > 0 && prevHma >= _peakStack.Peek())
{
_peakStack.Pop(); // Pop the mitigated (lower) peak
mitigatedPeaks++;
}
if (mitigatedPeaks > 0)
{
// Draw mitigation count above the peak bar
// The remaining count is the peaks *higher* than the new one
string label = $"Mit: {mitigatedPeaks} / Rem: {_peakStack.Count}";
double yPos = Bars.HighPrices[index - 1] + Symbol.PipSize * 5;
Chart.DrawText($"peak_mit_{lblCnt}", label, index - 1, yPos, Color.Red);
dir = 1;
}
// Add the new peak to its own stack
_peakStack.Push(prevHma);
}
if (isTrough)
{
// New Trough: Check if it mitigates any *previous Troughs*
if( dir > 0 )
{
mitigatedTroughs = 0;
lblCnt++;
}
// A new trough (prevHma) mitigates old troughs that are *higher*
while (_troughStack.Count > 0 && prevHma <= _troughStack.Peek())
{
_troughStack.Pop(); // Pop the mitigated (higher) trough
mitigatedTroughs++;
}
if (mitigatedTroughs > 0)
{
// Draw mitigation count below the trough bar
// The remaining count is the troughs *lower* than the new one
string label = $"Mit: {mitigatedTroughs} / Rem: {_troughStack.Count}";
double yPos = Bars.LowPrices[index - 1] - Symbol.PipSize * 5;
Chart.DrawText($"trough_mit_{lblCnt}", label, index - 1, yPos, Color.Lime);
dir = -1;
}
// Add the new trough to its own stack
_troughStack.Push(prevHma);
}
}
}
}
@@ -0,0 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="cTrader.Automate" Version="*" />
</ItemGroup>
</Project>