hft-js 0.1.2 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/trader.ts CHANGED
@@ -20,6 +20,7 @@ import {
20
20
  OffsetType,
21
21
  OrderData,
22
22
  OrderFlag,
23
+ OrderStatistic,
23
24
  OrderStatus,
24
25
  PositionData,
25
26
  PositionDetail,
@@ -54,6 +55,7 @@ type CommissionRateQuery = {
54
55
  };
55
56
 
56
57
  type PositionInfo = Writeable<PositionData>;
58
+ type OrderStat = Writeable<OrderStatistic>;
57
59
 
58
60
  export class Trader extends CTPProvider implements ITraderProvider {
59
61
  private traderApi?: ctp.Trader;
@@ -74,6 +76,7 @@ export class Trader extends CTPProvider implements ITraderProvider {
74
76
  private readonly commRates: Map<string, ctp.InstrumentCommissionRateField>;
75
77
  private readonly placeOrders: Map<number, IPlaceOrderResultReceiver>;
76
78
  private readonly cancelOrders: Map<number, ICancelOrderResultReceiver>;
79
+ private readonly orderStatistics: Map<string, OrderStat>;
77
80
  private readonly marginRatesQueue: Denque<MarginRateQuery>;
78
81
  private readonly commRatesQueue: Denque<CommissionRateQuery>;
79
82
  private readonly accountsQueue: Denque<ITradingAccountsReceiver>;
@@ -102,6 +105,7 @@ export class Trader extends CTPProvider implements ITraderProvider {
102
105
  this.commRates = new Map();
103
106
  this.placeOrders = new Map();
104
107
  this.cancelOrders = new Map();
108
+ this.orderStatistics = new Map();
105
109
  this.marginRatesQueue = new Denque();
106
110
  this.commRatesQueue = new Denque();
107
111
  this.accountsQueue = new Denque();
@@ -151,6 +155,7 @@ export class Trader extends CTPProvider implements ITraderProvider {
151
155
  if (this.tradingDay !== tradingDay) {
152
156
  this.marginRates.clear();
153
157
  this.commRates.clear();
158
+ this.orderStatistics.clear();
154
159
  this.tradingDay = tradingDay;
155
160
  }
156
161
 
@@ -349,12 +354,28 @@ export class Trader extends CTPProvider implements ITraderProvider {
349
354
  orderData.volume,
350
355
  );
351
356
  }
357
+
358
+ const statistic = this._ensureOrderStatistic(symbol);
359
+
360
+ statistic.entrusts += 1;
352
361
  }
353
362
 
354
363
  this.receivers.forEach((receiver) => receiver.onEntrust(orderData));
355
364
  }
356
365
  break;
357
366
 
367
+ case "filled":
368
+ {
369
+ const symbol = this._toSymbol(order.InstrumentID);
370
+
371
+ if (symbol) {
372
+ const statistic = this._ensureOrderStatistic(symbol);
373
+
374
+ statistic.filleds += 1;
375
+ }
376
+ }
377
+ break;
378
+
358
379
  case "canceled":
359
380
  {
360
381
  const orderData = this._toOrderData(order);
@@ -376,6 +397,10 @@ export class Trader extends CTPProvider implements ITraderProvider {
376
397
  orderData.volume,
377
398
  );
378
399
  }
400
+
401
+ const statistic = this._ensureOrderStatistic(symbol);
402
+
403
+ statistic.cancels += 1;
379
404
  }
380
405
 
381
406
  this.receivers.forEach((receiver) => receiver.onCancel(orderData));
@@ -385,6 +410,14 @@ export class Trader extends CTPProvider implements ITraderProvider {
385
410
  case "rejected":
386
411
  {
387
412
  const orderData = this._toOrderData(order);
413
+ const symbol = this._toSymbol(order.InstrumentID);
414
+
415
+ if (symbol) {
416
+ const statistic = this._ensureOrderStatistic(symbol);
417
+
418
+ statistic.rejects += 1;
419
+ }
420
+
388
421
  this.receivers.forEach((receiver) => receiver.onReject(orderData));
389
422
  }
390
423
  break;
@@ -534,6 +567,7 @@ export class Trader extends CTPProvider implements ITraderProvider {
534
567
  if (options.isLast) {
535
568
  const positionDetails = this.positionDetails.map(
536
569
  this._toPositionDetail,
570
+ this,
537
571
  );
538
572
  const receivers = this.positionDetailsQueue.toArray();
539
573
 
@@ -615,6 +649,28 @@ export class Trader extends CTPProvider implements ITraderProvider {
615
649
  return this.tradingDay;
616
650
  }
617
651
 
652
+ getOrderStatistics() {
653
+ const statistics = Array.from(this.orderStatistics.values());
654
+ return statistics.map((stat) => Object.freeze({ ...stat }));
655
+ }
656
+
657
+ getOrderStatistic(symbol: string) {
658
+ const statistic = this.orderStatistics.get(symbol);
659
+
660
+ if (!statistic) {
661
+ return Object.freeze({
662
+ symbol: symbol,
663
+ places: 0,
664
+ entrusts: 0,
665
+ filleds: 0,
666
+ cancels: 0,
667
+ rejects: 0,
668
+ });
669
+ }
670
+
671
+ return Object.freeze({ ...statistic });
672
+ }
673
+
618
674
  queryCommissionRate(symbol: string, receiver: ICommissionRateReceiver) {
619
675
  const [instrumentId] = parseSymbol(symbol);
620
676
  const commRate = this.commRates.get(instrumentId);
@@ -850,6 +906,10 @@ export class Trader extends CTPProvider implements ITraderProvider {
850
906
  return;
851
907
  }
852
908
 
909
+ const statistic = this._ensureOrderStatistic(symbol);
910
+
911
+ statistic.places += 1;
912
+
853
913
  this.placeOrders.set(requestId, receiver);
854
914
 
855
915
  const receiptId = `${this.frontId}:${this.sessionId}:${orderRef}`;
@@ -1018,7 +1078,7 @@ export class Trader extends CTPProvider implements ITraderProvider {
1018
1078
  }
1019
1079
  }
1020
1080
 
1021
- private _ensurePositionInfo(symbol: string) {
1081
+ private _ensurePositionInfo(symbol: string): PositionInfo {
1022
1082
  let position = this.positions.get(symbol);
1023
1083
 
1024
1084
  if (!position) {
@@ -1041,6 +1101,25 @@ export class Trader extends CTPProvider implements ITraderProvider {
1041
1101
  return position;
1042
1102
  }
1043
1103
 
1104
+ private _ensureOrderStatistic(symbol: string): OrderStat {
1105
+ let statistic = this.orderStatistics.get(symbol);
1106
+
1107
+ if (!statistic) {
1108
+ statistic = {
1109
+ symbol: symbol,
1110
+ places: 0,
1111
+ entrusts: 0,
1112
+ filleds: 0,
1113
+ cancels: 0,
1114
+ rejects: 0,
1115
+ };
1116
+
1117
+ this.orderStatistics.set(symbol, statistic);
1118
+ }
1119
+
1120
+ return statistic;
1121
+ }
1122
+
1044
1123
  private _calcPosition(
1045
1124
  symbol: string,
1046
1125
  side: SideType,
@@ -1055,7 +1134,7 @@ export class Trader extends CTPProvider implements ITraderProvider {
1055
1134
  case "long":
1056
1135
  position.today.long.position += volume;
1057
1136
 
1058
- if (position.pending.long > volume) {
1137
+ if (position.pending.long >= volume) {
1059
1138
  position.pending.long -= volume;
1060
1139
  } else {
1061
1140
  position.pending.long = 0;
@@ -1065,7 +1144,7 @@ export class Trader extends CTPProvider implements ITraderProvider {
1065
1144
  case "short":
1066
1145
  position.today.short.position += volume;
1067
1146
 
1068
- if (position.pending.short > volume) {
1147
+ if (position.pending.short >= volume) {
1069
1148
  position.pending.short -= volume;
1070
1149
  } else {
1071
1150
  position.pending.short = 0;
@@ -1077,65 +1156,65 @@ export class Trader extends CTPProvider implements ITraderProvider {
1077
1156
  case "close":
1078
1157
  switch (side) {
1079
1158
  case "long":
1080
- if (position.history.long.position > volume) {
1081
- position.history.long.position -= volume;
1159
+ if (position.history.short.position >= volume) {
1160
+ position.history.short.position -= volume;
1082
1161
  } else {
1083
- const rest = volume - position.history.long.position;
1084
- position.history.long.position -= position.history.long.position;
1162
+ const rest = volume - position.history.short.position;
1163
+ position.history.short.position -=
1164
+ position.history.short.position;
1085
1165
 
1086
1166
  if (rest > 0) {
1087
- if (position.today.long.position > rest) {
1088
- position.today.long.position -= rest;
1167
+ if (position.today.short.position >= rest) {
1168
+ position.today.short.position -= rest;
1089
1169
  } else {
1090
- position.today.long.position = 0;
1170
+ position.today.short.position = 0;
1091
1171
  }
1092
1172
  }
1093
1173
  }
1094
1174
 
1095
- if (position.history.long.frozen > volume) {
1096
- position.history.long.frozen -= volume;
1175
+ if (position.history.short.frozen >= volume) {
1176
+ position.history.short.frozen -= volume;
1097
1177
  } else {
1098
- const rest = volume - position.history.long.frozen;
1099
- position.history.long.frozen -= position.history.long.frozen;
1178
+ const rest = volume - position.history.short.frozen;
1179
+ position.history.short.frozen -= position.history.short.frozen;
1100
1180
 
1101
1181
  if (rest > 0) {
1102
- if (position.today.long.frozen > rest) {
1103
- position.today.long.frozen -= rest;
1182
+ if (position.today.short.frozen >= rest) {
1183
+ position.today.short.frozen -= rest;
1104
1184
  } else {
1105
- position.today.long.frozen = 0;
1185
+ position.today.short.frozen = 0;
1106
1186
  }
1107
1187
  }
1108
1188
  }
1109
1189
  break;
1110
1190
 
1111
1191
  case "short":
1112
- if (position.history.short.position > volume) {
1113
- position.history.short.position -= volume;
1192
+ if (position.history.long.position >= volume) {
1193
+ position.history.long.position -= volume;
1114
1194
  } else {
1115
- const rest = volume - position.history.short.position;
1116
- position.history.short.position -=
1117
- position.history.short.position;
1195
+ const rest = volume - position.history.long.position;
1196
+ position.history.long.position -= position.history.long.position;
1118
1197
 
1119
1198
  if (rest > 0) {
1120
- if (position.today.short.position > rest) {
1121
- position.today.short.position -= rest;
1199
+ if (position.today.long.position >= rest) {
1200
+ position.today.long.position -= rest;
1122
1201
  } else {
1123
- position.today.short.position = 0;
1202
+ position.today.long.position = 0;
1124
1203
  }
1125
1204
  }
1126
1205
  }
1127
1206
 
1128
- if (position.history.short.frozen > volume) {
1129
- position.history.short.frozen -= volume;
1207
+ if (position.history.long.frozen >= volume) {
1208
+ position.history.long.frozen -= volume;
1130
1209
  } else {
1131
- const rest = volume - position.history.short.frozen;
1132
- position.history.short.frozen -= position.history.short.frozen;
1210
+ const rest = volume - position.history.long.frozen;
1211
+ position.history.long.frozen -= position.history.long.frozen;
1133
1212
 
1134
1213
  if (rest > 0) {
1135
- if (position.today.short.frozen > rest) {
1136
- position.today.short.frozen -= rest;
1214
+ if (position.today.long.frozen >= rest) {
1215
+ position.today.long.frozen -= rest;
1137
1216
  } else {
1138
- position.today.short.frozen = 0;
1217
+ position.today.long.frozen = 0;
1139
1218
  }
1140
1219
  }
1141
1220
  }
@@ -1146,30 +1225,30 @@ export class Trader extends CTPProvider implements ITraderProvider {
1146
1225
  case "close-today":
1147
1226
  switch (side) {
1148
1227
  case "long":
1149
- if (position.today.long.position > volume) {
1150
- position.today.long.position -= volume;
1228
+ if (position.today.short.position >= volume) {
1229
+ position.today.short.position -= volume;
1151
1230
  } else {
1152
- position.today.long.position = 0;
1231
+ position.today.short.position = 0;
1153
1232
  }
1154
1233
 
1155
- if (position.today.long.frozen > volume) {
1156
- position.today.long.frozen -= volume;
1234
+ if (position.today.short.frozen >= volume) {
1235
+ position.today.short.frozen -= volume;
1157
1236
  } else {
1158
- position.today.long.frozen = 0;
1237
+ position.today.short.frozen = 0;
1159
1238
  }
1160
1239
  break;
1161
1240
 
1162
1241
  case "short":
1163
- if (position.today.short.position > volume) {
1164
- position.today.short.position -= volume;
1242
+ if (position.today.long.position >= volume) {
1243
+ position.today.long.position -= volume;
1165
1244
  } else {
1166
- position.today.short.position = 0;
1245
+ position.today.long.position = 0;
1167
1246
  }
1168
1247
 
1169
- if (position.today.short.frozen > volume) {
1170
- position.today.short.frozen -= volume;
1248
+ if (position.today.long.frozen >= volume) {
1249
+ position.today.long.frozen -= volume;
1171
1250
  } else {
1172
- position.today.short.frozen = 0;
1251
+ position.today.long.frozen = 0;
1173
1252
  }
1174
1253
  break;
1175
1254
  }
@@ -1243,11 +1322,11 @@ export class Trader extends CTPProvider implements ITraderProvider {
1243
1322
  case "close":
1244
1323
  switch (side) {
1245
1324
  case "long":
1246
- position.history.long.frozen += volume;
1325
+ position.history.short.frozen += volume;
1247
1326
  break;
1248
1327
 
1249
1328
  case "short":
1250
- position.history.short.frozen += volume;
1329
+ position.history.long.frozen += volume;
1251
1330
  break;
1252
1331
  }
1253
1332
  break;
@@ -1255,11 +1334,11 @@ export class Trader extends CTPProvider implements ITraderProvider {
1255
1334
  case "close-today":
1256
1335
  switch (side) {
1257
1336
  case "long":
1258
- position.today.long.frozen += volume;
1337
+ position.today.short.frozen += volume;
1259
1338
  break;
1260
1339
 
1261
1340
  case "short":
1262
- position.today.short.frozen += volume;
1341
+ position.today.long.frozen += volume;
1263
1342
  break;
1264
1343
  }
1265
1344
  break;
@@ -1282,19 +1361,19 @@ export class Trader extends CTPProvider implements ITraderProvider {
1282
1361
  case "close":
1283
1362
  switch (side) {
1284
1363
  case "long":
1285
- if (position.history.long.frozen > volume) {
1286
- position.history.long.frozen -= volume;
1364
+ if (position.history.short.frozen >= volume) {
1365
+ position.history.short.frozen -= volume;
1287
1366
  } else {
1288
- position.history.long.frozen = 0;
1367
+ position.history.short.frozen = 0;
1289
1368
  }
1290
1369
 
1291
1370
  break;
1292
1371
 
1293
1372
  case "short":
1294
- if (position.history.short.frozen > volume) {
1295
- position.history.short.frozen -= volume;
1373
+ if (position.history.long.frozen >= volume) {
1374
+ position.history.long.frozen -= volume;
1296
1375
  } else {
1297
- position.history.short.frozen = 0;
1376
+ position.history.long.frozen = 0;
1298
1377
  }
1299
1378
  break;
1300
1379
  }
@@ -1303,18 +1382,18 @@ export class Trader extends CTPProvider implements ITraderProvider {
1303
1382
  case "close-today":
1304
1383
  switch (side) {
1305
1384
  case "long":
1306
- if (position.today.long.frozen > volume) {
1307
- position.today.long.frozen -= volume;
1385
+ if (position.today.short.frozen >= volume) {
1386
+ position.today.short.frozen -= volume;
1308
1387
  } else {
1309
- position.today.long.frozen = 0;
1388
+ position.today.short.frozen = 0;
1310
1389
  }
1311
1390
  break;
1312
1391
 
1313
1392
  case "short":
1314
- if (position.today.short.frozen > volume) {
1315
- position.today.short.frozen -= volume;
1393
+ if (position.today.long.frozen >= volume) {
1394
+ position.today.long.frozen -= volume;
1316
1395
  } else {
1317
- position.today.short.frozen = 0;
1396
+ position.today.long.frozen = 0;
1318
1397
  }
1319
1398
  break;
1320
1399
  }
package/src/typedef.ts CHANGED
@@ -141,7 +141,7 @@ export type OrderStatistic = Readonly<{
141
141
  symbol: string;
142
142
  places: number;
143
143
  entrusts: number;
144
- trades: number;
144
+ filleds: number;
145
145
  cancels: number;
146
146
  rejects: number;
147
147
  }>;