-
Notifications
You must be signed in to change notification settings - Fork 1
/
ordersOnly.ipl
138 lines (116 loc) · 2.99 KB
/
ordersOnly.ipl
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
//
// Imandra Inc.
// Copyright (c) 2024
//
// Minimal FIX 4.4 model
//
//
// For further info see https://docs.imandra.ai
//
//
import FIX_4_4
using OrdType {Limit Market}
//
// Import inbound NewOrderSingle message
//
message NewOrderSingle {
req ClOrdID
req Side
req TransactTime
req OrdType
req OrderQtyData.OrderQty
validate { state.live_order == false }
}
//
// Import an outbound message we would send out
//
//
outbound message ExecutionReport {
req OrderID
req ExecID
req ExecType
req OrdStatus
req Side
req LeavesQty
req CumQty
req AvgPx
}
// Define our internal state
internal state {
// The following fields would be assigned to
assignable {
OrdStatus : OrdStatus = OrdStatus.New;
Side : Side = Side.Buy;
OrderID : string = "";
LeavesQty : Qty = 0.0;
CumQty : Qty = 0.0;
AvgPx : Price = 0.0;
}
live_order : bool = false;
// These are not required within the orders, etc...
OrdQty : Qty = 0.0;
current_time : UTCTimeOnly = UTCTimeOnly (8, 0, 0, None);
// Define the opening and closing times
opening_time : UTCTimeOnly = UTCTimeOnly (8, 0, 0, None);
closing_time : UTCTimeOnly = UTCTimeOnly (16, 0, 0, None);
}
// Define how the model should process a validated
// incoming NewOrderSingle message
receive ( msg : NewOrderSingle ) {
// Extract all relevant fields from within the message
assignFrom (msg, state)
state.live_order = true
send ExecutionReport {
state with
ExecID = "";
ExecType = ExecType.New;
}
}
// Handle rejections for 'NewOrderSingle'
reject ( msg : NewOrderSingle, rejectReason : string ) {
// A field is missing
missingfield : {
send ExecutionReport {
state with
ExecID = "";
ExecType = ExecType.Rejected;
}
}
// A field value is
invalidfield : {
send ExecutionReport {
state with
ExecID = "";
ExecType = ExecType.Rejected;
}
}
// One or more 'validate' statements is
invalid : {
send ExecutionReport {
state with
ExecID = "";
ExecType = ExecType.Rejected;
}
}
}
// Define action 'time_change'
action time_change {
new_time : UTCTimeOnly
validate { this.new_time >= state.current_time && state.OrdStatus == OrdStatus.New }
}
// Define logic for handling 'time_change' action above
receive ( act : time_change ) {
// Save the new time into internal state
state.current_time = act.new_time
// If it's past closing time, then cancel the order and send
// out the ExecutionReport
if ( act.new_time >= state.closing_time) then {
state.OrdStatus = OrdStatus.Expired
state.live_order = false
send ExecutionReport {
state with
ExecID = "";
ExecType = ExecType.New;
}
}
}