forked from Ishirv/market-maker
-
Notifications
You must be signed in to change notification settings - Fork 0
/
maker.cpp
223 lines (175 loc) · 6.26 KB
/
maker.cpp
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
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
#include <iostream>
#include <cmath>
#include <random>
#include <chrono>
#include <vector>
#include <algorithm>
#include <fstream>
#include <sstream>
#include <torch/torch.h>
#include <torch/script.h>
using namespace std;
const double INITIAL_PRICE = 100.0;
const double SPREAD = 1.0;
const double RISK_FREE_RATE = 0.05;
struct Option {
string symbol;
double strike;
double expiry;
double price;
int quantity;
};
struct Future {
string symbol;
double expiry;
double price;
int quantity;
};
double generateRandomNumber(double mean, double std_dev) {
unsigned seed = chrono::system_clock::now().time_since_epoch().count();
default_random_engine generator(seed);
normal_distribution<double> distribution(mean, std_dev);
return distribution(generator);
}
void calculateBidAsk(double mid_price, double& bid_price, double& ask_price) {
double half_spread = SPREAD / 2.0;
bid_price = mid_price - half_spread;
ask_price = mid_price + half_spread;
}
double blackScholes(double S, double K, double T, double r, double sigma, bool isCall) {
double d1 = (log(S / K) + (r + 0.5 * sigma * sigma) * T) / (sigma * sqrt(T));
double d2 = d1 - sigma * sqrt(T);
if (isCall) {
double call_price = S * exp(-r * T) * N(d1) - K * exp(-r * T) * N(d2);
return call_price;
} else {
double put_price = K * exp(-r * T) * N(-d2) - S * exp(-r * T) * N(-d1);
return put_price;
}
}
double N(double x) {
return 0.5 * (1 + erf(x / sqrt(2)));
}
void handleBuyOrder(const Option& option, double bid_price, double& optionsPnL) {
double pnl = (option.price - bid_price) * option.quantity;
optionsPnL += pnl;
}
void handleSellOrder(const Option& option, double ask_price, double& optionsPnL) {
double pnl = (ask_price - option.price) * option.quantity;
optionsPnL += pnl;
}
void handleBuyOrder(const Future& future, double bid_price, double& futuresPnL) {
double pnl = (future.price - bid_price) * future.quantity;
futuresPnL += pnl;
}
void handleSellOrder(const Future& future, double ask_price, double& futuresPnL) {
double pnl = (ask_price - future.price) * future.quantity;
futuresPnL += pnl;
}
torch::Tensor loadTrainingData(const string& file_path) {
ifstream file(file_path);
vector<vector<float>> data;
string line;
while (getline(file, line)) {
istringstream iss(line);
vector<float> row;
float val;
while (iss >> val) {
row.push_back(val);
}
data.push_back(row);
}
file.close();
auto options_data = torch::from_blob(data.data(), {data.size(), data[0].size()});
return options_data;
}
torch::nn::Sequential trainVolatilityModel(torch::Tensor training_data) {
torch::manual_seed(0);
auto dtype = torch::kFloat32;
auto device = torch::kCPU;
int input_size = training_data.size(1);
int hidden_size = 32;
int output_size = 1;
int num_layers = 2;
torch::nn::Sequential model(
torch::nn::LSTM(torch::nn::LSTMOptions(input_size, hidden_size).num_layers(num_layers)),
torch::nn::Linear(hidden_size, output_size)
);
model->to(dtype).to(device);
torch::optim::Adam optimizer(model->parameters(), torch::optim::AdamOptions(0.001));
int num_epochs = 10;
int seq_length = 5;
for (int epoch = 0; epoch < num_epochs; ++epoch) {
for (int i = 0; i < training_data.size(0) - seq_length; ++i) {
torch::Tensor inputs = training_data.narrow(0, i, seq_length).unsqueeze(1);
torch::Tensor targets = training_data.narrow(0, i + seq_length, 1);
inputs = inputs.to(dtype).to(device);
targets = targets.to(dtype).to(device);
optimizer.zero_grad();
torch::Tensor outputs = model->forward(inputs);
torch::Tensor loss = torch::mse_loss(outputs, targets);
loss.backward();
optimizer.step();
}
}
return model;
}
double predictVolatility(const torch::nn::Sequential& model, double current_price) {
torch::NoGradGuard no_grad;
model->eval();
int input_size = model->named_parameters()["0.weight"].size(1);
torch::Tensor input = torch::empty({1, input_size});
input[0][0] = current_price;
torch::Tensor output = model->forward(input.unsqueeze(1));
double predicted_volatility = output[0][0].item<double>();
return predicted_volatility;
}
int main() {
double current_price = INITIAL_PRICE;
vector<Option> options{
{"AAPL", 120.0, 0.25, 0.0, 0},
{"GOOG", 2000.0, 0.5, 0.0, 0},
{"MSFT", 150.0, 0.75, 0.0, 0},
{"AMZN", 3000.0, 1.0, 0.0, 0}
};
vector<Future> futures{
{"CL", 1.0, 0.0, 0},
{"ES", 1.0, 0.0, 0},
{"NQ", 1.0, 0.0, 0},
{"GC", 1.0, 0.0, 0}
};
double optionsPnL = 0.0;
double futuresPnL = 0.0;
torch::Tensor training_data = loadTrainingData("volatility_data.csv");
torch::nn::Sequential volatilityModel = trainVolatilityModel(training_data);
for (int i = 1; i <= 10; ++i) {
double price_change = generateRandomNumber(0.0, predictVolatility(volatilityModel, current_price));
double mid_price = current_price + price_change;
double bid_price, ask_price;
calculateBidAsk(mid_price, bid_price, ask_price);
current_price = mid_price;
for (auto& option : options) {
option.price = blackScholes(current_price, option.strike, option.expiry, RISK_FREE_RATE, predictVolatility(volatilityModel, current_price), true
for (auto& future : futures) {
future.price = current_price;
}
// Handle buy and sell orders for options
for (auto& option : options) {
if (option.quantity > 0) {
handleSellOrder(option, ask_price, optionsPnL);
} else if (option.quantity < 0) {
handleBuyOrder(option, bid_price, optionsPnL);
}
}
// Handle buy and sell orders for futures
for (auto& future : futures) {
if (future.quantity > 0) {
handleSellOrder(future, ask_price, futuresPnL);
} else if (future.quantity < 0) {
handleBuyOrder(future, bid_price, futuresPnL);
}
}
}
cout << "Options PnL: " << optionsPnL << endl;
cout << "Futures PnL: " << futuresPnL << endl;
return 0;