fixparser-plugin-mcp 9.1.7-38cee007 → 9.1.7-3c6fd297

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.
@@ -163,7 +163,7 @@ var toolSchemas = {
163
163
  }
164
164
  },
165
165
  executeOrder: {
166
- description: "Executes a verified order. verifyOrder must be called before executeOrder.",
166
+ description: "Executes a verified order. verifyOrder must be called before executeOrder. user has to explicitly allow executeOrder.",
167
167
  schema: {
168
168
  type: "object",
169
169
  properties: {
@@ -307,395 +307,19 @@ var toolSchemas = {
307
307
  },
308
308
  required: ["symbol"]
309
309
  }
310
- },
311
- technicalAnalysis: {
312
- description: "Performs comprehensive technical analysis on market data for a given symbol, including indicators like SMA, EMA, RSI, Bollinger Bands, and trading signals",
313
- schema: {
314
- type: "object",
315
- properties: {
316
- symbol: {
317
- type: "string",
318
- description: "The trading symbol to analyze (e.g., AAPL, MSFT, EURUSD)"
319
- }
320
- },
321
- required: ["symbol"]
322
- }
323
310
  }
324
311
  };
325
312
 
326
- // src/tools/analytics.ts
327
- function sum(numbers) {
328
- return numbers.reduce((acc, val) => acc + val, 0);
329
- }
330
- var TechnicalAnalyzer = class {
331
- prices;
332
- volumes;
333
- highs;
334
- lows;
335
- constructor(data) {
336
- this.prices = data.map((d) => d.trade > 0 ? d.trade : d.midPrice);
337
- this.volumes = data.map((d) => d.volume);
338
- this.highs = data.map((d) => d.tradingSessionHighPrice > 0 ? d.tradingSessionHighPrice : d.trade);
339
- this.lows = data.map((d) => d.tradingSessionLowPrice > 0 ? d.tradingSessionLowPrice : d.trade);
340
- }
341
- // Calculate Simple Moving Average
342
- calculateSMA(data, period) {
343
- const sma = [];
344
- for (let i = period - 1; i < data.length; i++) {
345
- const sum2 = data.slice(i - period + 1, i + 1).reduce((a, b) => a + b, 0);
346
- sma.push(sum2 / period);
347
- }
348
- return sma;
349
- }
350
- // Calculate Exponential Moving Average
351
- calculateEMA(data, period) {
352
- const multiplier = 2 / (period + 1);
353
- const ema = [data[0]];
354
- for (let i = 1; i < data.length; i++) {
355
- ema.push(data[i] * multiplier + ema[i - 1] * (1 - multiplier));
356
- }
357
- return ema;
358
- }
359
- // Calculate RSI
360
- calculateRSI(data, period = 14) {
361
- if (data.length < period + 1) return [];
362
- const changes = [];
363
- for (let i = 1; i < data.length; i++) {
364
- changes.push(data[i] - data[i - 1]);
365
- }
366
- const gains = changes.map((change) => change > 0 ? change : 0);
367
- const losses = changes.map((change) => change < 0 ? Math.abs(change) : 0);
368
- let avgGain = gains.slice(0, period).reduce((a, b) => a + b, 0) / period;
369
- let avgLoss = losses.slice(0, period).reduce((a, b) => a + b, 0) / period;
370
- const rsi = [];
371
- for (let i = period; i < changes.length; i++) {
372
- const rs = avgGain / avgLoss;
373
- rsi.push(100 - 100 / (1 + rs));
374
- avgGain = (avgGain * (period - 1) + gains[i]) / period;
375
- avgLoss = (avgLoss * (period - 1) + losses[i]) / period;
376
- }
377
- return rsi;
378
- }
379
- // Calculate Bollinger Bands
380
- calculateBollingerBands(data, period = 20, stdDev = 2) {
381
- if (data.length < period) return [];
382
- const sma = this.calculateSMA(data, period);
383
- const bands = [];
384
- for (let i = 0; i < sma.length; i++) {
385
- const dataSlice = data.slice(i, i + period);
386
- const mean = sma[i];
387
- const variance = dataSlice.reduce((sum2, price) => sum2 + (price - mean) ** 2, 0) / period;
388
- const standardDeviation = Math.sqrt(variance);
389
- bands.push({
390
- upper: mean + standardDeviation * stdDev,
391
- middle: mean,
392
- lower: mean - standardDeviation * stdDev
393
- });
394
- }
395
- return bands;
396
- }
397
- // Calculate maximum drawdown
398
- calculateMaxDrawdown(prices) {
399
- let maxPrice = prices[0];
400
- let maxDrawdown = 0;
401
- for (let i = 1; i < prices.length; i++) {
402
- if (prices[i] > maxPrice) {
403
- maxPrice = prices[i];
404
- }
405
- const drawdown = (maxPrice - prices[i]) / maxPrice;
406
- if (drawdown > maxDrawdown) {
407
- maxDrawdown = drawdown;
408
- }
409
- }
410
- return maxDrawdown;
411
- }
412
- // Calculate price changes for volatility
413
- calculatePriceChanges() {
414
- const changes = [];
415
- for (let i = 1; i < this.prices.length; i++) {
416
- changes.push((this.prices[i] - this.prices[i - 1]) / this.prices[i - 1]);
417
- }
418
- return changes;
419
- }
420
- // Generate comprehensive market analysis
421
- analyze() {
422
- const currentPrice = this.prices[this.prices.length - 1];
423
- const startPrice = this.prices[0];
424
- const sessionHigh = Math.max(...this.highs);
425
- const sessionLow = Math.min(...this.lows);
426
- const totalVolume = sum(this.volumes);
427
- const avgVolume = totalVolume / this.volumes.length;
428
- const priceChanges = this.calculatePriceChanges();
429
- const volatility = priceChanges.length > 0 ? Math.sqrt(
430
- priceChanges.reduce((sum2, change) => sum2 + change ** 2, 0) / priceChanges.length
431
- ) * Math.sqrt(252) * 100 : 0;
432
- const sessionReturn = (currentPrice - startPrice) / startPrice * 100;
433
- const pricePosition = (currentPrice - sessionLow) / (sessionHigh - sessionLow) * 100;
434
- const trueVWAP = this.prices.reduce((sum2, price, i) => sum2 + price * this.volumes[i], 0) / totalVolume;
435
- const momentum5 = this.prices.length > 5 ? (currentPrice - this.prices[Math.max(0, this.prices.length - 6)]) / this.prices[Math.max(0, this.prices.length - 6)] * 100 : 0;
436
- const momentum10 = this.prices.length > 10 ? (currentPrice - this.prices[Math.max(0, this.prices.length - 11)]) / this.prices[Math.max(0, this.prices.length - 11)] * 100 : 0;
437
- const maxDrawdown = this.calculateMaxDrawdown(this.prices);
438
- return {
439
- currentPrice,
440
- startPrice,
441
- sessionHigh,
442
- sessionLow,
443
- totalVolume,
444
- avgVolume,
445
- volatility,
446
- sessionReturn,
447
- pricePosition,
448
- trueVWAP,
449
- momentum5,
450
- momentum10,
451
- maxDrawdown
452
- };
453
- }
454
- // Generate technical indicators
455
- getTechnicalIndicators() {
456
- return {
457
- sma5: this.calculateSMA(this.prices, 5),
458
- sma10: this.calculateSMA(this.prices, 10),
459
- ema8: this.calculateEMA(this.prices, 8),
460
- ema21: this.calculateEMA(this.prices, 21),
461
- rsi: this.calculateRSI(this.prices, 14),
462
- bollinger: this.calculateBollingerBands(this.prices, 20, 2)
463
- };
464
- }
465
- // Generate trading signals
466
- generateSignals() {
467
- const analysis = this.analyze();
468
- let bullishSignals = 0;
469
- let bearishSignals = 0;
470
- const signals = [];
471
- if (analysis.currentPrice > analysis.trueVWAP) {
472
- signals.push(
473
- `\u2713 BULLISH: Price above VWAP (+${((analysis.currentPrice - analysis.trueVWAP) / analysis.trueVWAP * 100).toFixed(2)}%)`
474
- );
475
- bullishSignals++;
476
- } else {
477
- signals.push(
478
- `\u2717 BEARISH: Price below VWAP (${((analysis.currentPrice - analysis.trueVWAP) / analysis.trueVWAP * 100).toFixed(2)}%)`
479
- );
480
- bearishSignals++;
481
- }
482
- if (analysis.momentum5 > 0 && analysis.momentum10 > 0) {
483
- signals.push("\u2713 BULLISH: Positive momentum on both timeframes");
484
- bullishSignals++;
485
- } else if (analysis.momentum5 < 0 && analysis.momentum10 < 0) {
486
- signals.push("\u2717 BEARISH: Negative momentum on both timeframes");
487
- bearishSignals++;
488
- } else {
489
- signals.push("\u25D0 MIXED: Conflicting momentum signals");
490
- }
491
- const currentVolume = this.volumes[this.volumes.length - 1];
492
- const volumeRatio = currentVolume / analysis.avgVolume;
493
- if (volumeRatio > 1.2 && analysis.sessionReturn > 0) {
494
- signals.push("\u2713 BULLISH: Above-average volume supporting upward move");
495
- bullishSignals++;
496
- } else if (volumeRatio > 1.2 && analysis.sessionReturn < 0) {
497
- signals.push("\u2717 BEARISH: Above-average volume supporting downward move");
498
- bearishSignals++;
499
- } else {
500
- signals.push("\u25D0 NEUTRAL: Volume not providing clear direction");
501
- }
502
- if (analysis.pricePosition > 65 && analysis.volatility > 30) {
503
- signals.push("\u2717 BEARISH: High in range with elevated volatility - reversal risk");
504
- bearishSignals++;
505
- } else if (analysis.pricePosition < 35 && analysis.volatility > 30) {
506
- signals.push("\u2713 BULLISH: Low in range with volatility - potential bounce");
507
- bullishSignals++;
508
- } else {
509
- signals.push("\u25D0 NEUTRAL: Price position and volatility not extreme");
510
- }
511
- return { bullishSignals, bearishSignals, signals };
512
- }
513
- // Generate comprehensive JSON analysis
514
- generateJSONAnalysis(symbol) {
515
- const analysis = this.analyze();
516
- const indicators = this.getTechnicalIndicators();
517
- const signals = this.generateSignals();
518
- const currentSMA5 = indicators.sma5.length > 0 ? indicators.sma5[indicators.sma5.length - 1] : null;
519
- const currentSMA10 = indicators.sma10.length > 0 ? indicators.sma10[indicators.sma10.length - 1] : null;
520
- const currentEMA8 = indicators.ema8[indicators.ema8.length - 1];
521
- const currentEMA21 = indicators.ema21[indicators.ema21.length - 1];
522
- const currentRSI = indicators.rsi.length > 0 ? indicators.rsi[indicators.rsi.length - 1] : null;
523
- const currentBB = indicators.bollinger.length > 0 ? indicators.bollinger[indicators.bollinger.length - 1] : null;
524
- const currentVolume = this.volumes[this.volumes.length - 1];
525
- const volumeRatio = currentVolume / analysis.avgVolume;
526
- const currentDrawdown = (analysis.sessionHigh - analysis.currentPrice) / analysis.sessionHigh * 100;
527
- const rangeWidth = (analysis.sessionHigh - analysis.sessionLow) / analysis.sessionLow * 100;
528
- const priceVsVWAP = (analysis.currentPrice - analysis.trueVWAP) / analysis.trueVWAP * 100;
529
- const totalScore = signals.bullishSignals - signals.bearishSignals;
530
- const overallSignal = totalScore > 0 ? "BULLISH_BIAS" : totalScore < 0 ? "BEARISH_BIAS" : "NEUTRAL";
531
- const targetEntry = Math.max(analysis.sessionLow * 1.005, analysis.trueVWAP * 0.998);
532
- const stopLoss = analysis.sessionLow * 0.995;
533
- const profitTarget = analysis.sessionHigh * 0.995;
534
- const riskRewardRatio = (profitTarget - analysis.currentPrice) / (analysis.currentPrice - stopLoss);
535
- return {
536
- symbol,
537
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
538
- marketStructure: {
539
- currentPrice: analysis.currentPrice,
540
- startPrice: analysis.startPrice,
541
- sessionHigh: analysis.sessionHigh,
542
- sessionLow: analysis.sessionLow,
543
- rangeWidth,
544
- totalVolume: analysis.totalVolume,
545
- sessionPerformance: analysis.sessionReturn,
546
- positionInRange: analysis.pricePosition
547
- },
548
- volatility: {
549
- impliedVolatility: analysis.volatility,
550
- maxDrawdown: analysis.maxDrawdown * 100,
551
- currentDrawdown
552
- },
553
- technicalIndicators: {
554
- sma5: currentSMA5,
555
- sma10: currentSMA10,
556
- ema8: currentEMA8,
557
- ema21: currentEMA21,
558
- rsi: currentRSI,
559
- bollingerBands: currentBB ? {
560
- upper: currentBB.upper,
561
- middle: currentBB.middle,
562
- lower: currentBB.lower,
563
- position: (analysis.currentPrice - currentBB.lower) / (currentBB.upper - currentBB.lower) * 100
564
- } : null
565
- },
566
- volumeAnalysis: {
567
- currentVolume,
568
- averageVolume: Math.round(analysis.avgVolume),
569
- volumeRatio,
570
- trueVWAP: analysis.trueVWAP,
571
- priceVsVWAP
572
- },
573
- momentum: {
574
- momentum5: analysis.momentum5,
575
- momentum10: analysis.momentum10,
576
- sessionROC: analysis.sessionReturn
577
- },
578
- tradingSignals: {
579
- ...signals,
580
- overallSignal,
581
- signalScore: totalScore
582
- },
583
- riskManagement: {
584
- targetEntry,
585
- stopLoss,
586
- profitTarget,
587
- riskRewardRatio
588
- }
589
- };
590
- }
591
- };
592
- var createTechnicalAnalysisHandler = (marketDataPrices) => {
593
- return async (args) => {
594
- try {
595
- const symbol = args.symbol;
596
- const priceHistory = marketDataPrices.get(symbol) || [];
597
- if (priceHistory.length === 0) {
598
- return {
599
- content: [
600
- {
601
- type: "text",
602
- text: `No price data available for ${symbol}. Please request market data first.`,
603
- uri: "technicalAnalysis"
604
- }
605
- ]
606
- };
607
- }
608
- const analyzer = new TechnicalAnalyzer(priceHistory);
609
- const analysis = analyzer.generateJSONAnalysis(symbol);
610
- return {
611
- content: [
612
- {
613
- type: "text",
614
- text: `Technical Analysis for ${symbol}:
615
-
616
- ${JSON.stringify(analysis, null, 2)}`,
617
- uri: "technicalAnalysis"
618
- }
619
- ]
620
- };
621
- } catch (error) {
622
- return {
623
- content: [
624
- {
625
- type: "text",
626
- text: `Error performing technical analysis: ${error instanceof Error ? error.message : "Unknown error"}`,
627
- uri: "technicalAnalysis"
628
- }
629
- ],
630
- isError: true
631
- };
632
- }
633
- };
634
- };
635
-
636
313
  // src/tools/marketData.ts
637
314
  var import_fixparser = require("fixparser");
638
315
  var import_quickchart_js = __toESM(require("quickchart-js"), 1);
639
316
  var createMarketDataRequestHandler = (parser, pendingRequests) => {
640
317
  return async (args) => {
641
318
  try {
642
- parser.logger.log({
643
- level: "info",
644
- message: `Sending market data request for symbols: ${args.symbols.join(", ")}`
645
- });
646
319
  const response = new Promise((resolve) => {
647
320
  pendingRequests.set(args.mdReqID, resolve);
648
- parser.logger.log({
649
- level: "info",
650
- message: `Registered callback for market data request ID: ${args.mdReqID}`
651
- });
652
321
  });
653
- const entryTypes = args.mdEntryTypes || [
654
- import_fixparser.MDEntryType.Bid,
655
- import_fixparser.MDEntryType.Offer,
656
- import_fixparser.MDEntryType.Trade,
657
- import_fixparser.MDEntryType.IndexValue,
658
- import_fixparser.MDEntryType.OpeningPrice,
659
- import_fixparser.MDEntryType.ClosingPrice,
660
- import_fixparser.MDEntryType.SettlementPrice,
661
- import_fixparser.MDEntryType.TradingSessionHighPrice,
662
- import_fixparser.MDEntryType.TradingSessionLowPrice,
663
- import_fixparser.MDEntryType.VWAP,
664
- import_fixparser.MDEntryType.Imbalance,
665
- import_fixparser.MDEntryType.TradeVolume,
666
- import_fixparser.MDEntryType.OpenInterest,
667
- import_fixparser.MDEntryType.CompositeUnderlyingPrice,
668
- import_fixparser.MDEntryType.SimulatedSellPrice,
669
- import_fixparser.MDEntryType.SimulatedBuyPrice,
670
- import_fixparser.MDEntryType.MarginRate,
671
- import_fixparser.MDEntryType.MidPrice,
672
- import_fixparser.MDEntryType.EmptyBook,
673
- import_fixparser.MDEntryType.SettleHighPrice,
674
- import_fixparser.MDEntryType.SettleLowPrice,
675
- import_fixparser.MDEntryType.PriorSettlePrice,
676
- import_fixparser.MDEntryType.SessionHighBid,
677
- import_fixparser.MDEntryType.SessionLowOffer,
678
- import_fixparser.MDEntryType.EarlyPrices,
679
- import_fixparser.MDEntryType.AuctionClearingPrice,
680
- import_fixparser.MDEntryType.SwapValueFactor,
681
- import_fixparser.MDEntryType.DailyValueAdjustmentForLongPositions,
682
- import_fixparser.MDEntryType.CumulativeValueAdjustmentForLongPositions,
683
- import_fixparser.MDEntryType.DailyValueAdjustmentForShortPositions,
684
- import_fixparser.MDEntryType.CumulativeValueAdjustmentForShortPositions,
685
- import_fixparser.MDEntryType.FixingPrice,
686
- import_fixparser.MDEntryType.CashRate,
687
- import_fixparser.MDEntryType.RecoveryRate,
688
- import_fixparser.MDEntryType.RecoveryRateForLong,
689
- import_fixparser.MDEntryType.RecoveryRateForShort,
690
- import_fixparser.MDEntryType.MarketBid,
691
- import_fixparser.MDEntryType.MarketOffer,
692
- import_fixparser.MDEntryType.ShortSaleMinPrice,
693
- import_fixparser.MDEntryType.PreviousClosingPrice,
694
- import_fixparser.MDEntryType.ThresholdLimitPriceBanding,
695
- import_fixparser.MDEntryType.DailyFinancingValue,
696
- import_fixparser.MDEntryType.AccruedFinancingValue,
697
- import_fixparser.MDEntryType.TWAP
698
- ];
322
+ const entryTypes = args.mdEntryTypes || [import_fixparser.MDEntryType.Bid, import_fixparser.MDEntryType.Offer, import_fixparser.MDEntryType.TradeVolume];
699
323
  const messageFields = [
700
324
  new import_fixparser.Field(import_fixparser.Fields.MsgType, import_fixparser.Messages.MarketDataRequest),
701
325
  new import_fixparser.Field(import_fixparser.Fields.SenderCompID, parser.sender),
@@ -717,10 +341,6 @@ var createMarketDataRequestHandler = (parser, pendingRequests) => {
717
341
  });
718
342
  const mdr = parser.createMessage(...messageFields);
719
343
  if (!parser.connected) {
720
- parser.logger.log({
721
- level: "error",
722
- message: "Not connected. Cannot send market data request."
723
- });
724
344
  return {
725
345
  content: [
726
346
  {
@@ -732,16 +352,8 @@ var createMarketDataRequestHandler = (parser, pendingRequests) => {
732
352
  isError: true
733
353
  };
734
354
  }
735
- parser.logger.log({
736
- level: "info",
737
- message: `Sending market data request message: ${JSON.stringify(mdr?.toFIXJSON())}`
738
- });
739
355
  parser.send(mdr);
740
356
  const fixData = await response;
741
- parser.logger.log({
742
- level: "info",
743
- message: `Received market data response for request ID: ${args.mdReqID}`
744
- });
745
357
  return {
746
358
  content: [
747
359
  {
@@ -790,9 +402,6 @@ var createGetStockGraphHandler = (marketDataPrices) => {
790
402
  const offerData = priceHistory.map((point) => point.offer);
791
403
  const spreadData = priceHistory.map((point) => point.spread);
792
404
  const volumeData = priceHistory.map((point) => point.volume);
793
- const tradeData = priceHistory.map((point) => point.trade);
794
- const vwapData = priceHistory.map((point) => point.vwap);
795
- const twapData = priceHistory.map((point) => point.twap);
796
405
  const config = {
797
406
  type: "line",
798
407
  data: {
@@ -822,30 +431,6 @@ var createGetStockGraphHandler = (marketDataPrices) => {
822
431
  fill: false,
823
432
  tension: 0.4
824
433
  },
825
- {
826
- label: "Trade",
827
- data: tradeData,
828
- borderColor: "#ffc107",
829
- backgroundColor: "rgba(255, 193, 7, 0.1)",
830
- fill: false,
831
- tension: 0.4
832
- },
833
- {
834
- label: "VWAP",
835
- data: vwapData,
836
- borderColor: "#17a2b8",
837
- backgroundColor: "rgba(23, 162, 184, 0.1)",
838
- fill: false,
839
- tension: 0.4
840
- },
841
- {
842
- label: "TWAP",
843
- data: twapData,
844
- borderColor: "#6610f2",
845
- backgroundColor: "rgba(102, 16, 242, 0.1)",
846
- fill: false,
847
- tension: 0.4
848
- },
849
434
  {
850
435
  label: "Volume",
851
436
  data: volumeData,
@@ -891,7 +476,7 @@ var createGetStockGraphHandler = (marketDataPrices) => {
891
476
  content: [
892
477
  {
893
478
  type: "text",
894
- text: `Error: ${error instanceof Error ? error.message : "Failed to generate graph"}`,
479
+ text: `Error: ${error instanceof Error ? error.message : "Failed to generate chart"}`,
895
480
  uri: "getStockGraph"
896
481
  }
897
482
  ],
@@ -929,48 +514,7 @@ var createGetStockPriceHistoryHandler = (marketDataPrices) => {
929
514
  bid: point.bid,
930
515
  offer: point.offer,
931
516
  spread: point.spread,
932
- volume: point.volume,
933
- trade: point.trade,
934
- indexValue: point.indexValue,
935
- openingPrice: point.openingPrice,
936
- closingPrice: point.closingPrice,
937
- settlementPrice: point.settlementPrice,
938
- tradingSessionHighPrice: point.tradingSessionHighPrice,
939
- tradingSessionLowPrice: point.tradingSessionLowPrice,
940
- vwap: point.vwap,
941
- imbalance: point.imbalance,
942
- openInterest: point.openInterest,
943
- compositeUnderlyingPrice: point.compositeUnderlyingPrice,
944
- simulatedSellPrice: point.simulatedSellPrice,
945
- simulatedBuyPrice: point.simulatedBuyPrice,
946
- marginRate: point.marginRate,
947
- midPrice: point.midPrice,
948
- emptyBook: point.emptyBook,
949
- settleHighPrice: point.settleHighPrice,
950
- settleLowPrice: point.settleLowPrice,
951
- priorSettlePrice: point.priorSettlePrice,
952
- sessionHighBid: point.sessionHighBid,
953
- sessionLowOffer: point.sessionLowOffer,
954
- earlyPrices: point.earlyPrices,
955
- auctionClearingPrice: point.auctionClearingPrice,
956
- swapValueFactor: point.swapValueFactor,
957
- dailyValueAdjustmentForLongPositions: point.dailyValueAdjustmentForLongPositions,
958
- cumulativeValueAdjustmentForLongPositions: point.cumulativeValueAdjustmentForLongPositions,
959
- dailyValueAdjustmentForShortPositions: point.dailyValueAdjustmentForShortPositions,
960
- cumulativeValueAdjustmentForShortPositions: point.cumulativeValueAdjustmentForShortPositions,
961
- fixingPrice: point.fixingPrice,
962
- cashRate: point.cashRate,
963
- recoveryRate: point.recoveryRate,
964
- recoveryRateForLong: point.recoveryRateForLong,
965
- recoveryRateForShort: point.recoveryRateForShort,
966
- marketBid: point.marketBid,
967
- marketOffer: point.marketOffer,
968
- shortSaleMinPrice: point.shortSaleMinPrice,
969
- previousClosingPrice: point.previousClosingPrice,
970
- thresholdLimitPriceBanding: point.thresholdLimitPriceBanding,
971
- dailyFinancingValue: point.dailyFinancingValue,
972
- accruedFinancingValue: point.accruedFinancingValue,
973
- twap: point.twap
517
+ volume: point.volume
974
518
  }))
975
519
  },
976
520
  null,
@@ -985,7 +529,7 @@ var createGetStockPriceHistoryHandler = (marketDataPrices) => {
985
529
  content: [
986
530
  {
987
531
  type: "text",
988
- text: `Error: ${error instanceof Error ? error.message : "Failed to get price history"}`,
532
+ text: `Error: ${error instanceof Error ? error.message : "Failed to get stock price history"}`,
989
533
  uri: "getStockPriceHistory"
990
534
  }
991
535
  ],
@@ -1093,7 +637,7 @@ Parameters verified:
1093
637
  - Symbol: ${args.symbol}
1094
638
  - TimeInForce: ${args.timeInForce} (${timeInForceNames[args.timeInForce]})
1095
639
 
1096
- To execute this order, call the executeOrder tool with these exact same parameters. Important: The user has to explicitly confirm before executeOrder is called!`,
640
+ To execute this order, call the executeOrder tool with these exact same parameters.`,
1097
641
  uri: "verifyOrder"
1098
642
  }
1099
643
  ]
@@ -1289,210 +833,48 @@ var createToolHandlers = (parser, verifiedOrders, pendingRequests, marketDataPri
1289
833
  executeOrder: createExecuteOrderHandler(parser, verifiedOrders, pendingRequests),
1290
834
  marketDataRequest: createMarketDataRequestHandler(parser, pendingRequests),
1291
835
  getStockGraph: createGetStockGraphHandler(marketDataPrices),
1292
- getStockPriceHistory: createGetStockPriceHistoryHandler(marketDataPrices),
1293
- technicalAnalysis: createTechnicalAnalysisHandler(marketDataPrices)
836
+ getStockPriceHistory: createGetStockPriceHistoryHandler(marketDataPrices)
1294
837
  });
1295
838
 
1296
839
  // src/utils/messageHandler.ts
1297
840
  var import_fixparser3 = require("fixparser");
1298
- function getEnumValue(enumObj, name) {
1299
- return enumObj[name] || name;
1300
- }
1301
841
  function handleMessage(message, parser, pendingRequests, marketDataPrices, maxPriceHistory, onPriceUpdate) {
842
+ parser.logger.log({
843
+ level: "info",
844
+ message: `MCP Server received message: ${message.messageType}: ${message.description}`
845
+ });
1302
846
  const msgType = message.messageType;
1303
- if (msgType === import_fixparser3.Messages.MarketDataSnapshotFullRefresh || msgType === import_fixparser3.Messages.MarketDataIncrementalRefresh) {
847
+ if (msgType === import_fixparser3.Messages.MarketDataSnapshotFullRefresh) {
1304
848
  const symbol = message.getField(import_fixparser3.Fields.Symbol)?.value;
1305
- const fixJson = message.toFIXJSON();
1306
- const entries = fixJson.Body?.NoMDEntries || [];
1307
- const data = {
1308
- timestamp: Date.now(),
1309
- bid: 0,
1310
- offer: 0,
1311
- spread: 0,
1312
- volume: 0,
1313
- trade: 0,
1314
- indexValue: 0,
1315
- openingPrice: 0,
1316
- closingPrice: 0,
1317
- settlementPrice: 0,
1318
- tradingSessionHighPrice: 0,
1319
- tradingSessionLowPrice: 0,
1320
- vwap: 0,
1321
- imbalance: 0,
1322
- openInterest: 0,
1323
- compositeUnderlyingPrice: 0,
1324
- simulatedSellPrice: 0,
1325
- simulatedBuyPrice: 0,
1326
- marginRate: 0,
1327
- midPrice: 0,
1328
- emptyBook: 0,
1329
- settleHighPrice: 0,
1330
- settleLowPrice: 0,
1331
- priorSettlePrice: 0,
1332
- sessionHighBid: 0,
1333
- sessionLowOffer: 0,
1334
- earlyPrices: 0,
1335
- auctionClearingPrice: 0,
1336
- swapValueFactor: 0,
1337
- dailyValueAdjustmentForLongPositions: 0,
1338
- cumulativeValueAdjustmentForLongPositions: 0,
1339
- dailyValueAdjustmentForShortPositions: 0,
1340
- cumulativeValueAdjustmentForShortPositions: 0,
1341
- fixingPrice: 0,
1342
- cashRate: 0,
1343
- recoveryRate: 0,
1344
- recoveryRateForLong: 0,
1345
- recoveryRateForShort: 0,
1346
- marketBid: 0,
1347
- marketOffer: 0,
1348
- shortSaleMinPrice: 0,
1349
- previousClosingPrice: 0,
1350
- thresholdLimitPriceBanding: 0,
1351
- dailyFinancingValue: 0,
1352
- accruedFinancingValue: 0,
1353
- twap: 0
1354
- };
1355
- for (const entry of entries) {
1356
- const entryType = entry.MDEntryType;
1357
- const price = entry.MDEntryPx ? Number.parseFloat(entry.MDEntryPx) : 0;
1358
- const size = entry.MDEntrySize ? Number.parseFloat(entry.MDEntrySize) : 0;
1359
- const enumValue = getEnumValue(import_fixparser3.MDEntryType, entryType);
1360
- switch (enumValue) {
1361
- case import_fixparser3.MDEntryType.Bid:
1362
- data.bid = price;
1363
- break;
1364
- case import_fixparser3.MDEntryType.Offer:
1365
- data.offer = price;
1366
- break;
1367
- case import_fixparser3.MDEntryType.Trade:
1368
- data.trade = price;
1369
- break;
1370
- case import_fixparser3.MDEntryType.IndexValue:
1371
- data.indexValue = price;
1372
- break;
1373
- case import_fixparser3.MDEntryType.OpeningPrice:
1374
- data.openingPrice = price;
1375
- break;
1376
- case import_fixparser3.MDEntryType.ClosingPrice:
1377
- data.closingPrice = price;
1378
- break;
1379
- case import_fixparser3.MDEntryType.SettlementPrice:
1380
- data.settlementPrice = price;
1381
- break;
1382
- case import_fixparser3.MDEntryType.TradingSessionHighPrice:
1383
- data.tradingSessionHighPrice = price;
1384
- break;
1385
- case import_fixparser3.MDEntryType.TradingSessionLowPrice:
1386
- data.tradingSessionLowPrice = price;
1387
- break;
1388
- case import_fixparser3.MDEntryType.VWAP:
1389
- data.vwap = price;
1390
- break;
1391
- case import_fixparser3.MDEntryType.Imbalance:
1392
- data.imbalance = size;
1393
- break;
1394
- case import_fixparser3.MDEntryType.TradeVolume:
1395
- data.volume = size;
1396
- break;
1397
- case import_fixparser3.MDEntryType.OpenInterest:
1398
- data.openInterest = size;
1399
- break;
1400
- case import_fixparser3.MDEntryType.CompositeUnderlyingPrice:
1401
- data.compositeUnderlyingPrice = price;
1402
- break;
1403
- case import_fixparser3.MDEntryType.SimulatedSellPrice:
1404
- data.simulatedSellPrice = price;
1405
- break;
1406
- case import_fixparser3.MDEntryType.SimulatedBuyPrice:
1407
- data.simulatedBuyPrice = price;
1408
- break;
1409
- case import_fixparser3.MDEntryType.MarginRate:
1410
- data.marginRate = price;
1411
- break;
1412
- case import_fixparser3.MDEntryType.MidPrice:
1413
- data.midPrice = price;
1414
- break;
1415
- case import_fixparser3.MDEntryType.EmptyBook:
1416
- data.emptyBook = 1;
1417
- break;
1418
- case import_fixparser3.MDEntryType.SettleHighPrice:
1419
- data.settleHighPrice = price;
1420
- break;
1421
- case import_fixparser3.MDEntryType.SettleLowPrice:
1422
- data.settleLowPrice = price;
1423
- break;
1424
- case import_fixparser3.MDEntryType.PriorSettlePrice:
1425
- data.priorSettlePrice = price;
1426
- break;
1427
- case import_fixparser3.MDEntryType.SessionHighBid:
1428
- data.sessionHighBid = price;
1429
- break;
1430
- case import_fixparser3.MDEntryType.SessionLowOffer:
1431
- data.sessionLowOffer = price;
1432
- break;
1433
- case import_fixparser3.MDEntryType.EarlyPrices:
1434
- data.earlyPrices = price;
1435
- break;
1436
- case import_fixparser3.MDEntryType.AuctionClearingPrice:
1437
- data.auctionClearingPrice = price;
1438
- break;
1439
- case import_fixparser3.MDEntryType.SwapValueFactor:
1440
- data.swapValueFactor = price;
1441
- break;
1442
- case import_fixparser3.MDEntryType.DailyValueAdjustmentForLongPositions:
1443
- data.dailyValueAdjustmentForLongPositions = price;
1444
- break;
1445
- case import_fixparser3.MDEntryType.CumulativeValueAdjustmentForLongPositions:
1446
- data.cumulativeValueAdjustmentForLongPositions = price;
1447
- break;
1448
- case import_fixparser3.MDEntryType.DailyValueAdjustmentForShortPositions:
1449
- data.dailyValueAdjustmentForShortPositions = price;
1450
- break;
1451
- case import_fixparser3.MDEntryType.CumulativeValueAdjustmentForShortPositions:
1452
- data.cumulativeValueAdjustmentForShortPositions = price;
1453
- break;
1454
- case import_fixparser3.MDEntryType.FixingPrice:
1455
- data.fixingPrice = price;
1456
- break;
1457
- case import_fixparser3.MDEntryType.CashRate:
1458
- data.cashRate = price;
1459
- break;
1460
- case import_fixparser3.MDEntryType.RecoveryRate:
1461
- data.recoveryRate = price;
1462
- break;
1463
- case import_fixparser3.MDEntryType.RecoveryRateForLong:
1464
- data.recoveryRateForLong = price;
1465
- break;
1466
- case import_fixparser3.MDEntryType.RecoveryRateForShort:
1467
- data.recoveryRateForShort = price;
1468
- break;
1469
- case import_fixparser3.MDEntryType.MarketBid:
1470
- data.marketBid = price;
1471
- break;
1472
- case import_fixparser3.MDEntryType.MarketOffer:
1473
- data.marketOffer = price;
1474
- break;
1475
- case import_fixparser3.MDEntryType.ShortSaleMinPrice:
1476
- data.shortSaleMinPrice = price;
1477
- break;
1478
- case import_fixparser3.MDEntryType.PreviousClosingPrice:
1479
- data.previousClosingPrice = price;
1480
- break;
1481
- case import_fixparser3.MDEntryType.ThresholdLimitPriceBanding:
1482
- data.thresholdLimitPriceBanding = price;
1483
- break;
1484
- case import_fixparser3.MDEntryType.DailyFinancingValue:
1485
- data.dailyFinancingValue = price;
1486
- break;
1487
- case import_fixparser3.MDEntryType.AccruedFinancingValue:
1488
- data.accruedFinancingValue = price;
1489
- break;
1490
- case import_fixparser3.MDEntryType.TWAP:
1491
- data.twap = price;
1492
- break;
849
+ const entries = message.getField(import_fixparser3.Fields.NoMDEntries)?.value;
850
+ let bid = 0;
851
+ let offer = 0;
852
+ let volume = 0;
853
+ const entryTypes = message.getFields(import_fixparser3.Fields.MDEntryType);
854
+ const entryPrices = message.getFields(import_fixparser3.Fields.MDEntryPx);
855
+ const entrySizes = message.getFields(import_fixparser3.Fields.MDEntrySize);
856
+ if (entryTypes && entryPrices && entrySizes) {
857
+ for (let i = 0; i < entries; i++) {
858
+ const entryType = entryTypes[i]?.value;
859
+ const entryPrice = Number.parseFloat(entryPrices[i]?.value);
860
+ const entrySize = Number.parseFloat(entrySizes[i]?.value);
861
+ if (entryType === import_fixparser3.MDEntryType.Bid) {
862
+ bid = entryPrice;
863
+ } else if (entryType === import_fixparser3.MDEntryType.Offer) {
864
+ offer = entryPrice;
865
+ }
866
+ volume += entrySize;
1493
867
  }
1494
868
  }
1495
- data.spread = data.offer - data.bid;
869
+ const spread = offer - bid;
870
+ const timestamp = Date.now();
871
+ const data = {
872
+ timestamp,
873
+ bid,
874
+ offer,
875
+ spread,
876
+ volume
877
+ };
1496
878
  if (!marketDataPrices.has(symbol)) {
1497
879
  marketDataPrices.set(symbol, []);
1498
880
  }
@@ -1502,14 +884,6 @@ function handleMessage(message, parser, pendingRequests, marketDataPrices, maxPr
1502
884
  prices.splice(0, prices.length - maxPriceHistory);
1503
885
  }
1504
886
  onPriceUpdate?.(symbol, data);
1505
- const mdReqID = message.getField(import_fixparser3.Fields.MDReqID)?.value;
1506
- if (mdReqID) {
1507
- const callback = pendingRequests.get(mdReqID);
1508
- if (callback) {
1509
- callback(message);
1510
- pendingRequests.delete(mdReqID);
1511
- }
1512
- }
1513
887
  } else if (msgType === import_fixparser3.Messages.ExecutionReport) {
1514
888
  const reqId = message.getField(import_fixparser3.Fields.ClOrdID)?.value;
1515
889
  const callback = pendingRequests.get(reqId);
@@ -1538,7 +912,7 @@ var MCPLocal = class extends MCPBase {
1538
912
  */
1539
913
  marketDataPrices = /* @__PURE__ */ new Map();
1540
914
  /**
1541
- * Maximum number of price history entries to keep per symbol
915
+ * Maximum number of price points to store per symbol
1542
916
  * @private
1543
917
  */
1544
918
  MAX_PRICE_HISTORY = 1e5;