-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathsbb_server_v2.c
452 lines (356 loc) · 19.6 KB
/
sbb_server_v2.c
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
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <iostream>
#include "BondPrice_calculator.h"
#include <math.h>
#include "SBB_util.h"
#include <string.h>
#include "SBB_ratings.h"
#include <fstream>
#include <map>
#include <vector>
#include <algorithm>
#include "sbb_socket.h"
int calculateIndex(double confidenceInterval, int count){
//printf("confidenceInterval %d \n", confidenceInterval);
//printf("count %d \n", count);
int indexIntoPnLVector = (count - ((confidenceInterval/100)* count)) - 1; //has to deduct 1 because index starts from 0
//printf("Index into PnL Vector %d \n", indexIntoPnLVector);
return indexIntoPnLVector;
}
struct VaR{
double total_VaR;//total VaR
double creditRisk_component;//credit risk component of VaR
double interestRisk_component;//interest risk component of VaR
};
struct _by_totalVar{
bool operator()(VaR const &a, VaR const &b) {
return a.total_VaR < b.total_VaR;
}
};
main(int argc, const char* arg[])
{
/*
* get an internet domain socket
*/
int sd;
if ((sd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
perror("socket");
exit(1);
}
/*
* set up the socket structure
*/
struct sockaddr_in sock_addr;
memset(&sock_addr, 0, sizeof(sock_addr));
sock_addr.sin_family = AF_INET;
#ifdef SBB_ANY
/* set to INADDR_ANY if want server to be open to any client on any machine */
sock_addr.sin_addr.s_addr = INADDR_ANY;
#else
char hostname[128];
/*
* we'll default to this host and call a section 3 func to get this host
*/
if( gethostname(hostname,sizeof(hostname)) ){
fprintf(stderr," SBB gethostname(...) failed errno: %d\n", errno);
exit(1);
}
printf("SBB gethostname() local hostname: \"%s\"\n", hostname);
/*
* set up socket structure for our host machine
*/
struct hostent *hp;
if ((hp = gethostbyname(hostname)) == 0) {
fprintf(stderr,"SBB gethostbyname(...) failed errno: %d exiting...\n", errno);
exit(1);
}
sock_addr.sin_addr.s_addr = ((struct in_addr *)(hp->h_addr))->s_addr;
#endif
sock_addr.sin_port = htons(PORT);
/*
* bind the socket to the port number
*/
if (bind(sd, (struct sockaddr *) &sock_addr, sizeof(sock_addr)) == -1) {
perror("bind");
exit(1);
}
/*
* advertise we are available on this socket/port
*/
if (listen(sd, 5) == -1) {
perror("listen");
exit(1);
}
/*
* wait for a client to connect
*/
struct sockaddr_in sock_addr_from_client;
socklen_t addrlen = sizeof(sock_addr_from_client);
int sd_current;
if ((sd_current = accept(sd, (struct sockaddr *) &sock_addr_from_client, &addrlen)) == -1) {
fprintf(stderr,"SBB accept(...) failed errno: %d exiting...\n", errno);
exit(1);
}
printf("SBB client ip address: %s port: %x\n",
inet_ntoa(sock_addr_from_client.sin_addr),
PORT);
// ntohs(sock_addr_from_client.sin_port));
/*
* block on socket waiting for client message
*/
int ret = 0;
char msg[MSGSIZE];
fprintf(stderr," SBB: sizeof msg: %d\n", sizeof(msg));
while (ret = recv(sd_current, msg, sizeof(msg), 0) > 0) {
printf("SBB server received msg: [%s] from client\n", msg);
/*
* read in the tradingbook.txt and perform calculation
*/
//start the timer
double realtime = 0.0, usertime = 0.0, systemtime = 0.0;
SBB_util timer;
timer.start_clock();
//SBB_instrument_input_file _opening_trading_file((char*)arg[1]);//get opening trading book file name from run.sh
SBB_instrument_input_file _closing_trading_file((char*)arg[2]);//get closing trading book file name from run.sh
SBB_instrument_input_file yieldFile((char*)arg[3]);//get yieldcurve.txt from run.sh
int _opening_book_records_count = 0;
int _closinging_book_records_count = 0;
int yield_record_count = 0;
//SBB_instrument_fields* _opening_book_fields = _opening_trading_file.get_records(_opening_book_records_count); //load the opening trading book
SBB_instrument_fields* _closing_book_fields = _closing_trading_file.get_records(_closinging_book_records_count); //load the closing trading book
//printf("_opening_book_records_count..%d \n", _opening_book_records_count);
//printf("_closinging_book_records_count..%d \n", _closinging_book_records_count);
SBB_instrument_fields* _yc_fields = yieldFile.get_records(yield_record_count);//load the yield file
/*
SBB_bond_ratings bond_ratings;
double _total_opening_lgd_amount_adjusted = 0.0; //total portfolio LGD at the start of the day aka opening trading book
double _total_closing_lgd_amount_adjusted = 0.0; //total portfolio LGD at the end of the day aka closing trading book
double _total_opening_portfolio_amount = 0.0; //total portfolio amount at the start of the day
double _total_closing_portfolio_amount = 0.0; //total portfolio amount at the end of the day
*/
std::vector<double> _t2_file; //create a map that holds the treasury data for T2
std::vector<double> _t5_file; //create a map that holds the treasury data for T5
std::vector<double> _t10_file; //create a map that holds the treasury data for T10
std::vector<double> _t30_file; //create a map that holds the treasury data for T30
std::vector<VaR> bookVector;//trading book vector for PnL calculation
for(int i = 0 ; i < _closinging_book_records_count ; i++){
//Get LGD from start of the day
//_total_opening_lgd_amount_adjusted += (bond_ratings.LGD_given_SnP_Fitch(_opening_book_fields[i].Quality.c_str()) * _opening_book_fields[i].Amount); //calculate total LGD by multiplying LGD with the amount
//Get LGD from end of the day
//_total_closing_lgd_amount_adjusted += (bond_ratings.LGD_given_SnP_Fitch(_closing_book_fields[i].Quality.c_str()) * _closing_book_fields[i].Amount);
//this is temporary output for debugging
//printf("Opening lgd amount : %s %.3f %.3f \n",_opening_book_fields[i].SecurityID, _opening_bond_lgd, _opening_bond_lgd * _opening_book_fields[i].Amount);
//printf("Closing lgd amount : %s %.3f %.3f \n",_closing_book_fields[i].SecurityID, _closing_bond_lgd, _closing_bond_lgd * _closing_book_fields[i].Amount);
//Get total portfolio amount for beginning of the day and end of the day
// _total_opening_portfolio_amount += _opening_book_fields[i].Amount;
//_total_closing_portfolio_amount += _closing_book_fields[i].Amount;
/** BASE PRICE CALCULATION ***/
//Calculate the years to matuirty of this security using closing trading book Settlement Date and Maturity Date
BondPrice_calculator* priceCalculator;
int years_to_maturity = priceCalculator->calculate_years_to_maturity(_closing_book_fields[i].SettlementDate, _closing_book_fields[i].MaturityDate);
//printf("Years to maturity %d \n", years_to_maturity);
double yield_closing = _closing_book_fields[i].YieldRate;
if(strcmp(_closing_book_fields[i].RateType.c_str(), "SPREAD") == 0){//if RateType is SPREAD
double spread = _closing_book_fields[i].YieldRate;
int closet_months_to_treasury;
for(int index = 0 ; index < yield_record_count; index++){
//find the number of months to treasury
SBB_date bmDate;
SBB_date ymDate;
bmDate.set_from_yyyymmdd(_closing_book_fields[i].MaturityDate);
ymDate.set_from_yyyymmdd(_yc_fields[index].MaturityDate);
int months_to_treasury = 0;
/*
if(bmDate <= ymDate){
while (bmDate != ymDate) {
bmDate.add_months(1);
months_to_treasury++;
}
}
if(bmDate >= ymDate){
while (bmDate != ymDate) {
bmDate.add_months(-1);
months_to_treasury++;
}
}*/
months_to_treasury = bmDate.calculate_date_difference(ymDate);
if(index == 0){
closet_months_to_treasury = months_to_treasury;
yield_closing = _yc_fields[index].YieldRate + (spread * 0.01);
}else{
if(months_to_treasury < closet_months_to_treasury){
closet_months_to_treasury = months_to_treasury;
yield_closing = _yc_fields[index].YieldRate + ( spread * 0.01);
}
}
}
}
if(_closing_book_fields[i].CouponRate == 0.0){
priceCalculator = new Zero_Coupon_Calculator(yield_closing, _closing_book_fields[i].Frequency, years_to_maturity);
}
if(_closing_book_fields[i].CouponRate > 0.0){
priceCalculator = new Coupon_Bond_Calculator(yield_closing, _closing_book_fields[i].CouponRate, _closing_book_fields[i].Frequency, years_to_maturity);
// cout << priceCalculator->yield << " " << priceCalculator->frequency << " " << priceCalculator->yearsToMature <<endl;
}
double basePrice = priceCalculator->calculate_price();
//printf("***** Base Price is %.3f \n", basePrice);
/*** END OF BASE PRICE CALCULATION **** /
/*
* Get the historic data file name and open the files
*/
std::string security_filename = _closing_book_fields[i].SecurityID;
std::string filename = arg[4] + security_filename + ".txt";
SBB_instrument_input_file _historical_file((char*)filename.c_str());
int _historical_data_count = 0;
SBB_instrument_fields* _historic_data = _historical_file.get_historic_records(_historical_data_count);
/*
* Determine whether or not the historical file contain YIELD or SPREAD
*/
bool _is_yield = true;
if(_historical_data_count > 1){
if(strcmp(_historic_data[0].RateType.c_str(), "YIELD") == 0){
_is_yield = true;
}else{
_is_yield = false;
std::string _treasury_filename = arg[4];
if(_historic_data[0].BenchmarkTicker.compare("T2") == 0){
//printf("Initializing T2...\n");
_treasury_filename += "T2.txt";
SBB_instrument_input_file _treasury_file((char*)_treasury_filename.c_str());
_treasury_file.initialize_treasury_values(_t2_file); //initialize the historic t2 files data
}else if(_historic_data[0].BenchmarkTicker.compare("T5") == 0){
//printf("Initializing T5...\n");
_treasury_filename += "T5.txt";
SBB_instrument_input_file _treasury_file((char*)_treasury_filename.c_str());
_treasury_file.initialize_treasury_values(_t5_file); //initialize the historic t5 files data
}else if(_historic_data[0].BenchmarkTicker.compare("T10") == 0){
//printf("Initializing T10...\n");
_treasury_filename += "T10.txt";
SBB_instrument_input_file _treasury_file((char*)_treasury_filename.c_str());
_treasury_file.initialize_treasury_values(_t10_file); //initialize the historic t10 files data
}else if(_historic_data[0].BenchmarkTicker.compare("T30") == 0){
//printf("Initializing T30...\n");
_treasury_filename += "T30.txt";
SBB_instrument_input_file _treasury_file((char*)_treasury_filename.c_str());
_treasury_file.initialize_treasury_values(_t30_file); //initialize the historic t30 files data
}
}
}
/*
* If this is the first time, then initalize our trading book vector to 0.0 for calculation,
if(bookVector.size() <= 0){
bookVector.assign(_historical_data_count,0.0);
}
*/
//loop through
double prev_price = 0.0;
double prev_yield = 0.0;
std::vector<VaR> _PnL_Vector; //using full pricing
/** VaR calculation according his lecture ***/
for(int j = 0; j < _historical_data_count ; j++){
double yield = 0.0;
double bp_diff = 0.0;
double yield_diff = 0.0;
if( j == 0){
prev_yield = _historic_data[j].YieldRate;
}
bp_diff = _historic_data[j].YieldRate - prev_yield;
//printf("BP change is %.3f \n", bp_diff);
if(_is_yield){ //if the historic file is YIELD, then just use that yield rate
yield = yield_closing + bp_diff;
}else{ //if the historic file is SPREAD, then get the corresponding YIELD from T2 file, and add the corresponding spread
//printf("............ %d \n", _historic_data[j].SettlementDate-1);
if(j == 0){
yield = 0+ yield_closing + (bp_diff/100);
}else{
//std::string benchmark = _historic_data[j].BenchmarkTicker;
//benchmark = benchmark.erase(benchmark.length()-1);
//printf("Bench mark is %s \n", benchmark);
if(_historic_data[j].BenchmarkTicker.compare("T2") == 0){
yield_diff = _t2_file[j] - _t2_file[(j-1)];
//yield = (_t2_file[j] - _t2_file[(j-1)])+ yield_closing + (bp_diff/100);
}else if(_historic_data[j].BenchmarkTicker.compare("T5") == 0){
yield_diff = _t5_file[j] - _t5_file[(j-1)];
//yield = (_t5_file[j] - _t5_file[(j-1)])+ yield_closing + (bp_diff/100);
}else if(_historic_data[j].BenchmarkTicker.compare("T10") == 0){
yield_diff = _t10_file[j] - _t10_file[(j-1)];
//yield = (_t10_file[j] - _t10_file[(j-1)])+ yield_closing + (bp_diff/100);
}else if(_historic_data[j].BenchmarkTicker.compare("T30") == 0){
yield_diff = _t30_file[j] - _t30_file[(j-1)];
}
yield = yield_diff + yield_closing + (bp_diff/100);
}
}
//printf(".... Yield is %.3f\n", yield);
if(_closing_book_fields[i].CouponRate == 0.0){
priceCalculator = new Zero_Coupon_Calculator(yield, _closing_book_fields[i].Frequency, years_to_maturity);
}
if(_closing_book_fields[i].CouponRate > 0.0){
priceCalculator = new Coupon_Bond_Calculator(yield,
_closing_book_fields[i].CouponRate, _closing_book_fields[i].Frequency, years_to_maturity);
}
double newPrice = priceCalculator->calculate_price();
VaR v;
v.total_VaR = (newPrice - basePrice)/100* _closing_book_fields[i].Amount;
v.creditRisk_component = bp_diff; //please note that this is in decimal
v.interestRisk_component = yield_diff;
/*printf("Date: %d /// Total VaR is %.3f Credit component is %.3f Interest component is %.3f \n",
_closing_book_fields[i].SettlementDate, v.total_VaR,
(v.creditRisk_component/(v.interestRisk_component + v.creditRisk_component)) * v.total_VaR,
(v.interestRisk_component/(v.interestRisk_component + v.creditRisk_component)) * v.total_VaR);*/
_PnL_Vector.push_back(v);
prev_price = newPrice;
prev_yield = _historic_data[j].YieldRate;
}
_historical_file.free_records(); //free the records for the historic data
//_historical_file.close_file();
if(i == 0){
for(int tindex = 0; tindex < _PnL_Vector.size(); tindex++){
bookVector.push_back(_PnL_Vector[tindex]);
}
}else{
for(int tindex = 0; tindex < _PnL_Vector.size(); tindex++){
bookVector[tindex].total_VaR = bookVector[tindex].total_VaR + _PnL_Vector[tindex].total_VaR;
}
}
}
sort(bookVector.begin(), bookVector.end(),_by_totalVar());
VaR _var = bookVector[calculateIndex(99, bookVector.size())];
//printf("99 percent confidence interval for total number of %d of %.3f \n", bookVector.size(),_VaR);
//double _lgd_change = _total_opening_lgd_amount_adjusted - _total_closing_lgd_amount_adjusted;
//printf("LGD change : %.3f\n", _lgd_change);
//double _portfolio_amt_change = _total_opening_portfolio_amount - _total_closing_portfolio_amount;
//printf("Portfolio Amount change : %.3f\n", _portfolio_amt_change);
timer.end_clock(realtime, usertime, systemtime);
/*
* ack back to the client
*/
sprintf (msg, "%.3f %.3f %.3f %.3f %.3f %.3f", _var.total_VaR/1000,
_var.total_VaR*(_var.creditRisk_component/(_var.interestRisk_component+_var.creditRisk_component))/1000,
_var.total_VaR*(_var.interestRisk_component/(_var.interestRisk_component+_var.creditRisk_component))/1000, realtime, usertime, systemtime);
//strcpy(msg," this is the server message response!");
if (send(sd_current, msg, strlen(msg), 0) == -1) {
fprintf(stderr,"SBB send(...) failed errno: %d exiting...\n", errno);
exit(1);
}
}
if( 0 == ret ) {
printf("SBB client exited...\n");
/* For TCP sockets
* the return value 0 means the peer has closed its half side of the connection
*/
close(sd_current);
}else if( -1 == ret ) {
fprintf(stderr,"SBB recv(...) returned failed - errno: %d exiting...\n", errno);
exit(1);
}
close(sd);
}