Production hardening: kill switch, circuit breaker, trailing stops, log level, holiday calendar
Some checks failed
Build and Test / build (push) Has been cancelled
Some checks failed
Build and Test / build (push) Has been cancelled
This commit is contained in:
@@ -98,7 +98,7 @@ namespace NT8.Core.Execution
|
||||
return null;
|
||||
}
|
||||
|
||||
var newStopPrice = CalculateNewStopPrice(trailingStop.Config.Type, trailingStop.Position, currentPrice);
|
||||
var newStopPrice = CalculateNewStopPrice(trailingStop.Config.Type, trailingStop.Position, currentPrice, trailingStop.Config);
|
||||
|
||||
// Only update if the stop has improved (moved in favorable direction)
|
||||
var shouldUpdate = false;
|
||||
@@ -149,55 +149,73 @@ namespace NT8.Core.Execution
|
||||
/// <param name="type">Type of trailing stop</param>
|
||||
/// <param name="position">Position information</param>
|
||||
/// <param name="marketPrice">Current market price</param>
|
||||
/// <param name="config">Trailing stop configuration</param>
|
||||
/// <returns>Calculated stop price</returns>
|
||||
public decimal CalculateNewStopPrice(StopType type, OMS.OrderStatus position, decimal marketPrice)
|
||||
public decimal CalculateNewStopPrice(StopType type, OMS.OrderStatus position, decimal marketPrice, TrailingStopConfig config = null)
|
||||
{
|
||||
if (position == null)
|
||||
throw new ArgumentNullException("position");
|
||||
|
||||
try
|
||||
{
|
||||
if (config == null)
|
||||
{
|
||||
config = new TrailingStopConfig(StopType.FixedTrailing, 8, 2m, true);
|
||||
}
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case StopType.FixedTrailing:
|
||||
// Fixed trailing: trail by fixed number of ticks from high/low
|
||||
if (position.Side == OMS.OrderSide.Buy)
|
||||
{
|
||||
// Long position: stop trails below highest high
|
||||
return marketPrice - (position.AverageFillPrice - position.AverageFillPrice); // Simplified
|
||||
}
|
||||
else
|
||||
{
|
||||
// Short position: stop trails above lowest low
|
||||
return marketPrice + (position.AverageFillPrice - position.AverageFillPrice); // Simplified
|
||||
// Tick size is fixed here as a temporary default (ES/NQ standard).
|
||||
// TODO: provide symbol-specific tick size via configuration.
|
||||
var tickSize = 0.25m;
|
||||
var trailingTicks = config.TrailingAmountTicks > 0 ? config.TrailingAmountTicks : 8;
|
||||
var distance = trailingTicks * tickSize;
|
||||
|
||||
return position.Side == OMS.OrderSide.Buy
|
||||
? marketPrice - distance
|
||||
: marketPrice + distance;
|
||||
}
|
||||
|
||||
case StopType.ATRTrailing:
|
||||
// ATR trailing: trail by ATR multiple
|
||||
return position.Side == OMS.OrderSide.Buy ?
|
||||
marketPrice - (position.AverageFillPrice * 0.01m) : // Placeholder for ATR calculation
|
||||
marketPrice + (position.AverageFillPrice * 0.01m); // Placeholder for ATR calculation
|
||||
{
|
||||
// ATR is approximated here until live ATR is provided in config/context.
|
||||
var atrMultiplier = config.AtrMultiplier > 0 ? config.AtrMultiplier : 2.0m;
|
||||
var estimatedAtr = position.AverageFillPrice * 0.005m;
|
||||
var distance = atrMultiplier * estimatedAtr;
|
||||
|
||||
return position.Side == OMS.OrderSide.Buy
|
||||
? marketPrice - distance
|
||||
: marketPrice + distance;
|
||||
}
|
||||
|
||||
case StopType.Chandelier:
|
||||
// Chandelier: trail from highest high minus ATR * multiplier
|
||||
return position.Side == OMS.OrderSide.Buy ?
|
||||
marketPrice - (position.AverageFillPrice * 0.01m) : // Placeholder for chandelier calculation
|
||||
marketPrice + (position.AverageFillPrice * 0.01m); // Placeholder for chandelier calculation
|
||||
{
|
||||
// Chandelier approximation uses the same ATR proxy until bar history is wired in.
|
||||
var chanMultiplier = config.AtrMultiplier > 0 ? config.AtrMultiplier : 3.0m;
|
||||
var estimatedAtr = position.AverageFillPrice * 0.005m;
|
||||
var distance = chanMultiplier * estimatedAtr;
|
||||
|
||||
return position.Side == OMS.OrderSide.Buy
|
||||
? marketPrice - distance
|
||||
: marketPrice + distance;
|
||||
}
|
||||
|
||||
case StopType.PercentageTrailing:
|
||||
// Percentage trailing: trail by percentage of current price
|
||||
var pctTrail = 0.02m; // Default 2% - in real impl this would come from config
|
||||
var pctTrail = 0.02m;
|
||||
return position.Side == OMS.OrderSide.Buy ?
|
||||
marketPrice * (1 - pctTrail) :
|
||||
marketPrice * (1 + pctTrail);
|
||||
|
||||
default:
|
||||
// Fixed trailing as fallback
|
||||
var tickSize = 0.25m; // Default tick size - should be configurable
|
||||
var ticks = 8; // Default trailing ticks - should come from config
|
||||
var tickSizeFallback = 0.25m;
|
||||
var ticks = config.TrailingAmountTicks > 0 ? config.TrailingAmountTicks : 8;
|
||||
return position.Side == OMS.OrderSide.Buy ?
|
||||
marketPrice - (ticks * tickSize) :
|
||||
marketPrice + (ticks * tickSize);
|
||||
marketPrice - (ticks * tickSizeFallback) :
|
||||
marketPrice + (ticks * tickSizeFallback);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
||||
Reference in New Issue
Block a user