File size: 4,715 Bytes
d982819
 
894c633
d982819
e4830ea
894c633
d982819
 
 
 
 
 
 
 
 
e4830ea
 
894c633
 
 
 
 
 
 
 
 
 
 
d982819
 
894c633
d982819
 
 
 
894c633
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d982819
894c633
d982819
 
894c633
 
 
 
 
d982819
894c633
d982819
894c633
 
 
d982819
 
 
 
894c633
 
 
d982819
 
 
 
 
 
894c633
 
 
d982819
 
 
 
 
 
 
894c633
 
d982819
894c633
d982819
 
e4830ea
 
 
 
 
 
 
d982819
 
894c633
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
#pragma once
#include "Types.h"
#include <memory>
#include <stdexcept>
#include <string>
#include <list>
#include <chrono>

class Order {
public:
    Order(OrderType   orderType,
          OrderId     orderId,
          Side        side,
          Price       price,
          Quantity    quantity,
          Quantity    peakQuantity  = 0,
          Price       stopPrice     = Constants::InvalidPrice)
        : orderType_    { orderType    }
        , orderId_      { orderId      }
        , side_         { side         }
        , status_       { OrderStatus::New }
        , price_        { price        }
        , stopPrice_    { stopPrice    }
        , initialQty_   { quantity     }
        , remainingQty_ { quantity     }
        , displayQty_   { peakQuantity > 0 ? peakQuantity : quantity }
        , peakQty_      { peakQuantity }
        , timestamp_    { std::chrono::steady_clock::now().time_since_epoch().count() }
    {}

    // Market order convenience
    Order(OrderId orderId, Side side, Quantity quantity)
        : Order(OrderType::Market, orderId, side, Constants::InvalidPrice, quantity)
    {}

    // ─── Accessors ───────────────────────────────────────────────────────────
    OrderId     GetOrderId()           const noexcept { return orderId_;        }
    Side        GetSide()              const noexcept { return side_;           }
    Price       GetPrice()             const noexcept { return price_;          }
    Price       GetStopPrice()         const noexcept { return stopPrice_;      }
    OrderType   GetOrderType()         const noexcept { return orderType_;      }
    OrderStatus GetStatus()            const noexcept { return status_;         }
    Quantity    GetInitialQuantity()   const noexcept { return initialQty_;     }
    Quantity    GetRemainingQuantity() const noexcept { return remainingQty_;   }
    Quantity    GetFilledQuantity()    const noexcept { return initialQty_ - remainingQty_; }
    Quantity    GetDisplayQuantity()   const noexcept { return displayQty_;     }
    Quantity    GetPeakQuantity()      const noexcept { return peakQty_;        }
    int64_t     GetTimestamp()         const noexcept { return timestamp_;      }
    bool        IsFilled()             const noexcept { return remainingQty_ == 0; }
    bool        IsIceberg()            const noexcept { return peakQty_ > 0 && peakQty_ < initialQty_; }

    // ─── Mutators ────────────────────────────────────────────────────────────
    void Fill(Quantity qty) {
        if (qty > remainingQty_) [[unlikely]]
            throw std::logic_error(
                "Order " + std::to_string(orderId_) +
                " cannot fill " + std::to_string(qty) +
                " > remaining " + std::to_string(remainingQty_));

        remainingQty_ -= qty;

        if (IsIceberg()) {
            if (displayQty_ >= qty) displayQty_ -= qty;
            else                    displayQty_ = 0;
            if (displayQty_ == 0 && remainingQty_ > 0)
                displayQty_ = std::min(peakQty_, remainingQty_);
        } else {
            displayQty_ = remainingQty_;
        }

        if (remainingQty_ == 0) status_ = OrderStatus::Filled;
        else if (qty > 0)       status_ = OrderStatus::PartiallyFilled;
    }

    void Cancel() noexcept { status_ = OrderStatus::Cancelled; }

    void ToGoodTillCancel(Price price) {
        if (orderType_ != OrderType::Market) [[unlikely]]
            throw std::logic_error(
                "Order " + std::to_string(orderId_) +
                " is not Market type, cannot convert to GTC");
        price_     = price;
        orderType_ = OrderType::GoodTillCancel;
    }

    void SetStatus(OrderStatus s) noexcept { status_ = s; }

private:
    // Members declared in initialization order (matches constructor init list)
    // to avoid -Wreorder warnings
    OrderType   orderType_;
    OrderId     orderId_;
    Side        side_;
    OrderStatus status_;
    Price       price_;
    Price       stopPrice_;
    Quantity    initialQty_;
    Quantity    remainingQty_;
    Quantity    displayQty_;
    Quantity    peakQty_;
    int64_t     timestamp_;
};

// BUG FIX: Original defined OrderPointer as Order* (raw pointer).
// All engine code uses shared_ptr semantics (lifetime managed, no manual delete).
// Raw pointer caused "cannot convert shared_ptr<Order> to Order*" errors.
using OrderPointer  = std::shared_ptr<Order>;
using OrderPointers = std::list<OrderPointer>;