fixparser-plugin-mcp 9.1.7-c415bb75 → 9.1.7-c6228661

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.
Files changed (35) hide show
  1. package/build/cjs/MCPLocal.js +422 -10
  2. package/build/cjs/MCPLocal.js.map +4 -4
  3. package/build/cjs/MCPRemote.js +422 -66
  4. package/build/cjs/MCPRemote.js.map +4 -4
  5. package/build/cjs/index.js +422 -66
  6. package/build/cjs/index.js.map +4 -4
  7. package/build/esm/MCPLocal.mjs +422 -10
  8. package/build/esm/MCPLocal.mjs.map +4 -4
  9. package/build/esm/MCPRemote.mjs +422 -66
  10. package/build/esm/MCPRemote.mjs.map +4 -4
  11. package/build/esm/index.mjs +422 -66
  12. package/build/esm/index.mjs.map +4 -4
  13. package/build-examples/cjs/example_mcp_local.js +9 -7
  14. package/build-examples/cjs/example_mcp_local.js.map +4 -4
  15. package/build-examples/cjs/example_mcp_remote.js +9 -7
  16. package/build-examples/cjs/example_mcp_remote.js.map +4 -4
  17. package/build-examples/esm/example_mcp_local.mjs +9 -7
  18. package/build-examples/esm/example_mcp_local.mjs.map +4 -4
  19. package/build-examples/esm/example_mcp_remote.mjs +9 -7
  20. package/build-examples/esm/example_mcp_remote.mjs.map +4 -4
  21. package/package.json +2 -2
  22. package/types/MCPBase.d.ts +0 -49
  23. package/types/MCPLocal.d.ts +0 -32
  24. package/types/MCPRemote.d.ts +0 -58
  25. package/types/PluginOptions.d.ts +0 -6
  26. package/types/index.d.ts +0 -3
  27. package/types/schemas/index.d.ts +0 -15
  28. package/types/schemas/marketData.d.ts +0 -48
  29. package/types/schemas/schemas.d.ts +0 -168
  30. package/types/tools/index.d.ts +0 -17
  31. package/types/tools/marketData.d.ts +0 -40
  32. package/types/tools/order.d.ts +0 -12
  33. package/types/tools/parse.d.ts +0 -5
  34. package/types/tools/parseToJSON.d.ts +0 -5
  35. package/types/utils/messageHandler.d.ts +0 -12
@@ -273,8 +273,331 @@ var toolSchemas = {
273
273
  },
274
274
  required: ["symbol"]
275
275
  }
276
+ },
277
+ technicalAnalysis: {
278
+ description: "Performs comprehensive technical analysis on market data for a given symbol, including indicators like SMA, EMA, RSI, Bollinger Bands, and trading signals",
279
+ schema: {
280
+ type: "object",
281
+ properties: {
282
+ symbol: {
283
+ type: "string",
284
+ description: "The trading symbol to analyze (e.g., AAPL, MSFT, EURUSD)"
285
+ }
286
+ },
287
+ required: ["symbol"]
288
+ }
289
+ }
290
+ };
291
+
292
+ // src/tools/analytics.ts
293
+ function sum(numbers) {
294
+ return numbers.reduce((acc, val) => acc + val, 0);
295
+ }
296
+ var TechnicalAnalyzer = class {
297
+ prices;
298
+ volumes;
299
+ highs;
300
+ lows;
301
+ constructor(data) {
302
+ this.prices = data.map((d) => d.trade > 0 ? d.trade : d.midPrice);
303
+ this.volumes = data.map((d) => d.volume);
304
+ this.highs = data.map((d) => d.tradingSessionHighPrice > 0 ? d.tradingSessionHighPrice : d.trade);
305
+ this.lows = data.map((d) => d.tradingSessionLowPrice > 0 ? d.tradingSessionLowPrice : d.trade);
306
+ }
307
+ // Calculate Simple Moving Average
308
+ calculateSMA(data, period) {
309
+ const sma = [];
310
+ for (let i = period - 1; i < data.length; i++) {
311
+ const sum2 = data.slice(i - period + 1, i + 1).reduce((a, b) => a + b, 0);
312
+ sma.push(sum2 / period);
313
+ }
314
+ return sma;
315
+ }
316
+ // Calculate Exponential Moving Average
317
+ calculateEMA(data, period) {
318
+ const multiplier = 2 / (period + 1);
319
+ const ema = [data[0]];
320
+ for (let i = 1; i < data.length; i++) {
321
+ ema.push(data[i] * multiplier + ema[i - 1] * (1 - multiplier));
322
+ }
323
+ return ema;
324
+ }
325
+ // Calculate RSI
326
+ calculateRSI(data, period = 14) {
327
+ if (data.length < period + 1) return [];
328
+ const changes = [];
329
+ for (let i = 1; i < data.length; i++) {
330
+ changes.push(data[i] - data[i - 1]);
331
+ }
332
+ const gains = changes.map((change) => change > 0 ? change : 0);
333
+ const losses = changes.map((change) => change < 0 ? Math.abs(change) : 0);
334
+ let avgGain = gains.slice(0, period).reduce((a, b) => a + b, 0) / period;
335
+ let avgLoss = losses.slice(0, period).reduce((a, b) => a + b, 0) / period;
336
+ const rsi = [];
337
+ for (let i = period; i < changes.length; i++) {
338
+ const rs = avgGain / avgLoss;
339
+ rsi.push(100 - 100 / (1 + rs));
340
+ avgGain = (avgGain * (period - 1) + gains[i]) / period;
341
+ avgLoss = (avgLoss * (period - 1) + losses[i]) / period;
342
+ }
343
+ return rsi;
344
+ }
345
+ // Calculate Bollinger Bands
346
+ calculateBollingerBands(data, period = 20, stdDev = 2) {
347
+ if (data.length < period) return [];
348
+ const sma = this.calculateSMA(data, period);
349
+ const bands = [];
350
+ for (let i = 0; i < sma.length; i++) {
351
+ const dataSlice = data.slice(i, i + period);
352
+ const mean = sma[i];
353
+ const variance = dataSlice.reduce((sum2, price) => sum2 + (price - mean) ** 2, 0) / period;
354
+ const standardDeviation = Math.sqrt(variance);
355
+ bands.push({
356
+ upper: mean + standardDeviation * stdDev,
357
+ middle: mean,
358
+ lower: mean - standardDeviation * stdDev
359
+ });
360
+ }
361
+ return bands;
362
+ }
363
+ // Calculate maximum drawdown
364
+ calculateMaxDrawdown(prices) {
365
+ let maxPrice = prices[0];
366
+ let maxDrawdown = 0;
367
+ for (let i = 1; i < prices.length; i++) {
368
+ if (prices[i] > maxPrice) {
369
+ maxPrice = prices[i];
370
+ }
371
+ const drawdown = (maxPrice - prices[i]) / maxPrice;
372
+ if (drawdown > maxDrawdown) {
373
+ maxDrawdown = drawdown;
374
+ }
375
+ }
376
+ return maxDrawdown;
377
+ }
378
+ // Calculate price changes for volatility
379
+ calculatePriceChanges() {
380
+ const changes = [];
381
+ for (let i = 1; i < this.prices.length; i++) {
382
+ changes.push((this.prices[i] - this.prices[i - 1]) / this.prices[i - 1]);
383
+ }
384
+ return changes;
385
+ }
386
+ // Generate comprehensive market analysis
387
+ analyze() {
388
+ const currentPrice = this.prices[this.prices.length - 1];
389
+ const startPrice = this.prices[0];
390
+ const sessionHigh = Math.max(...this.highs);
391
+ const sessionLow = Math.min(...this.lows);
392
+ const totalVolume = sum(this.volumes);
393
+ const avgVolume = totalVolume / this.volumes.length;
394
+ const priceChanges = this.calculatePriceChanges();
395
+ const volatility = priceChanges.length > 0 ? Math.sqrt(
396
+ priceChanges.reduce((sum2, change) => sum2 + change ** 2, 0) / priceChanges.length
397
+ ) * Math.sqrt(252) * 100 : 0;
398
+ const sessionReturn = (currentPrice - startPrice) / startPrice * 100;
399
+ const pricePosition = (currentPrice - sessionLow) / (sessionHigh - sessionLow) * 100;
400
+ const trueVWAP = this.prices.reduce((sum2, price, i) => sum2 + price * this.volumes[i], 0) / totalVolume;
401
+ 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;
402
+ 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;
403
+ const maxDrawdown = this.calculateMaxDrawdown(this.prices);
404
+ return {
405
+ currentPrice,
406
+ startPrice,
407
+ sessionHigh,
408
+ sessionLow,
409
+ totalVolume,
410
+ avgVolume,
411
+ volatility,
412
+ sessionReturn,
413
+ pricePosition,
414
+ trueVWAP,
415
+ momentum5,
416
+ momentum10,
417
+ maxDrawdown
418
+ };
419
+ }
420
+ // Generate technical indicators
421
+ getTechnicalIndicators() {
422
+ return {
423
+ sma5: this.calculateSMA(this.prices, 5),
424
+ sma10: this.calculateSMA(this.prices, 10),
425
+ ema8: this.calculateEMA(this.prices, 8),
426
+ ema21: this.calculateEMA(this.prices, 21),
427
+ rsi: this.calculateRSI(this.prices, 14),
428
+ bollinger: this.calculateBollingerBands(this.prices, 20, 2)
429
+ };
430
+ }
431
+ // Generate trading signals
432
+ generateSignals() {
433
+ const analysis = this.analyze();
434
+ let bullishSignals = 0;
435
+ let bearishSignals = 0;
436
+ const signals = [];
437
+ if (analysis.currentPrice > analysis.trueVWAP) {
438
+ signals.push(
439
+ `\u2713 BULLISH: Price above VWAP (+${((analysis.currentPrice - analysis.trueVWAP) / analysis.trueVWAP * 100).toFixed(2)}%)`
440
+ );
441
+ bullishSignals++;
442
+ } else {
443
+ signals.push(
444
+ `\u2717 BEARISH: Price below VWAP (${((analysis.currentPrice - analysis.trueVWAP) / analysis.trueVWAP * 100).toFixed(2)}%)`
445
+ );
446
+ bearishSignals++;
447
+ }
448
+ if (analysis.momentum5 > 0 && analysis.momentum10 > 0) {
449
+ signals.push("\u2713 BULLISH: Positive momentum on both timeframes");
450
+ bullishSignals++;
451
+ } else if (analysis.momentum5 < 0 && analysis.momentum10 < 0) {
452
+ signals.push("\u2717 BEARISH: Negative momentum on both timeframes");
453
+ bearishSignals++;
454
+ } else {
455
+ signals.push("\u25D0 MIXED: Conflicting momentum signals");
456
+ }
457
+ const currentVolume = this.volumes[this.volumes.length - 1];
458
+ const volumeRatio = currentVolume / analysis.avgVolume;
459
+ if (volumeRatio > 1.2 && analysis.sessionReturn > 0) {
460
+ signals.push("\u2713 BULLISH: Above-average volume supporting upward move");
461
+ bullishSignals++;
462
+ } else if (volumeRatio > 1.2 && analysis.sessionReturn < 0) {
463
+ signals.push("\u2717 BEARISH: Above-average volume supporting downward move");
464
+ bearishSignals++;
465
+ } else {
466
+ signals.push("\u25D0 NEUTRAL: Volume not providing clear direction");
467
+ }
468
+ if (analysis.pricePosition > 65 && analysis.volatility > 30) {
469
+ signals.push("\u2717 BEARISH: High in range with elevated volatility - reversal risk");
470
+ bearishSignals++;
471
+ } else if (analysis.pricePosition < 35 && analysis.volatility > 30) {
472
+ signals.push("\u2713 BULLISH: Low in range with volatility - potential bounce");
473
+ bullishSignals++;
474
+ } else {
475
+ signals.push("\u25D0 NEUTRAL: Price position and volatility not extreme");
476
+ }
477
+ return { bullishSignals, bearishSignals, signals };
478
+ }
479
+ // Generate comprehensive JSON analysis
480
+ generateJSONAnalysis(symbol) {
481
+ const analysis = this.analyze();
482
+ const indicators = this.getTechnicalIndicators();
483
+ const signals = this.generateSignals();
484
+ const currentSMA5 = indicators.sma5.length > 0 ? indicators.sma5[indicators.sma5.length - 1] : null;
485
+ const currentSMA10 = indicators.sma10.length > 0 ? indicators.sma10[indicators.sma10.length - 1] : null;
486
+ const currentEMA8 = indicators.ema8[indicators.ema8.length - 1];
487
+ const currentEMA21 = indicators.ema21[indicators.ema21.length - 1];
488
+ const currentRSI = indicators.rsi.length > 0 ? indicators.rsi[indicators.rsi.length - 1] : null;
489
+ const currentBB = indicators.bollinger.length > 0 ? indicators.bollinger[indicators.bollinger.length - 1] : null;
490
+ const currentVolume = this.volumes[this.volumes.length - 1];
491
+ const volumeRatio = currentVolume / analysis.avgVolume;
492
+ const currentDrawdown = (analysis.sessionHigh - analysis.currentPrice) / analysis.sessionHigh * 100;
493
+ const rangeWidth = (analysis.sessionHigh - analysis.sessionLow) / analysis.sessionLow * 100;
494
+ const priceVsVWAP = (analysis.currentPrice - analysis.trueVWAP) / analysis.trueVWAP * 100;
495
+ const totalScore = signals.bullishSignals - signals.bearishSignals;
496
+ const overallSignal = totalScore > 0 ? "BULLISH_BIAS" : totalScore < 0 ? "BEARISH_BIAS" : "NEUTRAL";
497
+ const targetEntry = Math.max(analysis.sessionLow * 1.005, analysis.trueVWAP * 0.998);
498
+ const stopLoss = analysis.sessionLow * 0.995;
499
+ const profitTarget = analysis.sessionHigh * 0.995;
500
+ const riskRewardRatio = (profitTarget - analysis.currentPrice) / (analysis.currentPrice - stopLoss);
501
+ return {
502
+ symbol,
503
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
504
+ marketStructure: {
505
+ currentPrice: analysis.currentPrice,
506
+ startPrice: analysis.startPrice,
507
+ sessionHigh: analysis.sessionHigh,
508
+ sessionLow: analysis.sessionLow,
509
+ rangeWidth,
510
+ totalVolume: analysis.totalVolume,
511
+ sessionPerformance: analysis.sessionReturn,
512
+ positionInRange: analysis.pricePosition
513
+ },
514
+ volatility: {
515
+ impliedVolatility: analysis.volatility,
516
+ maxDrawdown: analysis.maxDrawdown * 100,
517
+ currentDrawdown
518
+ },
519
+ technicalIndicators: {
520
+ sma5: currentSMA5,
521
+ sma10: currentSMA10,
522
+ ema8: currentEMA8,
523
+ ema21: currentEMA21,
524
+ rsi: currentRSI,
525
+ bollingerBands: currentBB ? {
526
+ upper: currentBB.upper,
527
+ middle: currentBB.middle,
528
+ lower: currentBB.lower,
529
+ position: (analysis.currentPrice - currentBB.lower) / (currentBB.upper - currentBB.lower) * 100
530
+ } : null
531
+ },
532
+ volumeAnalysis: {
533
+ currentVolume,
534
+ averageVolume: Math.round(analysis.avgVolume),
535
+ volumeRatio,
536
+ trueVWAP: analysis.trueVWAP,
537
+ priceVsVWAP
538
+ },
539
+ momentum: {
540
+ momentum5: analysis.momentum5,
541
+ momentum10: analysis.momentum10,
542
+ sessionROC: analysis.sessionReturn
543
+ },
544
+ tradingSignals: {
545
+ ...signals,
546
+ overallSignal,
547
+ signalScore: totalScore
548
+ },
549
+ riskManagement: {
550
+ targetEntry,
551
+ stopLoss,
552
+ profitTarget,
553
+ riskRewardRatio
554
+ }
555
+ };
276
556
  }
277
557
  };
558
+ var createTechnicalAnalysisHandler = (marketDataPrices) => {
559
+ return async (args) => {
560
+ try {
561
+ const symbol = args.symbol;
562
+ const priceHistory = marketDataPrices.get(symbol) || [];
563
+ if (priceHistory.length === 0) {
564
+ return {
565
+ content: [
566
+ {
567
+ type: "text",
568
+ text: `No price data available for ${symbol}. Please request market data first.`,
569
+ uri: "technicalAnalysis"
570
+ }
571
+ ]
572
+ };
573
+ }
574
+ const analyzer = new TechnicalAnalyzer(priceHistory);
575
+ const analysis = analyzer.generateJSONAnalysis(symbol);
576
+ return {
577
+ content: [
578
+ {
579
+ type: "text",
580
+ text: `Technical Analysis for ${symbol}:
581
+
582
+ ${JSON.stringify(analysis, null, 2)}`,
583
+ uri: "technicalAnalysis"
584
+ }
585
+ ]
586
+ };
587
+ } catch (error) {
588
+ return {
589
+ content: [
590
+ {
591
+ type: "text",
592
+ text: `Error performing technical analysis: ${error instanceof Error ? error.message : "Unknown error"}`,
593
+ uri: "technicalAnalysis"
594
+ }
595
+ ],
596
+ isError: true
597
+ };
598
+ }
599
+ };
600
+ };
278
601
 
279
602
  // src/tools/marketData.ts
280
603
  import { Field, Fields, MDEntryType, Messages } from "fixparser";
@@ -282,8 +605,16 @@ import QuickChart from "quickchart-js";
282
605
  var createMarketDataRequestHandler = (parser, pendingRequests) => {
283
606
  return async (args) => {
284
607
  try {
608
+ parser.logger.log({
609
+ level: "info",
610
+ message: `Sending market data request for symbols: ${args.symbols.join(", ")}`
611
+ });
285
612
  const response = new Promise((resolve) => {
286
613
  pendingRequests.set(args.mdReqID, resolve);
614
+ parser.logger.log({
615
+ level: "info",
616
+ message: `Registered callback for market data request ID: ${args.mdReqID}`
617
+ });
287
618
  });
288
619
  const entryTypes = args.mdEntryTypes || [
289
620
  MDEntryType.Bid,
@@ -352,6 +683,10 @@ var createMarketDataRequestHandler = (parser, pendingRequests) => {
352
683
  });
353
684
  const mdr = parser.createMessage(...messageFields);
354
685
  if (!parser.connected) {
686
+ parser.logger.log({
687
+ level: "error",
688
+ message: "Not connected. Cannot send market data request."
689
+ });
355
690
  return {
356
691
  content: [
357
692
  {
@@ -363,8 +698,16 @@ var createMarketDataRequestHandler = (parser, pendingRequests) => {
363
698
  isError: true
364
699
  };
365
700
  }
701
+ parser.logger.log({
702
+ level: "info",
703
+ message: `Sending market data request message: ${JSON.stringify(mdr?.toFIXJSON())}`
704
+ });
366
705
  parser.send(mdr);
367
706
  const fixData = await response;
707
+ parser.logger.log({
708
+ level: "info",
709
+ message: `Received market data response for request ID: ${args.mdReqID}`
710
+ });
368
711
  return {
369
712
  content: [
370
713
  {
@@ -413,6 +756,9 @@ var createGetStockGraphHandler = (marketDataPrices) => {
413
756
  const offerData = priceHistory.map((point) => point.offer);
414
757
  const spreadData = priceHistory.map((point) => point.spread);
415
758
  const volumeData = priceHistory.map((point) => point.volume);
759
+ const tradeData = priceHistory.map((point) => point.trade);
760
+ const vwapData = priceHistory.map((point) => point.vwap);
761
+ const twapData = priceHistory.map((point) => point.twap);
416
762
  const config = {
417
763
  type: "line",
418
764
  data: {
@@ -442,6 +788,30 @@ var createGetStockGraphHandler = (marketDataPrices) => {
442
788
  fill: false,
443
789
  tension: 0.4
444
790
  },
791
+ {
792
+ label: "Trade",
793
+ data: tradeData,
794
+ borderColor: "#ffc107",
795
+ backgroundColor: "rgba(255, 193, 7, 0.1)",
796
+ fill: false,
797
+ tension: 0.4
798
+ },
799
+ {
800
+ label: "VWAP",
801
+ data: vwapData,
802
+ borderColor: "#17a2b8",
803
+ backgroundColor: "rgba(23, 162, 184, 0.1)",
804
+ fill: false,
805
+ tension: 0.4
806
+ },
807
+ {
808
+ label: "TWAP",
809
+ data: twapData,
810
+ borderColor: "#6610f2",
811
+ backgroundColor: "rgba(102, 16, 242, 0.1)",
812
+ fill: false,
813
+ tension: 0.4
814
+ },
445
815
  {
446
816
  label: "Volume",
447
817
  data: volumeData,
@@ -487,7 +857,7 @@ var createGetStockGraphHandler = (marketDataPrices) => {
487
857
  content: [
488
858
  {
489
859
  type: "text",
490
- text: `Error: ${error instanceof Error ? error.message : "Failed to generate chart"}`,
860
+ text: `Error: ${error instanceof Error ? error.message : "Failed to generate graph"}`,
491
861
  uri: "getStockGraph"
492
862
  }
493
863
  ],
@@ -525,7 +895,48 @@ var createGetStockPriceHistoryHandler = (marketDataPrices) => {
525
895
  bid: point.bid,
526
896
  offer: point.offer,
527
897
  spread: point.spread,
528
- volume: point.volume
898
+ volume: point.volume,
899
+ trade: point.trade,
900
+ indexValue: point.indexValue,
901
+ openingPrice: point.openingPrice,
902
+ closingPrice: point.closingPrice,
903
+ settlementPrice: point.settlementPrice,
904
+ tradingSessionHighPrice: point.tradingSessionHighPrice,
905
+ tradingSessionLowPrice: point.tradingSessionLowPrice,
906
+ vwap: point.vwap,
907
+ imbalance: point.imbalance,
908
+ openInterest: point.openInterest,
909
+ compositeUnderlyingPrice: point.compositeUnderlyingPrice,
910
+ simulatedSellPrice: point.simulatedSellPrice,
911
+ simulatedBuyPrice: point.simulatedBuyPrice,
912
+ marginRate: point.marginRate,
913
+ midPrice: point.midPrice,
914
+ emptyBook: point.emptyBook,
915
+ settleHighPrice: point.settleHighPrice,
916
+ settleLowPrice: point.settleLowPrice,
917
+ priorSettlePrice: point.priorSettlePrice,
918
+ sessionHighBid: point.sessionHighBid,
919
+ sessionLowOffer: point.sessionLowOffer,
920
+ earlyPrices: point.earlyPrices,
921
+ auctionClearingPrice: point.auctionClearingPrice,
922
+ swapValueFactor: point.swapValueFactor,
923
+ dailyValueAdjustmentForLongPositions: point.dailyValueAdjustmentForLongPositions,
924
+ cumulativeValueAdjustmentForLongPositions: point.cumulativeValueAdjustmentForLongPositions,
925
+ dailyValueAdjustmentForShortPositions: point.dailyValueAdjustmentForShortPositions,
926
+ cumulativeValueAdjustmentForShortPositions: point.cumulativeValueAdjustmentForShortPositions,
927
+ fixingPrice: point.fixingPrice,
928
+ cashRate: point.cashRate,
929
+ recoveryRate: point.recoveryRate,
930
+ recoveryRateForLong: point.recoveryRateForLong,
931
+ recoveryRateForShort: point.recoveryRateForShort,
932
+ marketBid: point.marketBid,
933
+ marketOffer: point.marketOffer,
934
+ shortSaleMinPrice: point.shortSaleMinPrice,
935
+ previousClosingPrice: point.previousClosingPrice,
936
+ thresholdLimitPriceBanding: point.thresholdLimitPriceBanding,
937
+ dailyFinancingValue: point.dailyFinancingValue,
938
+ accruedFinancingValue: point.accruedFinancingValue,
939
+ twap: point.twap
529
940
  }))
530
941
  },
531
942
  null,
@@ -540,7 +951,7 @@ var createGetStockPriceHistoryHandler = (marketDataPrices) => {
540
951
  content: [
541
952
  {
542
953
  type: "text",
543
- text: `Error: ${error instanceof Error ? error.message : "Failed to get stock price history"}`,
954
+ text: `Error: ${error instanceof Error ? error.message : "Failed to get price history"}`,
544
955
  uri: "getStockPriceHistory"
545
956
  }
546
957
  ],
@@ -648,7 +1059,7 @@ Parameters verified:
648
1059
  - Symbol: ${args.symbol}
649
1060
  - TimeInForce: ${args.timeInForce} (${timeInForceNames[args.timeInForce]})
650
1061
 
651
- To execute this order, call the executeOrder tool with these exact same parameters.`,
1062
+ To execute this order, call the executeOrder tool with these exact same parameters. Important: The user has to explicitly confirm before executeOrder is called!`,
652
1063
  uri: "verifyOrder"
653
1064
  }
654
1065
  ]
@@ -844,16 +1255,16 @@ var createToolHandlers = (parser, verifiedOrders, pendingRequests, marketDataPri
844
1255
  executeOrder: createExecuteOrderHandler(parser, verifiedOrders, pendingRequests),
845
1256
  marketDataRequest: createMarketDataRequestHandler(parser, pendingRequests),
846
1257
  getStockGraph: createGetStockGraphHandler(marketDataPrices),
847
- getStockPriceHistory: createGetStockPriceHistoryHandler(marketDataPrices)
1258
+ getStockPriceHistory: createGetStockPriceHistoryHandler(marketDataPrices),
1259
+ technicalAnalysis: createTechnicalAnalysisHandler(marketDataPrices)
848
1260
  });
849
1261
 
850
1262
  // src/utils/messageHandler.ts
851
1263
  import { Fields as Fields3, MDEntryType as MDEntryType2, Messages as Messages3 } from "fixparser";
1264
+ function getEnumValue(enumObj, name) {
1265
+ return enumObj[name] || name;
1266
+ }
852
1267
  function handleMessage(message, parser, pendingRequests, marketDataPrices, maxPriceHistory, onPriceUpdate) {
853
- parser.logger.log({
854
- level: "info",
855
- message: `MCP Server received message: ${message.messageType}: ${message.description}`
856
- });
857
1268
  const msgType = message.messageType;
858
1269
  if (msgType === Messages3.MarketDataSnapshotFullRefresh || msgType === Messages3.MarketDataIncrementalRefresh) {
859
1270
  const symbol = message.getField(Fields3.Symbol)?.value;
@@ -911,7 +1322,8 @@ function handleMessage(message, parser, pendingRequests, marketDataPrices, maxPr
911
1322
  const entryType = entry.MDEntryType;
912
1323
  const price = entry.MDEntryPx ? Number.parseFloat(entry.MDEntryPx) : 0;
913
1324
  const size = entry.MDEntrySize ? Number.parseFloat(entry.MDEntrySize) : 0;
914
- switch (entryType) {
1325
+ const enumValue = getEnumValue(MDEntryType2, entryType);
1326
+ switch (enumValue) {
915
1327
  case MDEntryType2.Bid:
916
1328
  data.bid = price;
917
1329
  break;