using System; using System.Collections.Generic; namespace NT8.Core.OMS { #region Enumerations /// /// Order side enumeration /// public enum OrderSide { Buy = 1, Sell = -1 } /// /// Order type enumeration /// public enum OrderType { Market, Limit, StopMarket, StopLimit } /// /// Order state enumeration for the OMS state machine /// public enum OrderState { Pending, // Order request created, waiting for risk approval Submitted, // Sent to broker, waiting for acceptance Accepted, // Broker accepted the order Working, // Order is live in the market PartiallyFilled, // Order partially filled Filled, // Order completely filled Cancelled, // Order cancelled by user or system Rejected, // Order rejected by broker or system Expired // Order expired } /// /// Time in force enumeration /// public enum TimeInForce { Day, Gtc, // Good Till Cancelled Ioc, // Immediate Or Cancel Fok // Fill Or Kill } #endregion #region Core Order Models /// /// Order request parameters /// public class OrderRequest { /// /// Trading symbol /// public string Symbol { get; set; } /// /// Order side /// public OrderSide Side { get; set; } /// /// Order type /// public OrderType Type { get; set; } /// /// Order quantity /// public int Quantity { get; set; } /// /// Limit price (if applicable) /// public decimal? LimitPrice { get; set; } /// /// Stop price (if applicable) /// public decimal? StopPrice { get; set; } /// /// Time in force /// public TimeInForce TimeInForce { get; set; } /// /// Unique identifier for this order request /// public string ClientOrderId { get; set; } /// /// Timestamp when order was created /// public DateTime CreatedTime { get; set; } /// /// Constructor for OrderRequest /// public OrderRequest() { CreatedTime = DateTime.UtcNow; } } /// /// Order submission result /// public class OrderResult { /// /// Whether the order submission was successful /// public bool Success { get; set; } /// /// Order ID if successful /// public string OrderId { get; set; } /// /// Message describing the result /// public string Message { get; set; } /// /// Original order request /// public OrderRequest Request { get; set; } /// /// Constructor for OrderResult /// public OrderResult(bool success, string orderId, string message, OrderRequest request) { Success = success; OrderId = orderId; Message = message; Request = request; } } /// /// Current order status with full state information /// public class OrderStatus { /// /// Internal order ID assigned by the OMS /// public string OrderId { get; set; } /// /// Client-provided order ID /// public string ClientOrderId { get; set; } /// /// Trading symbol /// public string Symbol { get; set; } /// /// Order side /// public OrderSide Side { get; set; } /// /// Order type /// public OrderType Type { get; set; } /// /// Original order quantity /// public int Quantity { get; set; } /// /// Filled quantity /// public int FilledQuantity { get; set; } /// /// Remaining quantity /// public int RemainingQuantity { get { return Quantity - FilledQuantity; } } /// /// Limit price (if applicable) /// public decimal? LimitPrice { get; set; } /// /// Stop price (if applicable) /// public decimal? StopPrice { get; set; } /// /// Current order state /// public OrderState State { get; set; } /// /// Order creation time /// public DateTime CreatedTime { get; set; } /// /// Order fill time (if filled) /// public DateTime? FilledTime { get; set; } /// /// Order fills /// public List Fills { get; set; } /// /// Average fill price /// public decimal AverageFillPrice { get; set; } /// /// Total value of filled shares /// public decimal FillValue { get; set; } /// /// Constructor for OrderStatus /// public OrderStatus() { Fills = new List(); CreatedTime = DateTime.UtcNow; } } /// /// Represents a single fill event for an order /// public class OrderFill { /// /// Fill ID from the broker /// public string FillId { get; set; } /// /// Order ID this fill belongs to /// public string OrderId { get; set; } /// /// Quantity filled in this transaction /// public int FillQuantity { get; set; } /// /// Price at which the fill occurred /// public decimal FillPrice { get; set; } /// /// Timestamp of the fill /// public DateTime FillTime { get; set; } /// /// Commission paid for this fill /// public decimal Commission { get; set; } /// /// Constructor for OrderFill /// public OrderFill() { FillTime = DateTime.UtcNow; } } /// /// Order modification parameters /// public class OrderModification { /// /// Order ID to modify /// public string OrderId { get; set; } /// /// New quantity (if changing) /// public int? NewQuantity { get; set; } /// /// New limit price (if changing) /// public decimal? NewLimitPrice { get; set; } /// /// New stop price (if changing) /// public decimal? NewStopPrice { get; set; } /// /// New time in force (if changing) /// public TimeInForce? NewTimeInForce { get; set; } /// /// Constructor for OrderModification /// public OrderModification(string orderId) { OrderId = orderId; } } /// /// Order cancellation request /// public class OrderCancellation { /// /// Order ID to cancel /// public string OrderId { get; set; } /// /// Reason for cancellation /// public string Reason { get; set; } /// /// Constructor for OrderCancellation /// public OrderCancellation(string orderId, string reason) { OrderId = orderId; Reason = reason; } } #endregion #region Phase 2 - Partial Fill Models /// /// Detailed information about a partial fill event /// public class PartialFillInfo { /// /// Order ID this partial fill belongs to /// public string OrderId { get; set; } /// /// Quantity filled in this event /// public int FilledQuantity { get; set; } /// /// Remaining quantity after this fill /// public int RemainingQuantity { get; set; } /// /// Total quantity of the original order /// public int TotalQuantity { get; set; } /// /// Fill price for this partial fill /// public decimal FillPrice { get; set; } /// /// Average fill price across all fills so far /// public decimal AverageFillPrice { get; set; } /// /// Timestamp of this partial fill /// public DateTime FillTime { get; set; } /// /// Fill percentage (0-100) /// public double FillPercentage { get; set; } /// /// Whether this completes the order /// public bool IsComplete { get; set; } /// /// Constructor for PartialFillInfo /// public PartialFillInfo( string orderId, int filledQuantity, int remainingQuantity, int totalQuantity, decimal fillPrice, decimal averageFillPrice, DateTime fillTime) { if (string.IsNullOrEmpty(orderId)) throw new ArgumentNullException("orderId"); if (filledQuantity <= 0) throw new ArgumentException("FilledQuantity must be positive", "filledQuantity"); if (totalQuantity <= 0) throw new ArgumentException("TotalQuantity must be positive", "totalQuantity"); OrderId = orderId; FilledQuantity = filledQuantity; RemainingQuantity = remainingQuantity; TotalQuantity = totalQuantity; FillPrice = fillPrice; AverageFillPrice = averageFillPrice; FillTime = fillTime; FillPercentage = ((double)(totalQuantity - remainingQuantity) / (double)totalQuantity) * 100.0; IsComplete = remainingQuantity == 0; } } /// /// Strategy for handling partial fills /// public enum PartialFillStrategy { /// /// Allow partial fills and wait for complete fill /// AllowAndWait, /// /// Cancel remaining quantity after first partial fill /// CancelRemaining, /// /// Accept any partial fill as complete /// AcceptPartial, /// /// Reject the order if not filled immediately (FOK-like) /// AllOrNone } /// /// Configuration for partial fill handling /// public class PartialFillConfig { /// /// Strategy to use for partial fills /// public PartialFillStrategy Strategy { get; set; } /// /// Minimum fill percentage to accept (0-100) /// public double MinimumFillPercentage { get; set; } /// /// Maximum time to wait for complete fill (seconds) /// public int MaxWaitTimeSeconds { get; set; } /// /// Whether to retry remaining quantity with new order /// public bool RetryRemaining { get; set; } /// /// Constructor for PartialFillConfig /// public PartialFillConfig( PartialFillStrategy strategy, double minimumFillPercentage, int maxWaitTimeSeconds, bool retryRemaining) { Strategy = strategy; MinimumFillPercentage = minimumFillPercentage; MaxWaitTimeSeconds = maxWaitTimeSeconds; RetryRemaining = retryRemaining; } /// /// Default configuration - allow partial fills and wait /// public static PartialFillConfig Default { get { return new PartialFillConfig( PartialFillStrategy.AllowAndWait, 0.0, // Accept any fill percentage 300, // Wait up to 5 minutes false // Don't auto-retry ); } } } /// /// Result of handling a partial fill /// public class PartialFillResult { /// /// Order ID /// public string OrderId { get; set; } /// /// Action taken /// public PartialFillAction Action { get; set; } /// /// Reason for the action /// public string Reason { get; set; } /// /// Whether the order is now complete /// public bool IsComplete { get; set; } /// /// New order ID if retry was attempted /// public string RetryOrderId { get; set; } /// /// Constructor for PartialFillResult /// public PartialFillResult( string orderId, PartialFillAction action, string reason, bool isComplete, string retryOrderId) { OrderId = orderId; Action = action; Reason = reason; IsComplete = isComplete; RetryOrderId = retryOrderId; } } /// /// Action taken when handling partial fill /// public enum PartialFillAction { /// /// Continue waiting for complete fill /// Wait, /// /// Cancel remaining quantity /// CancelRemaining, /// /// Accept partial fill as complete /// AcceptPartial, /// /// Retry remaining quantity with new order /// RetryRemaining, /// /// No action needed (order complete) /// None } #endregion #region Phase 3 - Advanced Order Types /// /// Limit order request with specific price /// public class LimitOrderRequest : OrderRequest { /// /// Limit price for the order /// public new decimal LimitPrice { get; set; } /// /// Constructor for LimitOrderRequest /// /// Trading symbol /// Order side (Buy/Sell) /// Order quantity /// Limit price /// Time in force public LimitOrderRequest(string symbol, OrderSide side, int quantity, decimal limitPrice, TimeInForce tif) { if (string.IsNullOrEmpty(symbol)) throw new ArgumentNullException("symbol"); if (quantity <= 0) throw new ArgumentException("Quantity must be positive", "quantity"); if (limitPrice <= 0) throw new ArgumentException("LimitPrice must be positive", "limitPrice"); Symbol = symbol; Side = side; Quantity = quantity; LimitPrice = limitPrice; TimeInForce = tif; Type = OrderType.Limit; ClientOrderId = Guid.NewGuid().ToString(); CreatedTime = DateTime.UtcNow; } } /// /// Stop order request (stop market order) /// public class StopOrderRequest : OrderRequest { /// /// Stop price that triggers the order /// public new decimal StopPrice { get; set; } /// /// Constructor for StopOrderRequest /// /// Trading symbol /// Order side (Buy/Sell) /// Order quantity /// Stop price /// Time in force public StopOrderRequest(string symbol, OrderSide side, int quantity, decimal stopPrice, TimeInForce tif) { if (string.IsNullOrEmpty(symbol)) throw new ArgumentNullException("symbol"); if (quantity <= 0) throw new ArgumentException("Quantity must be positive", "quantity"); if (stopPrice <= 0) throw new ArgumentException("StopPrice must be positive", "stopPrice"); Symbol = symbol; Side = side; Quantity = quantity; StopPrice = stopPrice; TimeInForce = tif; Type = OrderType.StopMarket; ClientOrderId = Guid.NewGuid().ToString(); CreatedTime = DateTime.UtcNow; } } /// /// Stop-limit order request /// public class StopLimitOrderRequest : OrderRequest { /// /// Stop price that triggers the order /// public new decimal StopPrice { get; set; } /// /// Limit price for the triggered order /// public new decimal LimitPrice { get; set; } /// /// Constructor for StopLimitOrderRequest /// /// Trading symbol /// Order side (Buy/Sell) /// Order quantity /// Stop price /// Limit price /// Time in force public StopLimitOrderRequest(string symbol, OrderSide side, int quantity, decimal stopPrice, decimal limitPrice, TimeInForce tif) { if (string.IsNullOrEmpty(symbol)) throw new ArgumentNullException("symbol"); if (quantity <= 0) throw new ArgumentException("Quantity must be positive", "quantity"); if (stopPrice <= 0) throw new ArgumentException("StopPrice must be positive", "stopPrice"); if (limitPrice <= 0) throw new ArgumentException("LimitPrice must be positive", "limitPrice"); Symbol = symbol; Side = side; Quantity = quantity; StopPrice = stopPrice; LimitPrice = limitPrice; TimeInForce = tif; Type = OrderType.StopLimit; ClientOrderId = Guid.NewGuid().ToString(); CreatedTime = DateTime.UtcNow; } } /// /// Market-if-touched order request /// public class MITOrderRequest : OrderRequest { /// /// Trigger price for the MIT order /// public decimal TriggerPrice { get; set; } /// /// Constructor for MITOrderRequest /// /// Trading symbol /// Order side (Buy/Sell) /// Order quantity /// Trigger price /// Time in force public MITOrderRequest(string symbol, OrderSide side, int quantity, decimal triggerPrice, TimeInForce tif) { if (string.IsNullOrEmpty(symbol)) throw new ArgumentNullException("symbol"); if (quantity <= 0) throw new ArgumentException("Quantity must be positive", "quantity"); if (triggerPrice <= 0) throw new ArgumentException("TriggerPrice must be positive", "triggerPrice"); Symbol = symbol; Side = side; Quantity = quantity; TriggerPrice = triggerPrice; TimeInForce = tif; Type = OrderType.Market; // MIT orders become market orders when triggered ClientOrderId = Guid.NewGuid().ToString(); CreatedTime = DateTime.UtcNow; } } /// /// Trailing stop configuration /// public class TrailingStopConfig { /// /// Trailing amount in ticks /// public int TrailingTicks { get; set; } /// /// Trailing amount as percentage of current price /// public decimal? TrailingPercent { get; set; } /// /// Whether to trail by ATR or fixed amount /// public bool UseAtrTrail { get; set; } /// /// ATR multiplier for dynamic trailing /// public decimal AtrMultiplier { get; set; } /// /// Constructor for TrailingStopConfig /// /// Trailing amount in ticks /// Whether to use ATR-based trailing /// ATR multiplier if using ATR trail public TrailingStopConfig(int trailingTicks, bool useAtrTrail = false, decimal atrMultiplier = 2m) { if (trailingTicks <= 0) throw new ArgumentException("TrailingTicks must be positive", "trailingTicks"); if (atrMultiplier <= 0) throw new ArgumentException("AtrMultiplier must be positive", "atrMultiplier"); TrailingTicks = trailingTicks; UseAtrTrail = useAtrTrail; AtrMultiplier = atrMultiplier; } /// /// Constructor for percentage-based trailing stop /// /// Trailing percentage public TrailingStopConfig(decimal trailingPercent) { if (trailingPercent <= 0 || trailingPercent >= 100) throw new ArgumentException("TrailingPercent must be between 0 and 100", "trailingPercent"); TrailingPercent = trailingPercent; } } /// /// Parameters for different order types /// public class OrderTypeParameters { /// /// For limit orders - the limit price /// public decimal? LimitPrice { get; set; } /// /// For stop orders - the stop price /// public decimal? StopPrice { get; set; } /// /// For trailing stops - the trailing configuration /// public TrailingStopConfig TrailingConfig { get; set; } /// /// For iceberg orders - the displayed quantity /// public int? DisplayQty { get; set; } /// /// For algo orders - additional parameters /// public Dictionary AdditionalParams { get; set; } /// /// Constructor for OrderTypeParameters /// public OrderTypeParameters() { AdditionalParams = new Dictionary(); } } #endregion }