Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 0 additions & 93 deletions README.md.bak

This file was deleted.

33 changes: 14 additions & 19 deletions TriggerEngine/TriggerEngineService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,13 +56,11 @@ public static class TriggerEngineService

private static readonly Channel<MetricEvent> MetricChannel = Channel.CreateUnbounded<MetricEvent>();

// Architecture §2.2.5 — additive fan-in event consumed by the
// MarketDataRecorder TriggerCallbackHandler (T-MDR-046) and any other
// subscriber that needs to react to rule fires. Per ADR-03 this is
// purely additive: zero behavioural change for non-subscribers. The
// raise site lives at the bottom of ProcessMetric (after a fire passes
// the cooldown gate). Subscribers are invoked individually so a
// throwing handler never breaks others (T-MDR-045 case 7).
// Additive fan-in event for any subscriber that needs to react to rule
// fires. Purely additive: zero behavioural change for non-subscribers.
// The raise site lives at the bottom of ProcessMetric (after a fire
// passes the cooldown gate). Subscribers are invoked individually so a
// throwing handler never breaks others.
public static event Action<TriggerFiredEventArgs>? OnTriggerFired;


Expand Down Expand Up @@ -242,7 +240,7 @@ private static void ProcessMetric(MetricEvent e)
if (triggeringCondition == null)
triggeringCondition = condition;

// OD-3 / GAP-MDR-14: a rule with a sustained Window must only
// A rule with a sustained Window must only
// count as met once the condition has HELD for the full window.
// Previously ProcessMetric called EvaluateDirect unconditionally
// and IsConditionSatisfiedWithWindow was dead code, so windowed
Expand Down Expand Up @@ -291,9 +289,9 @@ private static void ProcessMetric(MetricEvent e)

if (!ActionLastFiredTimes.TryGetValue(actionKey, out var lastFireTime))
{
// GAP-MDR-01: the FIRST qualifying fire from a clean
// state must firethe spec (FR-3.3.1 / S-08) treats
// the first breach like any other. Previously this branch
// The FIRST qualifying fire from a clean state must
// fire: the first breach is treated like any other.
// Previously this branch
// only recorded the timestamp (ExecuteActionAsync and the
// OnTriggerFired raise were commented out), so the first
// breach was silently dropped and a fire only happened on
Expand Down Expand Up @@ -321,12 +319,10 @@ private static void ProcessMetric(MetricEvent e)
ActionLastFiredTimes[actionKey] = e.Timestamp;
_ = ExecuteActionAsync(rule.Name, triggeringCondition, action, e.Plugin, e.Metric, e.Exchange, e.Symbol, e.Value, e.Timestamp);

// Architecture §2.2.5 — raise OnTriggerFired
// AFTER the cooldown passes (matches the fire
// semantics of ExecuteActionAsync). Per-handler
// try/catch keeps a misbehaving subscriber from
// poisoning the rest of the invocation list
// (T-MDR-045 case 7).
// Raise OnTriggerFired AFTER the cooldown passes
// (matches the fire semantics of ExecuteActionAsync).
// Per-handler try/catch keeps a misbehaving subscriber
// from poisoning the rest of the invocation list.
RaiseOnTriggerFired(rule, triggeringCondition, e);
}
// else: cooldown not passed, do nothing
Expand All @@ -353,8 +349,7 @@ private static bool ConditionMatchesTick(TriggerCondition condition, MetricEvent

// Per-subscriber fan-out for OnTriggerFired. Iterating GetInvocationList
// is required so a throwing subscriber does not abort the multicast — the
// default `event(args)` form short-circuits on the first thrown exception
// (Architecture §2.2.5 / T-MDR-045 case 7).
// default `event(args)` form short-circuits on the first thrown exception.
private static void RaiseOnTriggerFired(TriggerRule rule, TriggerCondition condition, MetricEvent e)
{
var snapshot = OnTriggerFired;
Expand Down
1 change: 0 additions & 1 deletion ViewModel/vmTile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -346,7 +346,6 @@ private void OpenSettings(object obj)

/*
* Stop all studies (main and children) asynchronously
* ONLY FOR L3 VERSION
*/
public async Task StopAllAsync(CancellationToken cancellationToken)
{
Expand Down
4 changes: 2 additions & 2 deletions VisualHFT.Commons.WPF/Helper/FrameCoordinator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ public sealed class FrameCoordinator : IDisposable

// Guards _participants against concurrent mutation. Register is always reached on the UI
// thread (UIUpdater's constructor enforces it), but Unregister runs from UIUpdater.Dispose,
// which a plugin can dispose on a BACKGROUND thread (e.g. the replay session clone-swap
// stopping plugins off the dispatcher). Without this lock a concurrent Remove shrinks the
// which a plugin can dispose on a BACKGROUND thread (e.g. a plugin stopped off the
// dispatcher). Without this lock a concurrent Remove shrinks the
// list mid-tick and OnFrameTick's indexer throws IndexOutOfRange — crashing the app.
private readonly object _sync = new object();
// Reusable per-frame buffer: OnFrameTick copies the live participant set into this UNDER the
Expand Down
5 changes: 2 additions & 3 deletions VisualHFT.Commons/Helpers/HelperNotificationManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,8 @@ public enum HelprNorificationManagerTypes
ERROR,
WARNING,
TRIGGER_ACTION,
// GAP-MDR-16 — informational tier (below WARNING) for normal, expected
// outcomes that should be surfaced but are not problems (e.g. a Stop that
// discards an in-flight capture per the FR-03 50%-rule). Appended last so
// Informational tier (below WARNING) for normal, expected outcomes that
// should be surfaced but are not problems. Appended last so
// existing ordinals (ERROR=0/WARNING=1/TRIGGER_ACTION=2) are unchanged.
INFO
}
Expand Down
4 changes: 2 additions & 2 deletions VisualHFT.Commons/Helpers/HelperProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ private void _timer_check_heartbeat_Elapsed(object sender, System.Timers.Elapsed

/// <summary>
/// Runs the staleness check over all tracked providers: any provider whose last update is
/// older than the heartbeat window (compared on HelperTimeProvider.Now, so it stays correct
/// under replay) is marked CONNECTED_WITH_WARNINGS, its display cleared via empty order books,
/// older than the heartbeat window (compared on HelperTimeProvider.Now) is marked
/// CONNECTED_WITH_WARNINGS, its display cleared via empty order books,
/// and OnProviderStale raised. Public so a deterministic test can drive it by advancing the
/// virtual clock instead of waiting for the wall-clock 30s timer.
/// </summary>
Expand Down
4 changes: 2 additions & 2 deletions VisualHFT.Commons/PluginManager/BasePluginDataRetriever.cs
Original file line number Diff line number Diff line change
Expand Up @@ -455,8 +455,8 @@ private void LogAndNotify(string reason, Exception? exception = null)
/// <summary>
/// Per-frame freshness guard: if a received frame's exchange timestamp is more than
/// <paramref name="toleranceSeconds"/> behind the (virtual) clock, raise a WARNING notification.
/// Reads HelperTimeProvider.Now so it is deterministic under test and correct under replay (per
/// the replay-clock rule), and shared so every connector's hot-path freshness check is identical.
/// Reads HelperTimeProvider.Now so it is deterministic under test, and shared so every
/// connector's hot-path freshness check is identical.
/// Returns true when a warning was raised.
/// </summary>
protected bool CheckFrameFreshnessAndWarn(DateTime frameTimeLocal, double toleranceSeconds = 1.0)
Expand Down
10 changes: 4 additions & 6 deletions VisualHFT.Commons/Pools/BookItemL2Pool.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public interface IBasicBookItem
/// • Zero type checking overhead
/// • Lock-free statistics tracking
/// • Aggressive inlining for minimal overhead
/// • Open source clean (no L3 contamination)
/// • Handles only basic BookItem instances
///
/// PERFORMANCE CHARACTERISTICS:
/// ----------------------------
Expand All @@ -50,10 +50,8 @@ public interface IBasicBookItem
///
/// ARCHITECTURAL PURITY:
/// ----------------------
/// • Zero knowledge of L3 concepts
/// • Interface-based type safety
/// • Compile-time violation detection
/// • Open source synchronization safe
/// • No reflection, no runtime type checking
///
/// USAGE EXAMPLE:
Expand Down Expand Up @@ -112,15 +110,15 @@ public static BookItem Get()
/// <summary>
/// Thread-safe: Returns a basic BookItem to the pool.
/// ULTRA-HIGH-PERFORMANCE: Zero overhead return path.
/// OPTIMIZED: Removed reflection - L3 validation moved to BookItemPool smart dispatcher.
/// OPTIMIZED: Removed reflection - no type validation on the return path.
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Return(IBasicBookItem item)
{
if (item == null) return;

// OPTIMIZED: No reflection! L3 validation is handled by BookItemPool's smart dispatcher
// which routes L3 items to BookItemL3Pool before they ever reach here.
// No reflection and no type check here: BookItemPool.Return sends every BookItem to this
// pool unless a return handler has been registered.
// CustomObjectPool tracks returns internally, no additional counter needed.
_instance.Return((BookItem)item);
}
Expand Down
4 changes: 2 additions & 2 deletions VisualHFT.Plugins/MarketConnectors.Bitfinex/BitfinexPlugin.cs
Original file line number Diff line number Diff line change
Expand Up @@ -185,8 +185,8 @@ public async Task ClearAsync()
// teardown lives here rather than in StopAsync because BOTH stop paths - StopAsync and the
// reconnect's InternalStartAsync - must tear the subscriptions down on the live OUTGOING
// client and tolerate a dead one.
// Error, not Warn: the desktop telemetry appender ships nothing below Error, so a Warn
// never ships and a fleet-wide teardown failure would be invisible in production telemetry.
// Error, not Warn: a failed socket teardown leaves the venue connection in an unknown state
// and is a failure to surface, not a warning to file.
// Not LogException: it also increments OperationalErrorsCount, which the feed-health study
// reads as a feed failure, and a tolerated teardown is not one.
try
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,4 @@
<ProjectReference Include="..\..\VisualHFT.Commons\VisualHFT.Commons.csproj" />
</ItemGroup>

<ItemGroup>
<InternalsVisibleTo Include="MarketConnectors.Bitfinex.Tests" />
</ItemGroup>

</Project>
4 changes: 2 additions & 2 deletions VisualHFT.Plugins/MarketConnectors.Coinbase/CoinbasePlugin.cs
Original file line number Diff line number Diff line change
Expand Up @@ -212,8 +212,8 @@ public async Task ClearAsync()
// teardown lives here rather than in StopAsync because BOTH stop paths - StopAsync and the
// reconnect's InternalStartAsync - must tear the subscriptions down on the live OUTGOING
// client and tolerate a dead one.
// Error, not Warn: the desktop telemetry appender ships nothing below Error, so a Warn
// never ships and a fleet-wide teardown failure would be invisible in production telemetry.
// Error, not Warn: a failed socket teardown leaves the venue connection in an unknown state
// and is a failure to surface, not a warning to file.
// Not LogException: it also increments OperationalErrorsCount, which the feed-health study
// reads as a feed failure, and a tolerated teardown is not one.
try
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,4 @@
<ProjectReference Include="..\..\VisualHFT.Commons\VisualHFT.Commons.csproj" />
</ItemGroup>

<ItemGroup>
<InternalsVisibleTo Include="MarketConnectors.Coinbase.Tests" />
</ItemGroup>

</Project>
Loading