Optimizing and Refactoring HmaClusterBot & -Indicator
This commit is contained in:
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"Chart": {
|
||||
"Symbol": "GER40",
|
||||
"Period": "m5"
|
||||
},
|
||||
"Parameters": {
|
||||
"SymbolsCsv": "",
|
||||
"RiskPercent": 1.0,
|
||||
"EntrySigThreshold": 15.0,
|
||||
"SlSigThreshold": 5.0,
|
||||
"SmaBiasPeriod": 250,
|
||||
"HmaBiasPeriod": 225,
|
||||
"UseBiasDeviationFilter": true,
|
||||
"BiasDeviationAvgPeriod": 100,
|
||||
"UseDynamicPositionManagement": true,
|
||||
"CloseProfitOnBiasFlip": false,
|
||||
"HmaClusterPeriod": 25,
|
||||
"MaxPoints": 2000,
|
||||
"DecayPeriod": 1000,
|
||||
"SendTelegramOnly": false,
|
||||
"TelegramBotToken": "8569913524:AAE9RGsvkBPa0yhTFCKBjVeST0fuzdOx5w0",
|
||||
"TelegramChatId": "5171721381"
|
||||
}
|
||||
}
|
||||
Binary file not shown.
@@ -7,7 +7,7 @@ using System.Threading.Tasks;
|
||||
using cAlgo.API;
|
||||
using cAlgo.API.Indicators;
|
||||
using cAlgo.API.Internals;
|
||||
using Myc; // Referenz auf die extrahierte Cluster-Logik
|
||||
using Myc; // Referencing external cluster logic
|
||||
|
||||
namespace cAlgo.Robots
|
||||
{
|
||||
@@ -130,8 +130,6 @@ namespace cAlgo.Robots
|
||||
{
|
||||
Print(message);
|
||||
|
||||
// WICHTIG: Im Backtest NIEMALS Netzwerk-Calls machen, auch nicht bei Fehlern.
|
||||
// Das führt bei vielen Fehlern zum Stillstand der Simulation.
|
||||
if (IsBacktesting) return;
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(TelegramBotToken) && !string.IsNullOrWhiteSpace(TelegramChatId))
|
||||
@@ -272,7 +270,6 @@ namespace cAlgo.Robots
|
||||
private bool _deviationConditionMetInCurrentCycle;
|
||||
private bool _isTradingAllowedBasedOnPrevCycle;
|
||||
|
||||
// --- OPTIMIERUNG: Nutzt Calculator statt Liste ---
|
||||
private readonly Myc.ClusterCalculator _clusterCalculator;
|
||||
private readonly List<double> _amplitudes = new();
|
||||
|
||||
@@ -305,7 +302,6 @@ namespace cAlgo.Robots
|
||||
_chatId = chatId;
|
||||
_errorCallback = errorCallback;
|
||||
|
||||
// Calculator mit Reserve initialisieren
|
||||
_clusterCalculator = new Myc.ClusterCalculator();
|
||||
}
|
||||
|
||||
@@ -470,57 +466,25 @@ namespace cAlgo.Robots
|
||||
ClusterLevel? newSl = null;
|
||||
ClusterLevel? newTp = null;
|
||||
|
||||
// For logic: Find nearest strong cluster behind entry (SL) and nearest strong cluster ahead (TP)
|
||||
double highestSlPrice = double.MinValue; // Buy SL: Highest below price
|
||||
double lowestTpPrice = double.MaxValue; // Buy TP: Lowest above price
|
||||
|
||||
double lowestSlPrice = double.MaxValue; // Sell SL: Lowest above price
|
||||
double highestTpPrice = double.MinValue; // Sell TP: Highest below price
|
||||
|
||||
if (pos.TradeType == TradeType.Buy)
|
||||
{
|
||||
double highestSlPrice = double.MinValue;
|
||||
double highestTpPrice = double.MinValue;
|
||||
|
||||
foreach (var c in clusters)
|
||||
{
|
||||
if (c.Price < pNow && c.Significance < _config.SlSigThreshold && c.Price > highestSlPrice)
|
||||
// SL: Strong clusters BELOW price -> Nearest one (Highest Price)
|
||||
if (c.Price < pNow && c.Significance >= _config.SlSigThreshold && c.Price > highestSlPrice)
|
||||
{
|
||||
newSl = c;
|
||||
highestSlPrice = c.Price;
|
||||
}
|
||||
if (c.Price > pNow && c.Significance >= _config.EntrySigThreshold && c.Price > highestTpPrice)
|
||||
{
|
||||
newTp = c;
|
||||
highestTpPrice = c.Price;
|
||||
}
|
||||
}
|
||||
|
||||
double proposedSl = (newSl.HasValue) ? newSl.Value.Price : (pos.StopLoss ?? 0);
|
||||
double proposedTp = (newTp.HasValue) ? newTp.Value.Price : (pos.TakeProfit ?? 0);
|
||||
|
||||
bool modifySl = pos.StopLoss.HasValue && (proposedSl > pos.StopLoss.Value + _symbol.TickSize);
|
||||
if (!pos.StopLoss.HasValue && newSl.HasValue) modifySl = true;
|
||||
|
||||
bool modifyTp = newTp.HasValue && Math.Abs(proposedTp - (pos.TakeProfit ?? 0)) > _symbol.TickSize;
|
||||
|
||||
if (modifySl || modifyTp)
|
||||
{
|
||||
double finalSl = modifySl ? proposedSl : pos.StopLoss ?? 0;
|
||||
double finalTp = modifyTp ? proposedTp : pos.TakeProfit ?? 0;
|
||||
|
||||
if (finalSl < _symbol.Bid && (finalTp == 0 || finalTp > _symbol.Bid))
|
||||
{
|
||||
_robot.ModifyPosition(pos, finalSl, finalTp, ProtectionType.Absolute);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
double lowestSlPrice = double.MaxValue;
|
||||
double lowestTpPrice = double.MaxValue;
|
||||
|
||||
foreach (var c in clusters)
|
||||
{
|
||||
if (c.Price > pNow && c.Significance < _config.SlSigThreshold && c.Price < lowestSlPrice)
|
||||
{
|
||||
newSl = c;
|
||||
lowestSlPrice = c.Price;
|
||||
}
|
||||
if (c.Price < pNow && c.Significance >= _config.EntrySigThreshold && c.Price < lowestTpPrice)
|
||||
// TP: Strong clusters ABOVE price -> Nearest one (Lowest Price)
|
||||
if (c.Price > pNow && c.Significance >= _config.EntrySigThreshold && c.Price < lowestTpPrice)
|
||||
{
|
||||
newTp = c;
|
||||
lowestTpPrice = c.Price;
|
||||
@@ -530,6 +494,47 @@ namespace cAlgo.Robots
|
||||
double proposedSl = (newSl.HasValue) ? newSl.Value.Price : (pos.StopLoss ?? 0);
|
||||
double proposedTp = (newTp.HasValue) ? newTp.Value.Price : (pos.TakeProfit ?? 0);
|
||||
|
||||
// Move SL up only (trailing)
|
||||
bool modifySl = pos.StopLoss.HasValue && (proposedSl > pos.StopLoss.Value + _symbol.TickSize);
|
||||
if (!pos.StopLoss.HasValue && newSl.HasValue) modifySl = true;
|
||||
|
||||
// Update TP if it changes significantly
|
||||
bool modifyTp = newTp.HasValue && Math.Abs(proposedTp - (pos.TakeProfit ?? 0)) > _symbol.TickSize;
|
||||
|
||||
if (modifySl || modifyTp)
|
||||
{
|
||||
double finalSl = modifySl ? proposedSl : pos.StopLoss ?? 0;
|
||||
double finalTp = modifyTp ? proposedTp : pos.TakeProfit ?? 0;
|
||||
|
||||
// SL < Bid, TP > Bid (or 0)
|
||||
if (finalSl < _symbol.Bid && (finalTp == 0 || finalTp > _symbol.Bid))
|
||||
{
|
||||
_robot.ModifyPosition(pos, finalSl, finalTp, ProtectionType.Absolute);
|
||||
}
|
||||
}
|
||||
}
|
||||
else // Sell
|
||||
{
|
||||
foreach (var c in clusters)
|
||||
{
|
||||
// SL: Strong clusters ABOVE price -> Nearest one (Lowest Price)
|
||||
if (c.Price > pNow && c.Significance >= _config.SlSigThreshold && c.Price < lowestSlPrice)
|
||||
{
|
||||
newSl = c;
|
||||
lowestSlPrice = c.Price;
|
||||
}
|
||||
// TP: Strong clusters BELOW price -> Nearest one (Highest Price)
|
||||
if (c.Price < pNow && c.Significance >= _config.EntrySigThreshold && c.Price > highestTpPrice)
|
||||
{
|
||||
newTp = c;
|
||||
highestTpPrice = c.Price;
|
||||
}
|
||||
}
|
||||
|
||||
double proposedSl = (newSl.HasValue) ? newSl.Value.Price : (pos.StopLoss ?? 0);
|
||||
double proposedTp = (newTp.HasValue) ? newTp.Value.Price : (pos.TakeProfit ?? 0);
|
||||
|
||||
// Move SL down only (trailing)
|
||||
bool modifySl = pos.StopLoss.HasValue && (proposedSl < pos.StopLoss.Value - _symbol.TickSize);
|
||||
if (!pos.StopLoss.HasValue && newSl.HasValue) modifySl = true;
|
||||
|
||||
@@ -540,6 +545,7 @@ namespace cAlgo.Robots
|
||||
double finalSl = modifySl ? proposedSl : pos.StopLoss ?? 0;
|
||||
double finalTp = modifyTp ? proposedTp : pos.TakeProfit ?? 0;
|
||||
|
||||
// SL > Ask, TP < Ask (or 0)
|
||||
if (finalSl > _symbol.Ask && (finalTp == 0 || finalTp < _symbol.Ask))
|
||||
{
|
||||
_robot.ModifyPosition(pos, finalSl, finalTp, ProtectionType.Absolute);
|
||||
@@ -619,20 +625,32 @@ namespace cAlgo.Robots
|
||||
ClusterLevel? sl = null;
|
||||
ClusterLevel? tp = null;
|
||||
|
||||
double highestEntryPrice = double.MinValue;
|
||||
double lowestSlPrice = double.MaxValue;
|
||||
double lowestTpPrice = double.MaxValue;
|
||||
double highestEntryPrice = double.MinValue; // Entry: Deepest fade (Highest Price)
|
||||
double lowestSlPrice = double.MaxValue; // SL: Nearest strong resistance above Entry (Lowest Price > Entry)
|
||||
double highestTpPrice = double.MinValue; // TP: Nearest strong support below Entry (Highest Price < Entry)
|
||||
|
||||
// 1. Find Entry (Above Price)
|
||||
foreach (var c in clusters)
|
||||
{
|
||||
if (c.Price > pNow)
|
||||
{
|
||||
// Aggressive fade: Pick highest price available
|
||||
if ((c.Significance >= _config.EntrySigThreshold) && (c.Price > highestEntryPrice))
|
||||
{
|
||||
entry = c;
|
||||
highestEntryPrice = c.Price;
|
||||
}
|
||||
if ((c.Significance < _config.SlSigThreshold) && (c.Price < lowestSlPrice))
|
||||
}
|
||||
}
|
||||
|
||||
if (entry == null) return;
|
||||
|
||||
// 2. Find SL relative to Entry (Strong Cluster, Nearest Above)
|
||||
foreach (var c in clusters)
|
||||
{
|
||||
if (c.Price > entry.Value.Price)
|
||||
{
|
||||
if (c.Significance >= _config.SlSigThreshold && c.Price < lowestSlPrice)
|
||||
{
|
||||
sl = c;
|
||||
lowestSlPrice = c.Price;
|
||||
@@ -640,16 +658,17 @@ namespace cAlgo.Robots
|
||||
}
|
||||
}
|
||||
|
||||
if (entry == null || sl == null) return;
|
||||
if (sl == null) return;
|
||||
|
||||
// 3. Find TP relative to Entry (Strong Cluster, Nearest Below)
|
||||
foreach (var c in clusters)
|
||||
{
|
||||
if ((c.Price < entry.Value.Price) && (c.Significance >= _config.EntrySigThreshold))
|
||||
if (c.Price < entry.Value.Price)
|
||||
{
|
||||
if (c.Price < lowestTpPrice)
|
||||
if (c.Significance >= _config.EntrySigThreshold && c.Price > highestTpPrice)
|
||||
{
|
||||
tp = c;
|
||||
lowestTpPrice = c.Price;
|
||||
highestTpPrice = c.Price;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -670,20 +689,32 @@ namespace cAlgo.Robots
|
||||
ClusterLevel? sl = null;
|
||||
ClusterLevel? tp = null;
|
||||
|
||||
double lowestEntryPrice = double.MaxValue;
|
||||
double highestSlPrice = double.MinValue;
|
||||
double highestTpPrice = double.MinValue;
|
||||
double lowestEntryPrice = double.MaxValue; // Entry: Deepest fade (Lowest Price)
|
||||
double highestSlPrice = double.MinValue; // SL: Nearest strong support below Entry (Highest Price < Entry)
|
||||
double lowestTpPrice = double.MaxValue; // TP: Nearest strong resistance above Entry (Lowest Price > Entry)
|
||||
|
||||
// 1. Find Entry (Below Price)
|
||||
foreach (var c in clusters)
|
||||
{
|
||||
if (c.Price < pNow)
|
||||
{
|
||||
// Aggressive fade: Pick lowest price available
|
||||
if ((c.Significance >= _config.EntrySigThreshold) && (c.Price < lowestEntryPrice))
|
||||
{
|
||||
entry = c;
|
||||
lowestEntryPrice = c.Price;
|
||||
}
|
||||
if ((c.Significance < _config.SlSigThreshold) && (c.Price > highestSlPrice))
|
||||
}
|
||||
}
|
||||
|
||||
if (entry == null) return;
|
||||
|
||||
// 2. Find SL relative to Entry (Strong Cluster, Nearest Below)
|
||||
foreach (var c in clusters)
|
||||
{
|
||||
if (c.Price < entry.Value.Price)
|
||||
{
|
||||
if (c.Significance >= _config.SlSigThreshold && c.Price > highestSlPrice)
|
||||
{
|
||||
sl = c;
|
||||
highestSlPrice = c.Price;
|
||||
@@ -691,16 +722,17 @@ namespace cAlgo.Robots
|
||||
}
|
||||
}
|
||||
|
||||
if (entry == null || sl == null) return;
|
||||
if (sl == null) return;
|
||||
|
||||
// 3. Find TP relative to Entry (Strong Cluster, Nearest Above)
|
||||
foreach (var c in clusters)
|
||||
{
|
||||
if ((c.Price > entry.Value.Price) && (c.Significance >= _config.EntrySigThreshold))
|
||||
if (c.Price > entry.Value.Price)
|
||||
{
|
||||
if (c.Price > highestTpPrice)
|
||||
if (c.Significance >= _config.EntrySigThreshold && c.Price < lowestTpPrice)
|
||||
{
|
||||
tp = c;
|
||||
highestTpPrice = c.Price;
|
||||
lowestTpPrice = c.Price;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -760,7 +792,6 @@ namespace cAlgo.Robots
|
||||
var result = _robot.ModifyPendingOrder(existingOrder, entry, sl, tp, ProtectionType.Absolute, null, volume);
|
||||
if (!result.IsSuccessful)
|
||||
{
|
||||
// Falls Modifikation fehlschlägt (z.B. Spread), löschen wir die Order, um keine veralteten Levels zu handeln
|
||||
_robot.CancelPendingOrder(existingOrder);
|
||||
}
|
||||
}
|
||||
@@ -820,7 +851,6 @@ namespace cAlgo.Robots
|
||||
if (_currentDynamicRange < _symbol.PipSize) _currentDynamicRange = _symbol.PipSize;
|
||||
}
|
||||
|
||||
// Neuen Punkt in den optimierten Calculator einspeisen
|
||||
_clusterCalculator.AddPoint(new Myc.ExtremumPoint
|
||||
{
|
||||
Price = _trendExtremum,
|
||||
|
||||
Reference in New Issue
Block a user