File size: 5,613 Bytes
a3b10ab
 
 
 
 
44cddac
 
 
a3b10ab
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
44cddac
a3b10ab
 
 
 
 
 
44cddac
 
a3b10ab
44cddac
 
a3b10ab
 
 
 
 
 
 
 
 
 
 
 
44cddac
 
 
a3b10ab
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
44cddac
a3b10ab
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
44cddac
 
a3b10ab
 
 
 
 
 
 
44cddac
a3b10ab
 
 
 
 
 
 
 
 
 
 
 
 
 
 
44cddac
 
a3b10ab
 
44cddac
a3b10ab
44cddac
a3b10ab
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
// ════════════════════════════════════════════════════════════════════
// AITraderActor tests β€” strategy execution and order submission
// ════════════════════════════════════════════════════════════════════

#include "actors/AITraderActor.hpp"
#include "actors/OEGActor.hpp"
#include "actors/MECoreActor.hpp"
#include "actors/MDGActor.hpp"
#include "actors/ClearingHouseActor.hpp"
#include <iostream>
#include <cassert>

using namespace eunex;

static int testsPassed = 0;
static int testsFailed = 0;

#define TEST(name) \
    std::cout << "  " << #name << "... "; \
    try { test_##name(); std::cout << "PASS\n"; ++testsPassed; } \
    catch (const std::exception& e) { std::cout << "FAIL: " << e.what() << "\n"; ++testsFailed; }

#define ASSERT_EQ(a, b) \
    if ((a) != (b)) throw std::runtime_error( \
        std::string("Expected ") + std::to_string(static_cast<long long>(b)) + " got " + std::to_string(static_cast<long long>(a)))

#define ASSERT_TRUE(x) \
    if (!(x)) throw std::runtime_error("Assertion failed: " #x)

// ── Tests ─────────────────────────────────────────────────────────

void test_ai_trader_creates() {
    auto oe = std::make_unique<OEGActor>();
    std::vector<SymbolIndex_t> syms = {1, 2};
    auto ai = std::make_unique<AITraderActor>(oe->getActorId(), syms);
    ASSERT_TRUE(ai != nullptr);
}

void test_ai_submits_orders() {
    auto oe = std::make_unique<OEGActor>();
    auto md = std::make_unique<MDGActor>();

    auto book1 = std::make_unique<MECoreActor>(1, oe->getActorId(), md->getActorId());
    auto book2 = std::make_unique<MECoreActor>(2, oe->getActorId(), md->getActorId());
    oe->mapSymbol(1, book1->getActorId());
    oe->mapSymbol(2, book2->getActorId());

    std::vector<SymbolIndex_t> syms = {1, 2};
    auto ai = std::make_unique<AITraderActor>(oe->getActorId(), syms);

    ai->onCallback();

    ASSERT_TRUE(oe->getReports().size() > 0);
}

void test_ai_responds_to_book_update() {
    auto oe = std::make_unique<OEGActor>();
    auto md = std::make_unique<MDGActor>();
    auto book = std::make_unique<MECoreActor>(1, oe->getActorId(), md->getActorId());
    oe->mapSymbol(1, book->getActorId());

    std::vector<SymbolIndex_t> syms = {1};
    auto ai = std::make_unique<AITraderActor>(oe->getActorId(), syms);

    BookUpdateEvent bue;
    bue.symbolIdx = 1;
    bue.bidDepth = 1;
    bue.askDepth = 1;
    bue.bids[0] = {toFixedPrice(150.0), 100};
    bue.asks[0] = {toFixedPrice(151.0), 100};
    ai->onEvent(bue);

    ai->onCallback();

    ASSERT_TRUE(oe->getReports().size() > 0);
}

void test_ai_responds_to_trade() {
    auto oe = std::make_unique<OEGActor>();
    std::vector<SymbolIndex_t> syms = {1};
    auto ai = std::make_unique<AITraderActor>(oe->getActorId(), syms);

    Trade t{};
    t.symbolIdx = 1;
    t.price = toFixedPrice(150.0);
    t.quantity = 10;
    TradeEvent evt(t);

    for (int i = 0; i < 10; ++i) {
        t.price = toFixedPrice(150.0 + i * 0.5);
        TradeEvent e(t);
        ai->onEvent(e);
    }

    ASSERT_TRUE(true);
}

void test_ai_with_clearing_house() {
    auto oe = std::make_unique<OEGActor>();
    auto md = std::make_unique<MDGActor>();
    auto ch = std::make_unique<ClearingHouseActor>();

    for (int i = 0; i < 10; ++i) {
        ch->mapSession(static_cast<SessionId_t>(200 + i),
                       static_cast<MemberId_t>(i + 1));
    }

    auto book = std::make_unique<MECoreActor>(
        1, oe->getActorId(), md->getActorId(), ch->getActorId());
    oe->mapSymbol(1, book->getActorId());

    std::vector<SymbolIndex_t> syms = {1};
    auto ai = std::make_unique<AITraderActor>(oe->getActorId(), syms);

    for (int i = 0; i < 5; ++i) {
        ai->onCallback();
    }

    auto lb = ch->getLeaderboard();
    ASSERT_EQ(static_cast<int>(lb.size()), 10);
}

void test_multiple_symbols() {
    auto oe = std::make_unique<OEGActor>();
    auto md = std::make_unique<MDGActor>();

    std::vector<SymbolIndex_t> syms = {1, 2, 3, 4};
    std::vector<std::unique_ptr<MECoreActor>> books;
    for (auto s : syms) {
        auto book = std::make_unique<MECoreActor>(s, oe->getActorId(), md->getActorId());
        oe->mapSymbol(s, book->getActorId());
        books.push_back(std::move(book));
    }

    auto ai = std::make_unique<AITraderActor>(oe->getActorId(), syms);
    ai->onCallback();

    ASSERT_TRUE(oe->getReports().size() > 0);
}

// ── Main ──────────────────────────────────────────────────────────

int main() {
    std::cout << "AITrader Tests\n";
    std::cout << "═══════════════════════════════════════════\n";

    TEST(ai_trader_creates);
    TEST(ai_submits_orders);
    TEST(ai_responds_to_book_update);
    TEST(ai_responds_to_trade);
    TEST(ai_with_clearing_house);
    TEST(multiple_symbols);

    std::cout << "═══════════════════════════════════════════\n";
    std::cout << testsPassed << " passed, " << testsFailed << " failed\n";
    return testsFailed > 0 ? 1 : 0;
}