Repository: hi-imcodeman/stock-nse-india Branch: master Commit: 7690080972e4 Files: 102 Total size: 1.9 MB Directory structure: gitextract_4l0czfbt/ ├── .eslintignore ├── .eslintrc ├── .github/ │ └── workflows/ │ ├── ci.yml │ ├── gpr_publish.yml │ └── npm_publish.yml ├── .gitignore ├── .husky/ │ └── pre-commit ├── .npmignore ├── Dockerfile ├── LICENSE ├── MCP_README.md ├── README.md ├── demo/ │ ├── README.md │ ├── mcp-client-demo.js │ └── memory-example.js ├── docs/ │ ├── .nojekyll │ ├── assets/ │ │ ├── highlight.css │ │ ├── main.js │ │ ├── search.js │ │ └── style.css │ ├── classes/ │ │ └── NseIndia.html │ ├── enums/ │ │ └── ApiList.html │ ├── index.html │ ├── interfaces/ │ │ ├── AllIndicesData.html │ │ ├── CircularsData.html │ │ ├── CommodityOptionChainData.html │ │ ├── CommodityRecords.html │ │ ├── DateRange.html │ │ ├── Datum.html │ │ ├── EquityCorporateInfo.html │ │ ├── EquityDetails.html │ │ ├── EquityHistoricalData.html │ │ ├── EquityHistoricalInfo.html │ │ ├── EquityInfo.html │ │ ├── EquityMaster.html │ │ ├── EquityMetadata.html │ │ ├── EquityOptionChainData.html │ │ ├── EquityOptionChainItem.html │ │ ├── EquityPreOpenMarket.html │ │ ├── EquityPriceInfo.html │ │ ├── EquitySecurityInfo.html │ │ ├── EquityTradeInfo.html │ │ ├── Filtered.html │ │ ├── GiftNifty.html │ │ ├── Glossary.html │ │ ├── Holiday.html │ │ ├── HolidaysBySegment.html │ │ ├── IndexDetails.html │ │ ├── IndexEquityInfo.html │ │ ├── IndexNamesData.html │ │ ├── IndexOptionChainData.html │ │ ├── IndexRecords.html │ │ ├── IndicativeNifty50.html │ │ ├── IntradayData.html │ │ ├── LatestCircularData.html │ │ ├── MarketCap.html │ │ ├── MarketState.html │ │ ├── MarketStatus.html │ │ ├── MarketTurnover.html │ │ ├── MergedDailyReportsData.html │ │ ├── OptionChainContractInfo.html │ │ ├── OptionsData.html │ │ ├── OptionsDetails.html │ │ ├── PreOpenDetails.html │ │ ├── PreOpenMarketData.html │ │ ├── SeriesData.html │ │ └── TechnicalIndicators.html │ └── modules.html ├── examples/ │ └── basic.js ├── jest.config.js ├── mcp-config.json ├── package.json ├── scripts/ │ └── setup-gpr.js ├── src/ │ ├── __snapshots__/ │ │ └── utils.spec.ts.snap │ ├── cli/ │ │ ├── @types/ │ │ │ ├── asciichart.d.ts │ │ │ └── ohlc.d.ts │ │ ├── api.ts │ │ └── index.ts │ ├── constants.ts │ ├── equity.graphql │ ├── helpers.spec.ts │ ├── helpers.ts │ ├── index.charting.spec.ts │ ├── index.spec.ts │ ├── index.ts │ ├── inputs.graphql │ ├── interface.ts │ ├── mcp/ │ │ ├── client/ │ │ │ └── mcp-client.ts │ │ ├── context-summarizer.ts │ │ ├── mcp-tools.ts │ │ ├── memory-manager.ts │ │ └── server/ │ │ ├── mcp-server-stdio.ts │ │ └── mcp-server.ts │ ├── root.graphql │ ├── root.resolver.ts │ ├── routes.ts │ ├── server.ts │ ├── stockIndex.graphql │ ├── swaggerDocOptions.ts │ ├── utils.spec.ts │ └── utils.ts └── tsconfig.json ================================================ FILE CONTENTS ================================================ ================================================ FILE: .eslintignore ================================================ node_modules build dist ================================================ FILE: .eslintrc ================================================ { "root": true, "parser": "@typescript-eslint/parser", "plugins": [ "@typescript-eslint" ], "extends": [ "eslint:recommended", "plugin:@typescript-eslint/eslint-recommended", "plugin:@typescript-eslint/recommended" ], "rules": { "max-len": ["error", { "code": 120 }], "no-console":["error", {"allow": ["warn", "error"]}], "@typescript-eslint/explicit-module-boundary-types":"error" } } ================================================ FILE: .github/workflows/ci.yml ================================================ name: CI on: push: schedule: - cron: '0 0 * * *' jobs: build: name: Test & Build runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - name: Use Node.js uses: actions/setup-node@v1 with: node-version: "18.x" - name: Install dependencies run: npm install - name: Test Package run: npm run test - name: Build Package run: npm run build ================================================ FILE: .github/workflows/gpr_publish.yml ================================================ name: Publish Package (GitHub) on: release: types: [created] jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 # Setup .npmrc file to publish to npm - uses: actions/setup-node@v1 with: node-version: "18.x" registry-url: "https://npm.pkg.github.com/hi-imcodeman" # Defaults to the user or organization that owns the workflow file scope: "@hi-imcodeman" - run: npm install - run: npm run gpr-setup - run: npm run build # Publish to GitHub Packages - run: npm publish env: NODE_AUTH_TOKEN: ${{ secrets.IMCODEMAN_PACKAGE_TOKEN }} ================================================ FILE: .github/workflows/npm_publish.yml ================================================ name: Publish Package (NPM) on: release: types: [created] jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 # Setup .npmrc file to publish to npm - uses: actions/setup-node@v1 with: node-version: "18.x" registry-url: "https://registry.npmjs.org" - run: npm install - run: npm run build - run: npm publish --access public env: NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} ================================================ FILE: .gitignore ================================================ # Logs logs *.log npm-debug.log* yarn-debug.log* yarn-error.log* lerna-debug.log* # Diagnostic reports (https://nodejs.org/api/report.html) report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json # Runtime data pids *.pid *.seed *.pid.lock # Directory for instrumented libs generated by jscoverage/JSCover lib-cov # Coverage directory used by tools like istanbul coverage *.lcov # nyc test coverage .nyc_output # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) .grunt # Bower dependency directory (https://bower.io/) bower_components # node-waf configuration .lock-wscript # Compiled binary addons (https://nodejs.org/api/addons.html) build/Release # Dependency directories node_modules/ jspm_packages/ # TypeScript v1 declaration files typings/ # TypeScript cache *.tsbuildinfo # Optional npm cache directory .npm # Optional eslint cache .eslintcache # Microbundle cache .rpt2_cache/ .rts2_cache_cjs/ .rts2_cache_es/ .rts2_cache_umd/ # Optional REPL history .node_repl_history # Output of 'npm pack' *.tgz # Yarn Integrity file .yarn-integrity # dotenv environment variables file .env .env.test # parcel-bundler cache (https://parceljs.org/) .cache # Next.js build output .next # Nuxt.js build / generate output .nuxt dist # Gatsby files .cache/ # Comment in the public line in if your project uses Gatsby and *not* Next.js # https://nextjs.org/blog/next-9-1#public-directory-support # public # vuepress build output .vuepress/dist # Serverless directories .serverless/ # FuseBox cache .fusebox/ # DynamoDB Local files .dynamodb/ # TernJS port file .tern-port #build build/ # MacOS store file .DS_Store # Memory data memory-data.json ================================================ FILE: .husky/pre-commit ================================================ #!/usr/bin/env sh . "$(dirname -- "$0")/_/husky.sh" npx lint-staged ================================================ FILE: .npmignore ================================================ src/ .github/ jest.config.js tsconfig.json scripts/ docs/ examples/ .eslintrc .eslintignore .gitignore *.map Dockerfile coverage ================================================ FILE: Dockerfile ================================================ FROM node:14 WORKDIR /app COPY src/ src/ COPY examples/ examples/ COPY package.json ./ COPY yarn.lock ./ COPY tsconfig.json ./ ENV TZ="Asia/Kolkata" RUN yarn install RUN yarn build ENV PORT=3001 EXPOSE 3001 CMD yarn start ================================================ FILE: LICENSE ================================================ MIT License Copyright (c) 2020 Hi! ImCodeMan Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: MCP_README.md ================================================ # NSE India MCP Server This is a Model Context Protocol (MCP) server that exposes all the functions from the NSE India stock market API library. ## What is MCP? Model Context Protocol (MCP) is a standard for AI assistants to communicate with external data sources and tools. It allows AI models to access real-time stock market data from the National Stock Exchange of India. ## Architecture The MCP server is built with a modular architecture for maintainability and consistency: - **`src/mcp/mcp-tools.ts`**: Common tools configuration and handler functions - **`src/mcp/server/mcp-server.ts`**: Stdio-based MCP server for local AI assistant integration - **`src/mcp/client/mcp-client.ts`**: OpenAI Functions-based MCP client for natural language queries All components share the same tool definitions and business logic, ensuring consistency and making maintenance easier. ## Benefits of Common Tools Configuration - **🔄 Consistency**: All server implementations use identical tool definitions and behavior - **🛠️ Maintainability**: Single source of truth for tool configurations and business logic - **📝 Easy Updates**: Add new tools or modify existing ones in one place - **🧪 Testing**: Unified testing approach across all server implementations - **📚 Documentation**: Centralized tool documentation and examples ## Available Tools The MCP server provides the following tools: ### Equity Data - `get_all_stock_symbols` - Get list of all NSE equity symbols - `get_equity_details` - Get equity details for a specific symbol - `get_equity_trade_info` - Get equity trade information for a specific symbol - `get_equity_corporate_info` - Get corporate information for a specific equity symbol - `get_equity_intraday_data` - Get intraday data for a specific equity symbol - `get_equity_historical_data` - Get historical data for a specific equity symbol - `get_equity_series` - Get series data for a specific equity symbol - `get_equity_option_chain` - Get option chain data for a specific equity symbol - `get_equity_technical_indicators` - Get technical indicators (RSI, MACD, Bollinger Bands, etc.) for a specific equity symbol ### Index Data - `get_equity_stock_indices` - Get equity stock indices for a specific index - `get_index_intraday_data` - Get intraday data for a specific index - `get_index_option_chain` - Get option chain data for a specific index - `get_index_option_chain_contract_info` - Get option chain contract information (expiry dates and strike prices) for a specific index ### Market Data - `get_market_status` - Get current market status - `get_market_turnover` - Get market turnover data - `get_pre_open_market_data` - Get pre-open market data - `get_all_indices` - Get list of all indices - `get_index_names` - Get list of index names ### Reports and Information - `get_glossary` - Get NSE glossary content - `get_trading_holidays` - Get list of trading holidays - `get_clearing_holidays` - Get list of clearing holidays - `get_circulars` - Get list of circulars - `get_latest_circulars` - Get list of latest circulars - `get_equity_master` - Get equity master data with categorized indices - `get_merged_daily_reports_capital` - Get merged daily reports for capital market - `get_merged_daily_reports_derivatives` - Get merged daily reports for derivatives - `get_merged_daily_reports_debt` - Get merged daily reports for debt market ### Commodity Data - `get_commodity_option_chain` - Get option chain data for a specific commodity symbol ### Analysis Tools - `get_gainers_and_losers_by_index` - Get top gainers and losers for a specific index - `get_most_active_equities` - Get most actively traded equities for a specific index, sorted by volume and value ## Installation 1. Install dependencies: ```bash yarn install ``` 2. Build the project: ```bash yarn build ``` ## Usage ### Starting the MCP Server #### Standard I/O (stdio) Server ```bash # Start the stdio MCP server yarn start:mcp # Test the stdio MCP server yarn test:mcp ``` ### Configuration #### Option 1: Using npx (Recommended for users who have installed the package) This is the easiest way to use the MCP server without cloning the repository. **Installation Steps:** 1. **Prerequisites**: Ensure Node.js 18+ is installed on your system ```bash node --version # Should be v18.0.0 or higher ``` 2. **Install the package** (optional but recommended for faster startup): ```bash npm install -g stock-nse-india ``` **Note**: If you don't install globally, `npx` will automatically download and cache the package on first use. The first run may take a few moments to download the package, but subsequent runs will be faster. **Configuration:** ```json { "mcpServers": { "npx-stock-nse-india": { "command": "npx", "args": ["stock-nse-india", "mcp"], "env": { "NODE_ENV": "production" } } } } ``` #### Option 2: Using local build (For developers with source code) If you have cloned the repository and built the project locally: ```json { "mcpServers": { "nse-india-stdio": { "command": "node", "args": ["build/mcp/server/mcp-server-stdio.js"], "env": { "NODE_ENV": "production" } } } } ``` **Prerequisites:** - Node.js 18+ installed - Repository cloned and dependencies installed (`npm install`) - Project built (`npm run build`) #### Configuring in Cursor IDE 1. **Open Cursor Settings**: - Press `Cmd+,` (Mac) or `Ctrl+,` (Windows/Linux) to open settings - Or go to `File → Preferences → Settings` 2. **Navigate to MCP Settings**: - Search for "MCP" or "Model Context Protocol" in settings - Go to `Settings → Features → Model Context Protocol` 3. **Add Server Configuration**: - Click "Edit in settings.json" or find the MCP configuration section - Add one of the configurations above (Option 1 is recommended for most users) - Save the configuration file 4. **Restart Cursor**: - Close and reopen Cursor IDE to load the MCP server - The server should appear in the MCP status indicator **Configuration File Location:** - **Mac/Linux**: `~/.cursor/mcp.json` or workspace-specific settings - **Windows**: `%APPDATA%\Cursor\mcp.json` or workspace-specific settings **Verification:** After configuration and restart, you should see the MCP server active in Cursor's status bar. You can then use natural language queries in Cursor's chat to access NSE India stock market data, such as: - "What is the current price of TCS?" - "Show me the top gainers in NIFTY 50" - "Get technical indicators for RELIANCE" ### Example Tool Calls #### Get all stock symbols ```json { "name": "get_all_stock_symbols", "arguments": {} } ``` #### Get equity details for TCS ```json { "name": "get_equity_details", "arguments": { "symbol": "TCS" } } ``` #### Get historical data for RELIANCE ```json { "name": "get_equity_historical_data", "arguments": { "symbol": "RELIANCE", "start_date": "2024-01-01", "end_date": "2024-01-31" } } ``` #### Get technical indicators for TCS ```json { "name": "get_equity_technical_indicators", "arguments": { "symbol": "TCS", "period": 200, "sma_periods": [5, 10, 20, 50], "ema_periods": [5, 10, 20, 50], "rsi_period": 14, "show_only_latest": true } } ``` #### Get gainers and losers for NIFTY 50 ```json { "name": "get_gainers_and_losers_by_index", "arguments": { "index_symbol": "NIFTY 50" } } ``` #### Get market status ```json { "name": "get_market_status", "arguments": {} } ``` ## Features - **Real-time Data**: Access live stock market data from NSE India - **Comprehensive Coverage**: All major NSE functions are exposed as MCP tools - **Error Handling**: Robust error handling with meaningful error messages - **Type Safety**: Full TypeScript support with proper type definitions - **Rate Limiting**: Built-in connection limiting to prevent API abuse - **Context Summarization**: Intelligent conversation history management with configurable thresholds ## MCP Client with Context Summarization The MCP Client (`MCPClient`) provides an OpenAI Functions-based interface for natural language queries with intelligent context management. ### Basic Usage ```typescript import { MCPClient } from 'stock-nse-india' const client = new MCPClient({ enableMemory: true, enableContextSummarization: true, memoryConfig: { contextWindowConfig: { maxTokens: 8000, reservedTokens: 2000, summarizationThreshold: 0.9, // Trigger at 90% minMessagesToSummarize: 6 } } }) // Process a natural language query const result = await client.processQuery({ query: "What is the current price of TCS?", sessionId: "user123", maxIterations: 5 }) ``` ### Context Summarization Configuration The context summarization system automatically manages conversation history to stay within token limits while preserving important information. #### Key Configuration Parameters ##### `summarizationThreshold` Controls when summarization is triggered as a percentage of `maxTokens`. **Recommended Values:** | Threshold | Use Case | Behavior | |-----------|----------|----------| | **0.9 (90%)** | **Recommended** | Less frequent summarization, more context preserved | | 0.8 (80%) | Balanced | Moderate summarization frequency | | 0.7 (70%) | Conservative | More frequent summarization | | 0.6 (60%) | Aggressive | Very frequent summarization | ##### `maxTokens` Maximum token limit for the context window. **Common Values:** - `8000` - Standard (GPT-4, GPT-3.5) - `16000` - Extended context models - `32000` - Large context models - `128000` - Very large context models (GPT-4 Turbo) ##### `reservedTokens` Tokens reserved for system prompt and response generation. **Guidelines:** - Typical: `2000-3000` tokens - Includes system prompt (~500-1000 tokens) - Includes response buffer (~1000-2000 tokens) ##### `minMessagesToSummarize` Minimum number of messages before summarization can occur. **Guidelines:** - Minimum: `4` (2 conversation pairs) - Recommended: `6-10` (3-5 pairs) - Prevents premature summarization #### Configuration Examples **Example 1: Recommended (Balanced)** ```typescript const client = new MCPClient({ enableMemory: true, enableContextSummarization: true, memoryConfig: { contextWindowConfig: { maxTokens: 8000, reservedTokens: 2000, summarizationThreshold: 0.9, // 90% - less frequent minMessagesToSummarize: 6 } } }) ``` **Expected Behavior:** - Summarization triggers at ~7200 tokens (90%) - 2-3 summarizations per 20 queries - More context preserved per query - Lower API costs **Example 2: Conservative (Frequent Summarization)** ```typescript const client = new MCPClient({ enableMemory: true, enableContextSummarization: true, memoryConfig: { contextWindowConfig: { maxTokens: 8000, reservedTokens: 2000, summarizationThreshold: 0.6, // 60% - more frequent minMessagesToSummarize: 6 } } }) ``` **Expected Behavior:** - Summarization triggers at ~4800 tokens (60%) - 4-6 summarizations per 20 queries - Less context per query - Higher API costs but safer **Example 3: Large Context Model** ```typescript const client = new MCPClient({ enableMemory: true, enableContextSummarization: true, memoryConfig: { contextWindowConfig: { maxTokens: 128000, // GPT-4 Turbo reservedTokens: 4000, summarizationThreshold: 0.95, // 95% - very rare minMessagesToSummarize: 20 } } }) ``` **Expected Behavior:** - Summarization triggers at ~121,600 tokens (95%) - Very rare summarization - Preserves entire conversation history - Higher token costs per query #### How It Works **1. Token Counting** The system estimates tokens for all messages: ``` totalTokens = systemPromptTokens + messageTokens + reservedTokens ``` **2. Threshold Check** Summarization triggers when: ``` totalTokens > (maxTokens × summarizationThreshold) AND messageCount >= minMessagesToSummarize ``` **3. Summarization Process** When triggered: 1. Keeps recent messages (targets 40% of maxTokens) 2. Summarizes older messages using AI 3. Replaces old messages with summary 4. Continues conversation with reduced context **4. Result** After summarization: - Token usage drops to ~40% of maxTokens - Recent messages preserved - Important information in summary - Ready for more conversation #### Monitoring Track these metrics to tune your configuration: ```typescript // Get context statistics const stats = await client.memoryManager.getContextStats(sessionId) console.log('Message Count:', stats.messageCount) console.log('Token Count:', stats.tokenCount.totalTokens) console.log('Needs Summarization:', stats.needsSummarization) console.log('Context Usage:', stats.contextWindowUsage + '%') // Get summarization history const history = client.getSummarizationHistory(sessionId) console.log('Total Summarizations:', history.length) ``` #### Tuning Guidelines **Choose Higher Threshold (0.8-0.9) When:** - ✅ You want to preserve more context - ✅ Cost is not a primary concern - ✅ Conversations are complex and interconnected - ✅ You have a larger context window available **Choose Lower Threshold (0.6-0.7) When:** - ✅ You want to minimize token costs - ✅ Conversations are independent queries - ✅ You have a smaller context window - ✅ You want guaranteed headroom #### Best Practices 1. **Start with 0.9 threshold** - Less intrusive, good for most use cases 2. **Monitor token usage** - Adjust based on actual patterns 3. **Consider your use case** - Independent queries vs. long conversations 4. **Test with real data** - Use the demo to see behavior 5. **Balance cost vs. context** - Higher threshold = more tokens but better context #### Troubleshooting **Too Many Summarizations** - **Increase** `summarizationThreshold` (0.6 → 0.9) - **Increase** `minMessagesToSummarize` **Token Overflow** - **Decrease** `summarizationThreshold` (0.9 → 0.7) - **Increase** `reservedTokens` **Context Loss** - **Increase** `summarizationThreshold` - **Increase** `maxTokens` (if model supports it) **High API Costs** - **Increase** `summarizationThreshold` (fewer summarizations) - Consider caching or simpler summarization ## Requirements - Node.js >= 18 - TypeScript - OpenAI API key (for MCP Client with context summarization) - All dependencies listed in package.json ## License MIT License - see LICENSE file for details ## Support For issues and questions, please visit the [GitHub repository](https://github.com/hi-imcodeman/stock-nse-india). ================================================ FILE: README.md ================================================ [![NPM](https://nodei.co/npm/stock-nse-india.png)](https://nodei.co/npm/stock-nse-india/) # National Stock Exchange - India (Unofficial) ![](https://github.com/hi-imcodeman/stock-nse-india/workflows/CI/badge.svg) ![npm](https://img.shields.io/npm/dt/stock-nse-india) ![NPM](https://img.shields.io/npm/l/stock-nse-india) ![GitHub Release Date - Published_At](https://img.shields.io/npm/v/stock-nse-india) ![GitHub top language](https://img.shields.io/github/languages/top/hi-imcodeman/stock-nse-india) A comprehensive package and API server for accessing equity/index details and historical data from the National Stock Exchange of India. This project provides both an NPM package for direct integration and a full-featured GraphQL/REST API server. **📚 [Documentation](https://hi-imcodeman.github.io/stock-nse-india)** | **🚀 [Examples](https://github.com/hi-imcodeman/stock-nse-india/tree/master/examples)** ## ✨ Features - **📦 NPM Package** - Direct integration into your Node.js projects - **🔌 GraphQL API** - Modern GraphQL interface with Apollo Server - **🌐 REST API** - Comprehensive REST endpoints with Swagger documentation - **🤖 MCP Server** - Model Context Protocol server for AI assistants - **💻 CLI Tool** - Command-line interface for quick data access - **🐳 Docker Support** - Containerized deployment - **🔒 CORS Configuration** - Configurable cross-origin resource sharing - **📊 Real-time Data** - Live market data and historical information - **📈 Multiple Data Types** - Equity, Index, Commodity, and Options data ## 🚀 Quick Start **⚠️ Prerequisites:** Node.js 18+ required ### As an NPM Package ```bash npm install stock-nse-india ``` ```javascript import { NseIndia } from "stock-nse-india"; const nseIndia = new NseIndia(); // Get all stock symbols const symbols = await nseIndia.getAllStockSymbols(); console.log(symbols); // Get equity details const details = await nseIndia.getEquityDetails('IRCTC'); console.log(details); // Get historical data const range = { start: new Date("2020-01-01"), end: new Date("2023-12-31") }; const historicalData = await nseIndia.getEquityHistoricalData('IRCTC', range); console.log(historicalData); ``` ### As an API Server ```bash # Clone and setup git clone https://github.com/hi-imcodeman/stock-nse-india.git cd stock-nse-india npm install # Start the server npm start ``` **🌐 Server URLs:** - **Main App:** http://localhost:3000 - **GraphQL Playground:** http://localhost:3000/graphql - **API Documentation:** http://localhost:3000/api-docs ## 📦 Installation ### Prerequisites - **Node.js:** Version 18 or higher - **npm:** Version 8 or higher (comes with Node.js 18+) ### NPM Package ```bash npm install stock-nse-india # or yarn add stock-nse-india ``` ### CLI Tool ```bash npm install -g stock-nse-india ``` ### Server Setup ```bash git clone https://github.com/hi-imcodeman/stock-nse-india.git cd stock-nse-india npm install npm start ``` ## 🔌 GraphQL API The project now includes a powerful GraphQL API for flexible data querying: ### Example Queries ```graphql # Get equity information query GetEquity { equities(symbolFilter: { symbols: ["IRCTC", "RELIANCE"] }) { symbol details { info { companyName industry isFNOSec } metadata { listingDate status } } } } # Get indices data query GetIndices { indices(filter: { filterBy: "NIFTY" }) { key index last variation percentChange } } ``` ### GraphQL Schema The API includes schemas for: - **Equity** - Stock information, metadata, and details - **Indices** - Market index data and performance - **Filters** - Flexible query filtering options ## 🤖 MCP Server The project includes a Model Context Protocol (MCP) server that allows AI assistants to access NSE India stock market data: ### What is MCP? Model Context Protocol (MCP) is a standard for AI assistants to communicate with external data sources and tools. This MCP server exposes all NSE India functions as tools that AI models can use. ### Architecture The MCP implementation is built with a modular architecture for maintainability and consistency: - **`src/mcp/mcp-tools.ts`**: Common tools configuration and handler functions shared across all implementations - **`src/mcp/server/mcp-server.ts`**: Stdio-based MCP server for local AI assistant integration - **`src/mcp/client/mcp-client.ts`**: OpenAI Functions-based MCP client for natural language queries All components share the same tool definitions and business logic, ensuring consistency and making maintenance easier. ### Benefits of Common Tools Configuration - **🔄 Consistency**: All server implementations use identical tool definitions and behavior - **🛠️ Maintainability**: Single source of truth for tool configurations and business logic - **📝 Easy Updates**: Add new tools or modify existing ones in one place - **🧪 Testing**: Unified testing approach across all server implementations - **📚 Documentation**: Centralized tool documentation and examples ### Available Tools The MCP server provides **30 tools** covering: - **Equity Data** - Stock details, trade info, corporate info, intraday data, historical data, technical indicators - **Index Data** - Market indices, intraday data, option chains, contract information - **Market Data** - Market status, turnover, pre-open data, all indices - **Reports** - Circulars, daily reports for capital/derivatives/debt markets - **Commodity Data** - Option chain data for commodities - **Analysis Tools** - Top gainers/losers, most active equities ### OpenAI Functions MCP Client The project includes an advanced MCP client that uses OpenAI's native function calling feature for intelligent query processing: #### Features - **🤖 Natural Language Processing**: Query data using plain English - **🔧 Automatic Tool Selection**: AI intelligently chooses the right NSE API tools - **📊 Real-time Data**: Access live market data, historical information, and more - **🎯 Smart Parameter Extraction**: Automatically extracts symbols, dates, and other parameters - **📈 Comprehensive Coverage**: Access to all 30 NSE India API endpoints - **🔄 Multiple Query Types**: Support for both simple and complex multi-step queries #### Query Methods - **`processQuery()`**: Single-round query processing for straightforward requests - **`processQueryWithMultipleFunctions()`**: Multi-step query processing for complex analysis #### Example Usage ```javascript import { mcpClient } from './mcp/client/mcp-client' // Simple query const response = await mcpClient.processQuery({ query: "What is the current price of TCS stock?", model: "gpt-4o-mini" }) // Complex multi-step query const complexResponse = await mcpClient.processQueryWithMemory({ query: "Compare the performance of Reliance and TCS over the last month and analyze their trends" }) ``` ### Usage #### Standard I/O (stdio) Server ```bash # Start the stdio MCP server npm run start:mcp # Test the stdio MCP server npm run test:mcp ``` ### Configuration #### Option 1: Using npx (Recommended for users who have installed the package) **Installation Steps:** 1. **Prerequisites**: Ensure Node.js 18+ is installed on your system ```bash node --version # Should be v18.0.0 or higher ``` 2. **Install the package** (optional but recommended for faster startup): ```bash npm install -g stock-nse-india ``` **Note**: If you don't install globally, `npx` will automatically download and cache the package on first use, which may take a few moments. **Configuration:** ```json { "mcpServers": { "npx-stock-nse-india": { "command": "npx", "args": ["stock-nse-india", "mcp"], "env": { "NODE_ENV": "production" } } } } ``` #### Option 2: Using local build (For developers with source code) ```json { "mcpServers": { "nse-india-stdio": { "command": "node", "args": ["build/mcp/server/mcp-server-stdio.js"], "env": { "NODE_ENV": "production" } } } } ``` #### Configuring in Cursor IDE 1. **Open Cursor Settings**: Press `Cmd+,` (Mac) or `Ctrl+,` (Windows/Linux) to open settings 2. **Navigate to MCP Settings**: Go to Settings → Features → Model Context Protocol 3. **Add Server Configuration**: Add either of the configurations above to your MCP settings 4. **Restart Cursor**: Restart Cursor IDE to load the MCP server Alternatively, you can directly edit the Cursor configuration file: - **Mac/Linux**: `~/.cursor/mcp.json` or in your workspace settings - **Windows**: `%APPDATA%\Cursor\mcp.json` After configuration, the MCP server will be available in Cursor's AI assistant, allowing you to query NSE India stock market data directly from the chat interface. For detailed MCP documentation, see [MCP_README.md](./MCP_README.md). ## 🌐 REST API Comprehensive REST endpoints with automatic Swagger documentation: ### Core Endpoints - `GET /` - Market status - `GET /api/marketStatus` - Market status information - `GET /api/glossary` - NSE glossary - `GET /api/equity/:symbol` - Equity details - `GET /api/equity/:symbol/historical` - Historical data - `GET /api/indices` - Market indices - `GET /api/charts/equity-historical-data` - Charting OHLC historical data - `GET /api/charts/symbol-info` - Charting symbol/token lookup - `GET /api-docs` - Interactive API documentation ### MCP Client Endpoints - `POST /api/mcp/query` - Natural language query using OpenAI Functions - `POST /api/mcp/query-multiple` - Multi-step natural language queries ### API Documentation Visit `http://localhost:3000/api-docs` for complete interactive API documentation powered by Swagger UI. ### Charting APIs #### NPM Package Methods ```javascript import { NseIndia } from "stock-nse-india"; const nseIndia = new NseIndia(); // Optional date range and optional token. // If token is omitted, it is auto-fetched internally using getEquitySymbolInfo(). const chartData = await nseIndia.getEquityChartHistoricalData( "ONGC", { start: new Date("2026-04-10"), end: new Date("2026-04-12") } ); // You can also fetch symbol info/token explicitly. const symbolInfo = await nseIndia.getEquitySymbolInfo("ONGC"); console.log(symbolInfo.scripcode); ``` #### REST Endpoints - **`GET /api/charts/equity-historical-data`** - Required: `symbol` - Optional: `start`, `end` (`YYYY-MM-DD`, `YYYY-MM-DD HH:MM:SS`, or unix timestamp), `token`, `symbolType`, `chartType`, `timeInterval` - If `token` is omitted, the API auto-fetches it. - If both `start` and `end` are omitted, default range is used. - If only one date is provided, the other date is auto-derived. - **`GET /api/charts/symbol-info`** - Required: `symbol` - Optional: `segment` - Returns charting symbol details including `scripcode` (token). ## 💻 CLI Usage ### Basic Commands ```bash # Get help nseindia --help # Get market status nseindia # Get equity details nseindia equity IRCTC # Get historical data nseindia historical IRCTC # Get indices information nseindia index # Get specific index details nseindia index "NIFTY AUTO" ``` ### CLI Features - **Real-time data** - Live market information - **Historical analysis** - Historical price data - **Index tracking** - Market index performance - **Interactive charts** - ASCII-based data visualization ## 🐳 Docker ### Quick Start ```bash # Pull and run from Docker Hub docker run --rm -d -p 3001:3001 imcodeman/nseindia # Or build locally docker build -t nseindia . && docker run --rm -d -p 3001:3001 nseindia:latest ``` ### Docker Hub **Image:** `imcodeman/nseindia` **Registry:** [Docker Hub](https://hub.docker.com/r/imcodeman/nseindia) ### Container URLs - **Main App:** http://localhost:3001 - **GraphQL:** http://localhost:3001/graphql - **API Docs:** http://localhost:3001/api-docs ## ⚙️ Configuration ### Environment Variables ```bash # Server Configuration PORT=3000 HOST_URL=http://localhost:3000 NODE_ENV=development # CORS Configuration CORS_ORIGINS=https://myapp.com,https://admin.myapp.com CORS_METHODS=GET,POST,OPTIONS CORS_HEADERS=Content-Type,Authorization,X-Requested-With CORS_CREDENTIALS=true ``` ### CORS Settings - **Origins:** Comma-separated list of allowed domains - **Methods:** HTTP methods (default: GET,POST,PUT,DELETE,OPTIONS) - **Headers:** Allowed request headers - **Credentials:** Enable/disable credentials (default: true) - **Localhost:** Always allowed for development ## 📊 API Methods ### Core Methods - **`getAllStockSymbols()`** - Get all NSE stock symbols - **`getData()`** - Generic data retrieval - **`getDataByEndpoint()`** - Get data by specific NSE API endpoints ### Equity Methods - **`getEquityDetails(symbol)`** - Get equity information - **`getEquityHistoricalData(symbol, range)`** - Historical price data - **`getEquityIntradayData(symbol)`** - Intraday trading data - **`getEquityOptionChain(symbol)`** - Options chain data - **`getEquityCorporateInfo(symbol)`** - Corporate information - **`getEquityTradeInfo(symbol)`** - Trading statistics ### Charting Methods - **`getEquityChartHistoricalData(symbol, range?, token?, symbolType?, chartType?, timeInterval?)`** - Get charting OHLC historical data - **`getEquitySymbolInfo(symbol, segment?)`** - Resolve charting symbol/token (`scripcode`) ### Index Methods - **`getEquityStockIndices()`** - Get all market indices - **`getIndexIntradayData(index)`** - Index intraday data - **`getIndexOptionChain(index)`** - Index options data - **`getIndexOptionChainContractInfo(indexSymbol)`** - Get option chain contract information (expiry dates and strike prices) ### Commodity Methods - **`getCommodityOptionChain(symbol)`** - Commodity options data ### Helper Methods - **`getGainersAndLosersByIndex(index)`** - Top gainers and losers - **`getMostActiveEquities()`** - Most actively traded stocks ## 🏃‍♂️ Development **⚠️ Prerequisites:** Node.js 18+ required ### Local Development ```bash # Clone repository git clone https://github.com/hi-imcodeman/stock-nse-india.git cd stock-nse-india # Install dependencies npm install # Development mode with auto-reload npm run start:dev # Build project npm run build # Run tests npm test # Generate documentation npm run docs ``` ### Development Scripts - **`npm start`** - Start production server - **`npm run start:dev`** - Development mode with auto-reload - **`npm run build`** - Build TypeScript to JavaScript - **`npm test`** - Run test suite with coverage - **`npm run docs`** - Generate TypeDoc documentation - **`npm run lint`** - Run ESLint ### MCP Scripts - **`npm run start:mcp`** - Start stdio MCP server - **`npm run test:mcp`** - Test stdio MCP server ## 🧪 Testing ```bash # Run all tests npm test # Run tests with coverage npm test -- --coverage # Run specific test file npm test -- utils.spec.ts ``` ## 📚 Documentation - **📖 [API Reference](https://hi-imcodeman.github.io/stock-nse-india)** - Complete API documentation - **🔍 [Examples](https://github.com/hi-imcodeman/stock-nse-india/tree/master/examples)** - Code examples and use cases - **📋 [Interfaces](https://hi-imcodeman.github.io/stock-nse-india/interfaces/)** - TypeScript interface definitions - **🏗️ [Modules](https://hi-imcodeman.github.io/stock-nse-india/modules/)** - Module documentation ## 🤝 Contributing We welcome contributions! Please see our contributing guidelines and feel free to submit issues and pull requests. ### Development Setup 1. Fork the repository 2. Create a feature branch 3. Make your changes 4. Add tests for new functionality 5. Ensure all tests pass 6. Submit a pull request ## 📄 License This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details. ## 👥 Contributors ## 🔗 Links - **🌐 Website:** [https://hi-imcodeman.github.io/stock-nse-india](https://hi-imcodeman.github.io/stock-nse-india) - **📦 NPM:** [https://www.npmjs.com/package/stock-nse-india](https://www.npmjs.com/package/stock-nse-india) - **🐳 Docker Hub:** [https://hub.docker.com/r/imcodeman/nseindia](https://hub.docker.com/r/imcodeman/nseindia) - **🐛 Issues:** [https://github.com/hi-imcodeman/stock-nse-india/issues](https://github.com/hi-imcodeman/stock-nse-india/issues) --- **⭐ Star this repository if you find it helpful!** ================================================ FILE: demo/README.md ================================================ # MCP Client Demo - NSE India Stock Market Complete demonstration of the MCP (Model Context Protocol) Client with **memory management** and **context summarization** features for NSE India stock market data. --- ## 🚀 Quick Start ### 1. Setup ```bash # Set OpenAI API Key export OPENAI_API_KEY=your-api-key # Build the project npm run build ``` ### 2. Run Demos ```bash # All demos npm run demo:mcp-client # Specific demo (1-7) npm run demo:mcp-client 3 # Memory example npm run demo:memory ``` --- ## 📦 What's Included ### Demo Files 1. **`mcp-client-demo.js`** (566 lines) - 7 comprehensive scenarios - All features demonstrated - Production-ready examples 2. **`memory-example.js`** (230 lines) - Focused memory & summarization demo - 8-query conversation flow - Real-time context window tracking - Visual progress indicators --- ## 🎯 Available Demos > **Note:** All demos use memory and context summarization by default! ### Demo 1: Basic Query with Memory Simple query demonstrating memory and summarization features. ```bash npm run demo:mcp-client 1 ``` **Features:** - Session-based tracking - Context summarization - User preference tracking - Response metadata ### Demo 2: Session Conversation Multi-query conversation maintaining context. ```bash npm run demo:mcp-client 2 ``` **Features:** - Follow-up questions work naturally - Context awareness - Preference learning - Session persistence ### Demo 3: Technical Analysis Fetch and analyze technical indicators. ```bash npm run demo:mcp-client 3 ``` **Features:** - RSI, MACD, Bollinger Bands - Multi-iteration processing - Session tracking - Analysis style detection ### Demo 4: Investment Recommendations Get investment recommendations based on technical analysis. ```bash npm run demo:mcp-client 4 ``` **Features:** - NIFTY 50 stock analysis - Multi-step queries - Learned preferences - Investment insights ### Demo 5: Multi-user Sessions Handle multiple users with separate sessions. ```bash npm run demo:mcp-client 5 ``` **Features:** - Isolated user contexts - User-specific preferences - Concurrent sessions - Session management ### Demo 6: Context Summarization Long conversation with automatic summarization. ```bash npm run demo:mcp-client 6 ``` **Features:** - 9-query conversation - Automatic summarization - Token optimization - Summarization history ### Demo 7: Tools & Configuration Display available tools and configuration. ```bash npm run demo:mcp-client 7 ``` **Features:** - 28 available tools - Configuration details - Context window settings - Tool capabilities ### Memory Example Focused demonstration of memory features. ```bash npm run demo:memory ``` **Features:** - Natural conversation flow (8 queries) - Real-time context window tracking - Automatic preference learning - Summarization statistics - Visual progress indicators **Example Output:** ``` Query 1: 📊 Context Window: 37.0% used (2,964 tokens) [GREEN] Query 2: 📊 Context Window: 45.1% used (3,605 tokens) [GREEN] Query 3: 📊 Context Window: 58.9% used (4,713 tokens) [GREEN] Query 4: 📊 Context Window: 74.6% used (5,967 tokens) [YELLOW] ⚠️ Context Summarization Triggered! Query 5: 📊 Context Window: 45.2% used (3,616 tokens) [GREEN] ``` --- ## 🧠 Memory Features ### Session Management - **Unique Session IDs**: Each conversation tracked separately - **Multi-user Support**: Isolated contexts per user - **Session Persistence**: Data maintained throughout conversation - **Statistics**: Duration, message count, stocks accessed ### Context Awareness - **Follow-up Questions**: Reference previous queries naturally - **Cross-query Context**: Information synthesized across queries - **Conversation History**: Full history maintained - **Smart References**: AI understands context automatically ### User Preference Learning Automatically learns and tracks: - **Preferred Stocks**: Stocks you frequently ask about - **Analysis Style**: Brief, detailed, or technical - **Preferred Indices**: NIFTY, BANKNIFTY, etc. - **Personalization**: Responses tailored to preferences --- ## 📊 Context Summarization ### Automatic Summarization - **Token Monitoring**: Tracks usage in real-time - **Smart Triggering**: Activates at 70% threshold (configurable) - **Seamless Operation**: Happens transparently - **Context Preservation**: Important info retained ### Benefits - **Cost Savings**: 64% token reduction demonstrated - **Performance**: Faster responses with less context - **Scalability**: Enables unlimited conversation length - **Optimization**: Automatic token management ### Real-World Results ``` Before Summarization: 5,752 tokens After Summarization: 2,075 tokens Savings: 3,677 tokens (64% reduction!) ``` --- ## ⚙️ Configuration ### Client Configuration ```javascript const client = new MCPClient({ enableMemory: true, // Enable session memory enableContextSummarization: true, // Enable auto-summarization enableDebugLogging: false, // Debug logs memoryConfig: { maxConversationHistory: 50, // Max messages in conversation history contextWindowConfig: { maxTokens: 8000, // Token limit summarizationThreshold: 0.8 // Trigger at 80% } } }); ``` ### Query Options ```javascript await client.processQuery({ query: 'Your question', sessionId: 'unique-session-id', // For memory userId: 'user-identifier', // Optional useMemory: true, // Use session memory includeContext: true, // Include history updatePreferences: true, // Learn preferences maxIterations: 5, // Max AI iterations model: 'gpt-4o-mini', // OpenAI model temperature: 0.7, // Creativity (0-1) max_tokens: 2000 // Max response length }); ``` --- ## 💡 Usage Examples ### Basic Query ```javascript const { MCPClient } = require('./build/mcp/client/mcp-client.js'); const client = new MCPClient(); const response = await client.processQuery({ query: 'What is the current market status?', useMemory: false }); console.log(response.response); ``` ### Session-based Conversation ```javascript const sessionId = 'user-123-' + Date.now(); // Query 1 await client.processQuery({ query: 'Tell me about RELIANCE stock', sessionId, useMemory: true }); // Query 2 - Uses context from Query 1 await client.processQuery({ query: 'What is its current price?', // Knows you mean RELIANCE sessionId, useMemory: true, includeContext: true }); ``` ### With Preferences ```javascript await client.processQuery({ query: 'I prefer detailed technical analysis', sessionId, useMemory: true, updatePreferences: true }); // Future queries will be more technical ``` --- ## 🎨 Features Showcase ### Real-time Context Tracking - See context window usage after each query - Color-coded indicators (green/yellow) - Token count display - Visual progress ### Automatic Summarization - Triggers when approaching limit - Shows what was summarized - Displays tokens saved - Maintains conversation flow ### Session Analytics - Message counts - Token usage - Summarization history - Tool usage tracking --- ## 🔧 Troubleshooting ### Error: OPENAI_API_KEY not set ```bash export OPENAI_API_KEY=your-api-key ``` ### Error: Module not found ```bash npm run build ``` ### Slow responses - Check internet connection - NSE API may be slow during market hours - Consider reducing `maxIterations` ### Rate limiting - Wait between demos - Use different API key - Upgrade OpenAI plan --- ## 📈 Performance Metrics ### Demo Results - **Session Duration**: ~170-210 seconds - **Queries Processed**: 8 - **Stocks Analyzed**: 4 (RELIANCE, TCS, HDFC, etc.) - **Summarizations**: 2 automatic triggers - **Tokens Saved**: 3,677 (64% reduction) - **Final Usage**: 48.5% (optimized) ### Benefits - ✅ 64% lower API costs - ✅ Faster response times - ✅ Longer conversations possible - ✅ Better context management - ✅ Automatic optimization --- ## 🎓 Learning Outcomes After running the demos, you'll understand: - How to implement conversational memory - How context summarization works - How to manage multi-user sessions - How to track user preferences - How to optimize token usage - How to build production AI apps --- ## 📚 Additional Resources ### Project Links - **Main README**: [../README.md](../README.md) - **MCP Server Docs**: [../MCP_README.md](../MCP_README.md) - **API Documentation**: https://hi-imcodeman.github.io/stock-nse-india - **GitHub**: https://github.com/hi-imcodeman/stock-nse-india ### Support - **Issues**: https://github.com/hi-imcodeman/stock-nse-india/issues - **Email**: asraf.cse@gmail.com --- ## ✨ Key Highlights - ✅ **Production Ready**: Complete error handling, tested - ✅ **Well Documented**: Comprehensive examples and guides - ✅ **Feature Complete**: All memory & summarization features - ✅ **User Friendly**: Beautiful console output, clear instructions - ✅ **Cost Effective**: 64% token savings demonstrated - ✅ **Scalable**: Handles unlimited conversation length --- ## 📊 Project Statistics - **Code**: 796 lines (JavaScript demos) - **Documentation**: This comprehensive guide - **Demo Scenarios**: 7 + 1 focused example - **Available Tools**: 28 NSE India API tools - **Features**: Memory, Summarization, Analytics, Tracking --- ## 🏆 Status **✅ Complete and Ready for Production Use** All features tested and working: - Memory management ✓ - Context summarization ✓ - User preferences ✓ - Session tracking ✓ - Multi-user support ✓ - Real-time analytics ✓ --- **License**: MIT **Version**: 1.0.0 **Last Updated**: October 2025 ================================================ FILE: demo/mcp-client-demo.js ================================================ /** * MCP Client Demo - Comprehensive Examples * * This demo showcases various features of the MCP Client including: * - Basic queries without memory * - Session-based conversations with memory * - Context summarization for long conversations * - Multi-iteration queries * - Technical analysis queries * - Investment recommendations */ const { MCPClient } = require('../build/mcp/client/mcp-client.js'); // ANSI color codes for better console output const colors = { reset: '\x1b[0m', bright: '\x1b[1m', dim: '\x1b[2m', red: '\x1b[31m', green: '\x1b[32m', yellow: '\x1b[33m', blue: '\x1b[34m', magenta: '\x1b[35m', cyan: '\x1b[36m', }; function log(message, color = colors.reset) { console.log(`${color}${message}${colors.reset}`); } function logSection(title) { console.log('\n' + '='.repeat(80)); log(title, colors.bright + colors.cyan); console.log('='.repeat(80) + '\n'); } function logSubSection(title) { log(`\n${title}`, colors.bright + colors.yellow); log('-'.repeat(title.length), colors.dim); } async function sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } /** * Demo 1: Basic Query with Memory and Summarization Enabled */ async function demo1_BasicQuery() { logSection('Demo 1: Basic Query with Memory and Summarization Enabled'); const client = new MCPClient({ enableMemory: true, enableContextSummarization: true, enableDebugLogging: false, memoryConfig: { maxConversationHistory: 50, contextWindowConfig: { maxTokens: 8000, summarizationThreshold: 0.8 } } }); const sessionId = 'demo1-session-' + Date.now(); try { log('Query: What is the current market status?', colors.blue); log(`Session ID: ${sessionId}`, colors.dim); const response = await client.processQuery({ query: 'What is the current market status?', sessionId, useMemory: true, includeContext: true, updatePreferences: true, maxIterations: 3 }); logSubSection('Response:'); log(response.response, colors.green); logSubSection('Metadata:'); console.log({ tools_used: response.tools_used, iterations_used: response.iterations_used, session_id: response.sessionId, context_used: response.context_used, conversation_length: response.conversation_length, timestamp: response.timestamp }); logSubSection('Memory Features:'); log('✓ Session memory enabled', colors.green); log('✓ Context summarization enabled', colors.green); log('✓ User preferences tracking enabled', colors.green); } catch (error) { log(`Error: ${error.message}`, colors.red); } } /** * Demo 2: Session-based Conversation with Memory */ async function demo2_SessionWithMemory() { logSection('Demo 2: Session-based Conversation with Memory'); const client = new MCPClient({ enableMemory: true, enableContextSummarization: true, enableDebugLogging: false }); const sessionId = 'demo-session-' + Date.now(); try { // First query logSubSection('Query 1: Get details about RELIANCE stock'); const response1 = await client.processQuery({ query: 'Tell me about RELIANCE stock', sessionId, useMemory: true, includeContext: true, maxIterations: 3 }); log(response1.response.substring(0, 300) + '...', colors.green); await sleep(1000); // Second query (uses context from first) logSubSection('Query 2: Follow-up question using context'); const response2 = await client.processQuery({ query: 'What are its technical indicators?', sessionId, useMemory: true, includeContext: true, maxIterations: 3 }); log(response2.response.substring(0, 300) + '...', colors.green); await sleep(1000); // Third query (uses context from both) logSubSection('Query 3: Another follow-up question'); const response3 = await client.processQuery({ query: 'Should I invest in it?', sessionId, useMemory: true, includeContext: true, maxIterations: 3 }); log(response3.response.substring(0, 300) + '...', colors.green); // Show session info logSubSection('Session Information:'); const sessionInfo = client.getSessionInfo(sessionId); if (sessionInfo) { console.log({ session_id: sessionInfo.sessionId, message_count: sessionInfo.messageCount, frequently_accessed_stocks: sessionInfo.frequentlyAccessedStocks }); } } catch (error) { log(`Error: ${error.message}`, colors.red); } } /** * Demo 3: Technical Analysis Query with Memory */ async function demo3_TechnicalAnalysis() { logSection('Demo 3: Technical Analysis Query with Memory'); const client = new MCPClient({ enableMemory: true, enableContextSummarization: true, enableDebugLogging: false }); const sessionId = 'demo3-session-' + Date.now(); try { log('Query: Get technical indicators for TCS stock', colors.blue); log(`Session ID: ${sessionId}`, colors.dim); const response = await client.processQuery({ query: 'Get me the technical indicators for TCS stock including RSI, MACD, and Bollinger Bands', sessionId, useMemory: true, includeContext: true, updatePreferences: true, maxIterations: 5 }); logSubSection('Response:'); log(response.response, colors.green); logSubSection('Iteration Details:'); response.iteration_details.forEach((detail, index) => { console.log(`\nIteration ${detail.iteration}:`); console.log(` Purpose: ${detail.purpose}`); console.log(` Tools: ${detail.tools_called.join(', ')}`); }); logSubSection('Session Info:'); const sessionInfo = client.getSessionInfo(sessionId); if (sessionInfo) { console.log({ session_id: sessionInfo.sessionId, message_count: sessionInfo.messageCount, frequently_accessed_stocks: sessionInfo.frequentlyAccessedStocks, frequently_used_tools: sessionInfo.frequentlyUsedTools }); } } catch (error) { log(`Error: ${error.message}`, colors.red); } } /** * Demo 4: Investment Recommendation Query with Memory */ async function demo4_InvestmentRecommendation() { logSection('Demo 4: Investment Recommendation Query with Memory'); const client = new MCPClient({ enableMemory: true, enableContextSummarization: true, enableDebugLogging: false }); const sessionId = 'demo4-session-' + Date.now(); try { log('Query: Which NIFTY 50 stocks are good for investment based on technical indicators?', colors.blue); log(`Session ID: ${sessionId}`, colors.dim); const response = await client.processQuery({ query: 'Which NIFTY 50 stocks are good for investment based on technical indicators?', sessionId, useMemory: true, includeContext: true, updatePreferences: true, maxIterations: 5 }); logSubSection('Response:'); log(response.response, colors.green); logSubSection('Query Statistics:'); console.log({ tools_used: response.tools_used, iterations_used: response.iterations_used, data_sources: response.data_sources, conversation_length: response.conversation_length, preferences_updated: response.user_preferences_updated }); logSubSection('Session Statistics:'); const sessionInfo = client.getSessionInfo(sessionId); if (sessionInfo) { console.log({ session_id: sessionInfo.sessionId, message_count: sessionInfo.messageCount, frequently_accessed_stocks: sessionInfo.frequentlyAccessedStocks, frequently_used_tools: sessionInfo.frequentlyUsedTools }); } } catch (error) { log(`Error: ${error.message}`, colors.red); } } /** * Demo 5: Multi-user Sessions */ async function demo5_MultiUserSessions() { logSection('Demo 5: Multi-user Sessions'); const client = new MCPClient({ enableMemory: true, enableContextSummarization: true, enableDebugLogging: false }); try { // User 1 logSubSection('User 1 Session:'); const user1Session = 'user1-' + Date.now(); const user1Response = await client.processQuery({ query: 'I am interested in IT stocks. Tell me about TCS.', sessionId: user1Session, userId: 'user1', useMemory: true, maxIterations: 3 }); log(user1Response.response.substring(0, 200) + '...', colors.green); await sleep(500); // User 2 logSubSection('User 2 Session:'); const user2Session = 'user2-' + Date.now(); const user2Response = await client.processQuery({ query: 'I am interested in banking stocks. Tell me about HDFC Bank.', sessionId: user2Session, userId: 'user2', useMemory: true, maxIterations: 3 }); log(user2Response.response.substring(0, 200) + '...', colors.green); await sleep(500); // User 1 follow-up logSubSection('User 1 Follow-up:'); const user1FollowUp = await client.processQuery({ query: 'What about Infosys?', sessionId: user1Session, userId: 'user1', useMemory: true, includeContext: true, maxIterations: 3 }); log(user1FollowUp.response.substring(0, 200) + '...', colors.green); // Show session statistics logSubSection('Session Statistics:'); const user1Info = client.getSessionInfo(user1Session); const user2Info = client.getSessionInfo(user2Session); if (user1Info && user2Info) { console.log('\nUser 1:'); console.log({ session_id: user1Info.sessionId, message_count: user1Info.messageCount, frequently_accessed_stocks: user1Info.frequentlyAccessedStocks }); console.log('\nUser 2:'); console.log({ session_id: user2Info.sessionId, message_count: user2Info.messageCount, frequently_accessed_stocks: user2Info.frequentlyAccessedStocks }); } } catch (error) { log(`Error: ${error.message}`, colors.red); } } /** * Demo 6: Context Summarization */ async function demo6_ContextSummarization() { logSection('Demo 6: Context Summarization (Long Conversation)'); const client = new MCPClient({ enableMemory: true, enableContextSummarization: true, enableDebugLogging: false, memoryConfig: { contextWindowConfig: { maxTokens: 4000, // Small window to trigger summarization summarizationThreshold: 0.7 } } }); const sessionId = 'summarization-demo-' + Date.now(); try { const queries = [ 'Tell me about RELIANCE stock', 'What is its current price?', 'Show me its technical indicators', 'What about TCS stock?', 'Compare RELIANCE and TCS', 'Which one is better for long-term investment?', 'What are the risks?', 'Tell me about HDFC Bank', 'Should I diversify my portfolio?' ]; for (let i = 0; i < queries.length; i++) { logSubSection(`Query ${i + 1}: ${queries[i]}`); const response = await client.processQuery({ query: queries[i], sessionId, useMemory: true, includeContext: true, maxIterations: 2 }); log(response.response.substring(0, 150) + '...', colors.green); if (response.context_summarized) { log('\n⚠️ Context was summarized!', colors.yellow); console.log('Summary:', response.context_summary); } await sleep(500); } // Show final session stats logSubSection('Final Session Statistics:'); const stats = await client.getContextStats(sessionId); console.log({ message_count: stats.messageCount, total_tokens: stats.tokenCount.totalTokens, context_window_usage: `${stats.contextWindowUsage.toFixed(1)}%`, needs_summarization: stats.needsSummarization }); // Show summarization history const summaryHistory = client.getSummarizationHistory(sessionId); if (summaryHistory.length > 0) { logSubSection('Summarization History:'); console.log(`Total summarizations: ${summaryHistory.length}`); } } catch (error) { log(`Error: ${error.message}`, colors.red); } } /** * Demo 7: Available Tools and Configuration */ async function demo7_ToolsAndConfig() { logSection('Demo 7: Available Tools and Configuration'); const client = new MCPClient({ enableMemory: true, enableContextSummarization: true, enableDebugLogging: false }); try { logSubSection('Client Configuration:'); const config = client.getConfig(); console.log({ memory_enabled: client.isMemoryEnabled(), context_summarization_enabled: client.isContextSummarizationEnabled(), debug_logging: client.isDebugLoggingEnabled() }); logSubSection('Available Tools:'); const tools = client.getAvailableTools(); console.log(`Total tools available: ${tools.length}\n`); tools.slice(0, 5).forEach((tool, index) => { console.log(`${index + 1}. ${tool.name}`); console.log(` ${tool.description.substring(0, 80)}...`); }); log(`\n... and ${tools.length - 5} more tools`, colors.dim); logSubSection('Context Window Configuration:'); const contextConfig = client.getContextWindowConfig(); console.log({ max_tokens: contextConfig.maxTokens, summarization_threshold: `${(contextConfig.summarizationThreshold * 100).toFixed(0)}%`, reserved_tokens: contextConfig.reservedTokens, min_messages_to_summarize: contextConfig.minMessagesToSummarize }); } catch (error) { log(`Error: ${error.message}`, colors.red); } } /** * Main function to run all demos */ async function runAllDemos() { log('\n' + '█'.repeat(80), colors.bright + colors.magenta); log(' MCP CLIENT DEMO - NSE India Stock Market Data', colors.bright + colors.magenta); log('█'.repeat(80) + '\n', colors.bright + colors.magenta); log('This demo will showcase various features of the MCP Client.', colors.cyan); log('Make sure you have set the OPENAI_API_KEY environment variable.\n', colors.yellow); // Check for OpenAI API key if (!process.env.OPENAI_API_KEY) { log('❌ Error: OPENAI_API_KEY environment variable is not set!', colors.red); log('Please set it using: export OPENAI_API_KEY=your-api-key', colors.yellow); process.exit(1); } try { // Run demos based on command line argument const demoNumber = process.argv[2]; if (demoNumber) { const demoMap = { '1': demo1_BasicQuery, '2': demo2_SessionWithMemory, '3': demo3_TechnicalAnalysis, '4': demo4_InvestmentRecommendation, '5': demo5_MultiUserSessions, '6': demo6_ContextSummarization, '7': demo7_ToolsAndConfig }; const demoFunc = demoMap[demoNumber]; if (demoFunc) { await demoFunc(); } else { log(`Invalid demo number: ${demoNumber}`, colors.red); log('Available demos: 1-7', colors.yellow); } } else { // Run all demos await demo1_BasicQuery(); await sleep(2000); await demo2_SessionWithMemory(); await sleep(2000); await demo3_TechnicalAnalysis(); await sleep(2000); await demo4_InvestmentRecommendation(); await sleep(2000); await demo5_MultiUserSessions(); await sleep(2000); await demo6_ContextSummarization(); await sleep(2000); await demo7_ToolsAndConfig(); } log('\n' + '█'.repeat(80), colors.bright + colors.green); log(' ✓ Demo completed successfully!', colors.bright + colors.green); log('█'.repeat(80) + '\n', colors.bright + colors.green); log('Usage:', colors.cyan); log(' Run all demos: node demo/mcp-client-demo.js', colors.dim); log(' Run specific demo: node demo/mcp-client-demo.js <1-7>', colors.dim); log(' Or use npm: npm run demo:mcp-client <1-7>', colors.dim); log('\nAvailable demos:', colors.cyan); log(' 1. Basic Query with Memory and Summarization', colors.dim); log(' 2. Session-based Conversation with Memory', colors.dim); log(' 3. Technical Analysis Query with Memory', colors.dim); log(' 4. Investment Recommendation Query with Memory', colors.dim); log(' 5. Multi-user Sessions', colors.dim); log(' 6. Context Summarization (Long Conversations)', colors.dim); log(' 7. Available Tools and Configuration', colors.dim); log('\n💡 All demos use memory and context summarization features!', colors.yellow); } catch (error) { log('\n' + '█'.repeat(80), colors.bright + colors.red); log(' ✗ Demo failed!', colors.bright + colors.red); log('█'.repeat(80) + '\n', colors.bright + colors.red); log(`Error: ${error.message}`, colors.red); console.error(error); process.exit(1); } } // Run the demos if (require.main === module) { runAllDemos().catch(error => { log(`Fatal error: ${error.message}`, colors.red); console.error(error); process.exit(1); }); } module.exports = { demo1_BasicQuery, demo2_SessionWithMemory, demo3_TechnicalAnalysis, demo4_InvestmentRecommendation, demo5_MultiUserSessions, demo6_ContextSummarization, demo7_ToolsAndConfig }; ================================================ FILE: demo/memory-example.js ================================================ /** * Memory and Summarization Example * * This example demonstrates the power of memory and context summarization * in maintaining context across multiple queries in a conversation. */ const { MCPClient } = require('../build/mcp/client/mcp-client.js'); // Colors for console output const colors = { reset: '\x1b[0m', bright: '\x1b[1m', cyan: '\x1b[36m', green: '\x1b[32m', yellow: '\x1b[33m', magenta: '\x1b[35m', dim: '\x1b[2m', }; function log(message, color = colors.reset) { console.log(`${color}${message}${colors.reset}`); } async function sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } async function runMemoryExample() { log('\n' + '='.repeat(80), colors.bright + colors.cyan); log('Memory and Context Summarization Example', colors.bright + colors.cyan); log('='.repeat(80) + '\n', colors.bright + colors.cyan); // Create client with memory and summarization enabled const client = new MCPClient({ enableMemory: true, enableContextSummarization: true, enableDebugLogging: false, memoryConfig: { maxConversationHistory: 30, contextWindowConfig: { maxTokens: 6000, // Smaller window to demonstrate summarization summarizationThreshold: 0.7 // Trigger at 70% capacity } } }); const sessionId = 'memory-example-' + Date.now(); log(`Session ID: ${sessionId}`, colors.dim); log('', colors.reset); try { // Conversation demonstrating memory and context awareness const conversation = [ { query: 'Tell me about RELIANCE stock', description: 'Initial query about RELIANCE' }, { query: 'What is its current price?', description: 'Follow-up using context (refers to RELIANCE)' }, { query: 'Show me its technical indicators', description: 'Another follow-up (still about RELIANCE)' }, { query: 'Now tell me about TCS', description: 'New topic - TCS stock' }, { query: 'Compare it with RELIANCE', description: 'Comparison using both stocks from context' }, { query: 'Which one has better RSI?', description: 'Technical comparison using context' }, { query: 'What about HDFC Bank?', description: 'Adding another stock to context' }, { query: 'Which of the three stocks I asked about is best for long-term investment?', description: 'Complex query requiring full conversation context' } ]; for (let i = 0; i < conversation.length; i++) { const { query, description } = conversation[i]; log(`\n${'─'.repeat(80)}`, colors.dim); log(`Query ${i + 1}/${conversation.length}: ${description}`, colors.bright + colors.yellow); log(`${'─'.repeat(80)}`, colors.dim); log(`\n"${query}"`, colors.cyan); const response = await client.processQuery({ query, sessionId, useMemory: true, includeContext: true, updatePreferences: true, maxIterations: 3 }); log(`\n${colors.green}Response:${colors.reset}`); log(response.response.substring(0, 300) + '...', colors.green); // Show memory features in action log(`\n${colors.magenta}Memory Info:${colors.reset}`); console.log({ conversation_length: response.conversation_length, context_used: response.context_used, preferences_updated: response.user_preferences_updated, tools_used: response.tools_used }); // Show context window usage after each query try { const contextStats = await client.getContextStats(sessionId); const usagePercent = contextStats.contextWindowUsage.toFixed(1); const usageColor = contextStats.contextWindowUsage > 70 ? colors.yellow : colors.green; log(`\n📊 Context Window: ${usagePercent}% used (${contextStats.tokenCount.totalTokens} tokens)`, usageColor); } catch (error) { // Ignore errors in context stats } // Check if context was summarized if (response.context_summarized) { log(`\n${colors.yellow}⚠️ Context Summarization Triggered!${colors.reset}`, colors.yellow); log('The conversation history was automatically summarized to save tokens.', colors.yellow); if (response.context_summary) { log('\nSummary:', colors.dim); console.log(response.context_summary); } } await sleep(1000); } // Show final session statistics log('\n' + '='.repeat(80), colors.bright + colors.magenta); log('Final Session Statistics', colors.bright + colors.magenta); log('='.repeat(80) + '\n', colors.bright + colors.magenta); const sessionInfo = client.getSessionInfo(sessionId); if (sessionInfo) { log('Conversation Stats:', colors.cyan); console.log({ session_id: sessionInfo.sessionId, user_id: sessionInfo.userId || 'anonymous', message_count: sessionInfo.messageCount, frequently_accessed_stocks: sessionInfo.frequentlyAccessedStocks, frequently_used_tools: sessionInfo.frequentlyUsedTools, session_duration: `${Math.round((Date.now() - new Date(sessionInfo.startTime).getTime()) / 1000)}s` }); } else { log('Session info not available', colors.yellow); } // Get conversation history to show learned preferences const conversationHistory = client.getConversationHistory(sessionId); log('\nConversation Summary:', colors.cyan); console.log({ total_messages: conversationHistory.length, user_messages: conversationHistory.filter(m => m.role === 'user').length, assistant_messages: conversationHistory.filter(m => m.role === 'assistant').length }); // Show context statistics const contextStats = await client.getContextStats(sessionId); log('\nContext Window Usage:', colors.cyan); console.log({ message_count: contextStats.messageCount, total_tokens: contextStats.tokenCount.totalTokens, system_prompt_tokens: contextStats.tokenCount.systemPromptTokens, estimated_response_tokens: contextStats.tokenCount.estimatedResponseTokens, window_usage: `${contextStats.contextWindowUsage.toFixed(1)}%`, needs_summarization: contextStats.needsSummarization }); // Show summarization history if any const summaryHistory = client.getSummarizationHistory(sessionId); if (summaryHistory.length > 0) { log('\nSummarization History:', colors.cyan); console.log(`Total summarizations performed: ${summaryHistory.length}`); // Calculate total tokens saved const totalTokensSaved = summaryHistory.reduce((sum, s) => sum + (s.tokensSaved || 0), 0); log(`Total tokens saved: ${totalTokensSaved}`, colors.green); summaryHistory.forEach((record, index) => { console.log(`\n Summarization ${index + 1}:`); console.log(` Timestamp: ${new Date(record.timestamp).toLocaleString()}`); console.log(` Original messages: ${record.originalMessageCount}`); console.log(` After summarization: ${record.summarizedMessageCount}`); console.log(` Tokens saved: ${record.tokensSaved}`); console.log(` Trigger: ${record.triggerReason}`); }); } log('\n' + '='.repeat(80), colors.bright + colors.green); log('✓ Memory Example Completed Successfully!', colors.bright + colors.green); log('='.repeat(80) + '\n', colors.bright + colors.green); log('Key Takeaways:', colors.cyan); log(' ✓ Context is maintained across queries', colors.green); log(' ✓ Follow-up questions work naturally', colors.green); log(' ✓ User preferences are learned automatically', colors.green); log(' ✓ Context is summarized when needed to save tokens', colors.green); log(' ✓ Session data persists throughout the conversation', colors.green); } catch (error) { log(`\n❌ Error: ${error.message}`, colors.bright); console.error(error); process.exit(1); } } // Check for OpenAI API key if (!process.env.OPENAI_API_KEY) { log('❌ Error: OPENAI_API_KEY environment variable is not set!', colors.bright); log('Please set it using: export OPENAI_API_KEY=your-api-key', colors.yellow); process.exit(1); } // Run the example runMemoryExample().catch(error => { log(`Fatal error: ${error.message}`, colors.bright); console.error(error); process.exit(1); }); ================================================ FILE: docs/.nojekyll ================================================ TypeDoc added this file to prevent GitHub Pages from using Jekyll. You can turn off this behavior by setting the `githubPages` option to false. ================================================ FILE: docs/assets/highlight.css ================================================ :root { --light-hl-0: #795E26; --dark-hl-0: #DCDCAA; --light-hl-1: #000000; --dark-hl-1: #D4D4D4; --light-hl-2: #A31515; --dark-hl-2: #CE9178; --light-hl-3: #AF00DB; --dark-hl-3: #C586C0; --light-hl-4: #001080; --dark-hl-4: #9CDCFE; --light-hl-5: #0000FF; --dark-hl-5: #569CD6; --light-hl-6: #0070C1; --dark-hl-6: #4FC1FF; --light-hl-7: #008000; --dark-hl-7: #6A9955; --light-hl-8: #0451A5; --dark-hl-8: #9CDCFE; --light-hl-9: #098658; --dark-hl-9: #B5CEA8; --light-code-background: #FFFFFF; --dark-code-background: #1E1E1E; } @media (prefers-color-scheme: light) { :root { --hl-0: var(--light-hl-0); --hl-1: var(--light-hl-1); --hl-2: var(--light-hl-2); --hl-3: var(--light-hl-3); --hl-4: var(--light-hl-4); --hl-5: var(--light-hl-5); --hl-6: var(--light-hl-6); --hl-7: var(--light-hl-7); --hl-8: var(--light-hl-8); --hl-9: var(--light-hl-9); --code-background: var(--light-code-background); } } @media (prefers-color-scheme: dark) { :root { --hl-0: var(--dark-hl-0); --hl-1: var(--dark-hl-1); --hl-2: var(--dark-hl-2); --hl-3: var(--dark-hl-3); --hl-4: var(--dark-hl-4); --hl-5: var(--dark-hl-5); --hl-6: var(--dark-hl-6); --hl-7: var(--dark-hl-7); --hl-8: var(--dark-hl-8); --hl-9: var(--dark-hl-9); --code-background: var(--dark-code-background); } } :root[data-theme='light'] { --hl-0: var(--light-hl-0); --hl-1: var(--light-hl-1); --hl-2: var(--light-hl-2); --hl-3: var(--light-hl-3); --hl-4: var(--light-hl-4); --hl-5: var(--light-hl-5); --hl-6: var(--light-hl-6); --hl-7: var(--light-hl-7); --hl-8: var(--light-hl-8); --hl-9: var(--light-hl-9); --code-background: var(--light-code-background); } :root[data-theme='dark'] { --hl-0: var(--dark-hl-0); --hl-1: var(--dark-hl-1); --hl-2: var(--dark-hl-2); --hl-3: var(--dark-hl-3); --hl-4: var(--dark-hl-4); --hl-5: var(--dark-hl-5); --hl-6: var(--dark-hl-6); --hl-7: var(--dark-hl-7); --hl-8: var(--dark-hl-8); --hl-9: var(--dark-hl-9); --code-background: var(--dark-code-background); } .hl-0 { color: var(--hl-0); } .hl-1 { color: var(--hl-1); } .hl-2 { color: var(--hl-2); } .hl-3 { color: var(--hl-3); } .hl-4 { color: var(--hl-4); } .hl-5 { color: var(--hl-5); } .hl-6 { color: var(--hl-6); } .hl-7 { color: var(--hl-7); } .hl-8 { color: var(--hl-8); } .hl-9 { color: var(--hl-9); } pre, code { background: var(--code-background); } ================================================ FILE: docs/assets/main.js ================================================ "use strict"; "use strict";(()=>{var Se=Object.create;var re=Object.defineProperty;var we=Object.getOwnPropertyDescriptor;var Te=Object.getOwnPropertyNames;var ke=Object.getPrototypeOf,Qe=Object.prototype.hasOwnProperty;var Pe=(t,e)=>()=>(e||t((e={exports:{}}).exports,e),e.exports);var Ie=(t,e,r,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of Te(e))!Qe.call(t,i)&&i!==r&&re(t,i,{get:()=>e[i],enumerable:!(n=we(e,i))||n.enumerable});return t};var Ce=(t,e,r)=>(r=t!=null?Se(ke(t)):{},Ie(e||!t||!t.__esModule?re(r,"default",{value:t,enumerable:!0}):r,t));var ae=Pe((se,oe)=>{(function(){var t=function(e){var r=new t.Builder;return r.pipeline.add(t.trimmer,t.stopWordFilter,t.stemmer),r.searchPipeline.add(t.stemmer),e.call(r,r),r.build()};t.version="2.3.9";t.utils={},t.utils.warn=function(e){return function(r){e.console&&console.warn&&console.warn(r)}}(this),t.utils.asString=function(e){return e==null?"":e.toString()},t.utils.clone=function(e){if(e==null)return e;for(var r=Object.create(null),n=Object.keys(e),i=0;i0){var d=t.utils.clone(r)||{};d.position=[a,u],d.index=s.length,s.push(new t.Token(n.slice(a,o),d))}a=o+1}}return s},t.tokenizer.separator=/[\s\-]+/;t.Pipeline=function(){this._stack=[]},t.Pipeline.registeredFunctions=Object.create(null),t.Pipeline.registerFunction=function(e,r){r in this.registeredFunctions&&t.utils.warn("Overwriting existing registered function: "+r),e.label=r,t.Pipeline.registeredFunctions[e.label]=e},t.Pipeline.warnIfFunctionNotRegistered=function(e){var r=e.label&&e.label in this.registeredFunctions;r||t.utils.warn(`Function is not registered with pipeline. This may cause problems when serialising the index. `,e)},t.Pipeline.load=function(e){var r=new t.Pipeline;return e.forEach(function(n){var i=t.Pipeline.registeredFunctions[n];if(i)r.add(i);else throw new Error("Cannot load unregistered function: "+n)}),r},t.Pipeline.prototype.add=function(){var e=Array.prototype.slice.call(arguments);e.forEach(function(r){t.Pipeline.warnIfFunctionNotRegistered(r),this._stack.push(r)},this)},t.Pipeline.prototype.after=function(e,r){t.Pipeline.warnIfFunctionNotRegistered(r);var n=this._stack.indexOf(e);if(n==-1)throw new Error("Cannot find existingFn");n=n+1,this._stack.splice(n,0,r)},t.Pipeline.prototype.before=function(e,r){t.Pipeline.warnIfFunctionNotRegistered(r);var n=this._stack.indexOf(e);if(n==-1)throw new Error("Cannot find existingFn");this._stack.splice(n,0,r)},t.Pipeline.prototype.remove=function(e){var r=this._stack.indexOf(e);r!=-1&&this._stack.splice(r,1)},t.Pipeline.prototype.run=function(e){for(var r=this._stack.length,n=0;n1&&(oe&&(n=s),o!=e);)i=n-r,s=r+Math.floor(i/2),o=this.elements[s*2];if(o==e||o>e)return s*2;if(ol?d+=2:a==l&&(r+=n[u+1]*i[d+1],u+=2,d+=2);return r},t.Vector.prototype.similarity=function(e){return this.dot(e)/this.magnitude()||0},t.Vector.prototype.toArray=function(){for(var e=new Array(this.elements.length/2),r=1,n=0;r0){var o=s.str.charAt(0),a;o in s.node.edges?a=s.node.edges[o]:(a=new t.TokenSet,s.node.edges[o]=a),s.str.length==1&&(a.final=!0),i.push({node:a,editsRemaining:s.editsRemaining,str:s.str.slice(1)})}if(s.editsRemaining!=0){if("*"in s.node.edges)var l=s.node.edges["*"];else{var l=new t.TokenSet;s.node.edges["*"]=l}if(s.str.length==0&&(l.final=!0),i.push({node:l,editsRemaining:s.editsRemaining-1,str:s.str}),s.str.length>1&&i.push({node:s.node,editsRemaining:s.editsRemaining-1,str:s.str.slice(1)}),s.str.length==1&&(s.node.final=!0),s.str.length>=1){if("*"in s.node.edges)var u=s.node.edges["*"];else{var u=new t.TokenSet;s.node.edges["*"]=u}s.str.length==1&&(u.final=!0),i.push({node:u,editsRemaining:s.editsRemaining-1,str:s.str.slice(1)})}if(s.str.length>1){var d=s.str.charAt(0),m=s.str.charAt(1),y;m in s.node.edges?y=s.node.edges[m]:(y=new t.TokenSet,s.node.edges[m]=y),s.str.length==1&&(y.final=!0),i.push({node:y,editsRemaining:s.editsRemaining-1,str:d+s.str.slice(2)})}}}return n},t.TokenSet.fromString=function(e){for(var r=new t.TokenSet,n=r,i=0,s=e.length;i=e;r--){var n=this.uncheckedNodes[r],i=n.child.toString();i in this.minimizedNodes?n.parent.edges[n.char]=this.minimizedNodes[i]:(n.child._str=i,this.minimizedNodes[i]=n.child),this.uncheckedNodes.pop()}};t.Index=function(e){this.invertedIndex=e.invertedIndex,this.fieldVectors=e.fieldVectors,this.tokenSet=e.tokenSet,this.fields=e.fields,this.pipeline=e.pipeline},t.Index.prototype.search=function(e){return this.query(function(r){var n=new t.QueryParser(e,r);n.parse()})},t.Index.prototype.query=function(e){for(var r=new t.Query(this.fields),n=Object.create(null),i=Object.create(null),s=Object.create(null),o=Object.create(null),a=Object.create(null),l=0;l1?this._b=1:this._b=e},t.Builder.prototype.k1=function(e){this._k1=e},t.Builder.prototype.add=function(e,r){var n=e[this._ref],i=Object.keys(this._fields);this._documents[n]=r||{},this.documentCount+=1;for(var s=0;s=this.length)return t.QueryLexer.EOS;var e=this.str.charAt(this.pos);return this.pos+=1,e},t.QueryLexer.prototype.width=function(){return this.pos-this.start},t.QueryLexer.prototype.ignore=function(){this.start==this.pos&&(this.pos+=1),this.start=this.pos},t.QueryLexer.prototype.backup=function(){this.pos-=1},t.QueryLexer.prototype.acceptDigitRun=function(){var e,r;do e=this.next(),r=e.charCodeAt(0);while(r>47&&r<58);e!=t.QueryLexer.EOS&&this.backup()},t.QueryLexer.prototype.more=function(){return this.pos1&&(e.backup(),e.emit(t.QueryLexer.TERM)),e.ignore(),e.more())return t.QueryLexer.lexText},t.QueryLexer.lexEditDistance=function(e){return e.ignore(),e.acceptDigitRun(),e.emit(t.QueryLexer.EDIT_DISTANCE),t.QueryLexer.lexText},t.QueryLexer.lexBoost=function(e){return e.ignore(),e.acceptDigitRun(),e.emit(t.QueryLexer.BOOST),t.QueryLexer.lexText},t.QueryLexer.lexEOS=function(e){e.width()>0&&e.emit(t.QueryLexer.TERM)},t.QueryLexer.termSeparator=t.tokenizer.separator,t.QueryLexer.lexText=function(e){for(;;){var r=e.next();if(r==t.QueryLexer.EOS)return t.QueryLexer.lexEOS;if(r.charCodeAt(0)==92){e.escapeCharacter();continue}if(r==":")return t.QueryLexer.lexField;if(r=="~")return e.backup(),e.width()>0&&e.emit(t.QueryLexer.TERM),t.QueryLexer.lexEditDistance;if(r=="^")return e.backup(),e.width()>0&&e.emit(t.QueryLexer.TERM),t.QueryLexer.lexBoost;if(r=="+"&&e.width()===1||r=="-"&&e.width()===1)return e.emit(t.QueryLexer.PRESENCE),t.QueryLexer.lexText;if(r.match(t.QueryLexer.termSeparator))return t.QueryLexer.lexTerm}},t.QueryParser=function(e,r){this.lexer=new t.QueryLexer(e),this.query=r,this.currentClause={},this.lexemeIdx=0},t.QueryParser.prototype.parse=function(){this.lexer.run(),this.lexemes=this.lexer.lexemes;for(var e=t.QueryParser.parseClause;e;)e=e(this);return this.query},t.QueryParser.prototype.peekLexeme=function(){return this.lexemes[this.lexemeIdx]},t.QueryParser.prototype.consumeLexeme=function(){var e=this.peekLexeme();return this.lexemeIdx+=1,e},t.QueryParser.prototype.nextClause=function(){var e=this.currentClause;this.query.clause(e),this.currentClause={}},t.QueryParser.parseClause=function(e){var r=e.peekLexeme();if(r!=null)switch(r.type){case t.QueryLexer.PRESENCE:return t.QueryParser.parsePresence;case t.QueryLexer.FIELD:return t.QueryParser.parseField;case t.QueryLexer.TERM:return t.QueryParser.parseTerm;default:var n="expected either a field or a term, found "+r.type;throw r.str.length>=1&&(n+=" with value '"+r.str+"'"),new t.QueryParseError(n,r.start,r.end)}},t.QueryParser.parsePresence=function(e){var r=e.consumeLexeme();if(r!=null){switch(r.str){case"-":e.currentClause.presence=t.Query.presence.PROHIBITED;break;case"+":e.currentClause.presence=t.Query.presence.REQUIRED;break;default:var n="unrecognised presence operator'"+r.str+"'";throw new t.QueryParseError(n,r.start,r.end)}var i=e.peekLexeme();if(i==null){var n="expecting term or field, found nothing";throw new t.QueryParseError(n,r.start,r.end)}switch(i.type){case t.QueryLexer.FIELD:return t.QueryParser.parseField;case t.QueryLexer.TERM:return t.QueryParser.parseTerm;default:var n="expecting term or field, found '"+i.type+"'";throw new t.QueryParseError(n,i.start,i.end)}}},t.QueryParser.parseField=function(e){var r=e.consumeLexeme();if(r!=null){if(e.query.allFields.indexOf(r.str)==-1){var n=e.query.allFields.map(function(o){return"'"+o+"'"}).join(", "),i="unrecognised field '"+r.str+"', possible fields: "+n;throw new t.QueryParseError(i,r.start,r.end)}e.currentClause.fields=[r.str];var s=e.peekLexeme();if(s==null){var i="expecting term, found nothing";throw new t.QueryParseError(i,r.start,r.end)}switch(s.type){case t.QueryLexer.TERM:return t.QueryParser.parseTerm;default:var i="expecting term, found '"+s.type+"'";throw new t.QueryParseError(i,s.start,s.end)}}},t.QueryParser.parseTerm=function(e){var r=e.consumeLexeme();if(r!=null){e.currentClause.term=r.str.toLowerCase(),r.str.indexOf("*")!=-1&&(e.currentClause.usePipeline=!1);var n=e.peekLexeme();if(n==null){e.nextClause();return}switch(n.type){case t.QueryLexer.TERM:return e.nextClause(),t.QueryParser.parseTerm;case t.QueryLexer.FIELD:return e.nextClause(),t.QueryParser.parseField;case t.QueryLexer.EDIT_DISTANCE:return t.QueryParser.parseEditDistance;case t.QueryLexer.BOOST:return t.QueryParser.parseBoost;case t.QueryLexer.PRESENCE:return e.nextClause(),t.QueryParser.parsePresence;default:var i="Unexpected lexeme type '"+n.type+"'";throw new t.QueryParseError(i,n.start,n.end)}}},t.QueryParser.parseEditDistance=function(e){var r=e.consumeLexeme();if(r!=null){var n=parseInt(r.str,10);if(isNaN(n)){var i="edit distance must be numeric";throw new t.QueryParseError(i,r.start,r.end)}e.currentClause.editDistance=n;var s=e.peekLexeme();if(s==null){e.nextClause();return}switch(s.type){case t.QueryLexer.TERM:return e.nextClause(),t.QueryParser.parseTerm;case t.QueryLexer.FIELD:return e.nextClause(),t.QueryParser.parseField;case t.QueryLexer.EDIT_DISTANCE:return t.QueryParser.parseEditDistance;case t.QueryLexer.BOOST:return t.QueryParser.parseBoost;case t.QueryLexer.PRESENCE:return e.nextClause(),t.QueryParser.parsePresence;default:var i="Unexpected lexeme type '"+s.type+"'";throw new t.QueryParseError(i,s.start,s.end)}}},t.QueryParser.parseBoost=function(e){var r=e.consumeLexeme();if(r!=null){var n=parseInt(r.str,10);if(isNaN(n)){var i="boost must be numeric";throw new t.QueryParseError(i,r.start,r.end)}e.currentClause.boost=n;var s=e.peekLexeme();if(s==null){e.nextClause();return}switch(s.type){case t.QueryLexer.TERM:return e.nextClause(),t.QueryParser.parseTerm;case t.QueryLexer.FIELD:return e.nextClause(),t.QueryParser.parseField;case t.QueryLexer.EDIT_DISTANCE:return t.QueryParser.parseEditDistance;case t.QueryLexer.BOOST:return t.QueryParser.parseBoost;case t.QueryLexer.PRESENCE:return e.nextClause(),t.QueryParser.parsePresence;default:var i="Unexpected lexeme type '"+s.type+"'";throw new t.QueryParseError(i,s.start,s.end)}}},function(e,r){typeof define=="function"&&define.amd?define(r):typeof se=="object"?oe.exports=r():e.lunr=r()}(this,function(){return t})})()});var ne=[];function G(t,e){ne.push({selector:e,constructor:t})}var U=class{constructor(){this.alwaysVisibleMember=null;this.createComponents(document.body),this.ensureActivePageVisible(),this.ensureFocusedElementVisible(),this.listenForCodeCopies(),window.addEventListener("hashchange",()=>this.ensureFocusedElementVisible())}createComponents(e){ne.forEach(r=>{e.querySelectorAll(r.selector).forEach(n=>{n.dataset.hasInstance||(new r.constructor({el:n,app:this}),n.dataset.hasInstance=String(!0))})})}filterChanged(){this.ensureFocusedElementVisible()}ensureActivePageVisible(){let e=document.querySelector(".tsd-navigation .current"),r=e?.parentElement;for(;r&&!r.classList.contains(".tsd-navigation");)r instanceof HTMLDetailsElement&&(r.open=!0),r=r.parentElement;if(e){let n=e.getBoundingClientRect().top-document.documentElement.clientHeight/4;document.querySelector(".site-menu").scrollTop=n}}ensureFocusedElementVisible(){if(this.alwaysVisibleMember&&(this.alwaysVisibleMember.classList.remove("always-visible"),this.alwaysVisibleMember.firstElementChild.remove(),this.alwaysVisibleMember=null),!location.hash)return;let e=document.getElementById(location.hash.substring(1));if(!e)return;let r=e.parentElement;for(;r&&r.tagName!=="SECTION";)r=r.parentElement;if(r&&r.offsetParent==null){this.alwaysVisibleMember=r,r.classList.add("always-visible");let n=document.createElement("p");n.classList.add("warning"),n.textContent="This member is normally hidden due to your filter settings.",r.prepend(n)}}listenForCodeCopies(){document.querySelectorAll("pre > button").forEach(e=>{let r;e.addEventListener("click",()=>{e.previousElementSibling instanceof HTMLElement&&navigator.clipboard.writeText(e.previousElementSibling.innerText.trim()),e.textContent="Copied!",e.classList.add("visible"),clearTimeout(r),r=setTimeout(()=>{e.classList.remove("visible"),r=setTimeout(()=>{e.textContent="Copy"},100)},1e3)})})}};var ie=(t,e=100)=>{let r;return()=>{clearTimeout(r),r=setTimeout(()=>t(),e)}};var ce=Ce(ae());function de(){let t=document.getElementById("tsd-search");if(!t)return;let e=document.getElementById("tsd-search-script");t.classList.add("loading"),e&&(e.addEventListener("error",()=>{t.classList.remove("loading"),t.classList.add("failure")}),e.addEventListener("load",()=>{t.classList.remove("loading"),t.classList.add("ready")}),window.searchData&&t.classList.remove("loading"));let r=document.querySelector("#tsd-search input"),n=document.querySelector("#tsd-search .results");if(!r||!n)throw new Error("The input field or the result list wrapper was not found");let i=!1;n.addEventListener("mousedown",()=>i=!0),n.addEventListener("mouseup",()=>{i=!1,t.classList.remove("has-focus")}),r.addEventListener("focus",()=>t.classList.add("has-focus")),r.addEventListener("blur",()=>{i||(i=!1,t.classList.remove("has-focus"))});let s={base:t.dataset.base+"/"};Oe(t,n,r,s)}function Oe(t,e,r,n){r.addEventListener("input",ie(()=>{Re(t,e,r,n)},200));let i=!1;r.addEventListener("keydown",s=>{i=!0,s.key=="Enter"?Fe(e,r):s.key=="Escape"?r.blur():s.key=="ArrowUp"?ue(e,-1):s.key==="ArrowDown"?ue(e,1):i=!1}),r.addEventListener("keypress",s=>{i&&s.preventDefault()}),document.body.addEventListener("keydown",s=>{s.altKey||s.ctrlKey||s.metaKey||!r.matches(":focus")&&s.key==="/"&&(r.focus(),s.preventDefault())})}function _e(t,e){t.index||window.searchData&&(e.classList.remove("loading"),e.classList.add("ready"),t.data=window.searchData,t.index=ce.Index.load(window.searchData.index))}function Re(t,e,r,n){if(_e(n,t),!n.index||!n.data)return;e.textContent="";let i=r.value.trim(),s=i?n.index.search(`*${i}*`):[];for(let o=0;oa.score-o.score);for(let o=0,a=Math.min(10,s.length);o${le(l.parent,i)}.${u}`);let d=document.createElement("li");d.classList.value=l.classes??"";let m=document.createElement("a");m.href=n.base+l.url,m.innerHTML=u,d.append(m),e.appendChild(d)}}function ue(t,e){let r=t.querySelector(".current");if(!r)r=t.querySelector(e==1?"li:first-child":"li:last-child"),r&&r.classList.add("current");else{let n=r;if(e===1)do n=n.nextElementSibling??void 0;while(n instanceof HTMLElement&&n.offsetParent==null);else do n=n.previousElementSibling??void 0;while(n instanceof HTMLElement&&n.offsetParent==null);n&&(r.classList.remove("current"),n.classList.add("current"))}}function Fe(t,e){let r=t.querySelector(".current");if(r||(r=t.querySelector("li:first-child")),r){let n=r.querySelector("a");n&&(window.location.href=n.href),e.blur()}}function le(t,e){if(e==="")return t;let r=t.toLocaleLowerCase(),n=e.toLocaleLowerCase(),i=[],s=0,o=r.indexOf(n);for(;o!=-1;)i.push(K(t.substring(s,o)),`${K(t.substring(o,o+n.length))}`),s=o+n.length,o=r.indexOf(n,s);return i.push(K(t.substring(s))),i.join("")}var Me={"&":"&","<":"<",">":">","'":"'",'"':"""};function K(t){return t.replace(/[&<>"'"]/g,e=>Me[e])}var P=class{constructor(e){this.el=e.el,this.app=e.app}};var M="mousedown",fe="mousemove",N="mouseup",J={x:0,y:0},he=!1,ee=!1,De=!1,D=!1,pe=/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);document.documentElement.classList.add(pe?"is-mobile":"not-mobile");pe&&"ontouchstart"in document.documentElement&&(De=!0,M="touchstart",fe="touchmove",N="touchend");document.addEventListener(M,t=>{ee=!0,D=!1;let e=M=="touchstart"?t.targetTouches[0]:t;J.y=e.pageY||0,J.x=e.pageX||0});document.addEventListener(fe,t=>{if(ee&&!D){let e=M=="touchstart"?t.targetTouches[0]:t,r=J.x-(e.pageX||0),n=J.y-(e.pageY||0);D=Math.sqrt(r*r+n*n)>10}});document.addEventListener(N,()=>{ee=!1});document.addEventListener("click",t=>{he&&(t.preventDefault(),t.stopImmediatePropagation(),he=!1)});var X=class extends P{constructor(r){super(r);this.className=this.el.dataset.toggle||"",this.el.addEventListener(N,n=>this.onPointerUp(n)),this.el.addEventListener("click",n=>n.preventDefault()),document.addEventListener(M,n=>this.onDocumentPointerDown(n)),document.addEventListener(N,n=>this.onDocumentPointerUp(n))}setActive(r){if(this.active==r)return;this.active=r,document.documentElement.classList.toggle("has-"+this.className,r),this.el.classList.toggle("active",r);let n=(this.active?"to-has-":"from-has-")+this.className;document.documentElement.classList.add(n),setTimeout(()=>document.documentElement.classList.remove(n),500)}onPointerUp(r){D||(this.setActive(!0),r.preventDefault())}onDocumentPointerDown(r){if(this.active){if(r.target.closest(".col-sidebar, .tsd-filter-group"))return;this.setActive(!1)}}onDocumentPointerUp(r){if(!D&&this.active&&r.target.closest(".col-sidebar")){let n=r.target.closest("a");if(n){let i=window.location.href;i.indexOf("#")!=-1&&(i=i.substring(0,i.indexOf("#"))),n.href.substring(0,i.length)==i&&setTimeout(()=>this.setActive(!1),250)}}}};var te;try{te=localStorage}catch{te={getItem(){return null},setItem(){}}}var Q=te;var me=document.head.appendChild(document.createElement("style"));me.dataset.for="filters";var Y=class extends P{constructor(r){super(r);this.key=`filter-${this.el.name}`,this.value=this.el.checked,this.el.addEventListener("change",()=>{this.setLocalStorage(this.el.checked)}),this.setLocalStorage(this.fromLocalStorage()),me.innerHTML+=`html:not(.${this.key}) .tsd-is-${this.el.name} { display: none; } `}fromLocalStorage(){let r=Q.getItem(this.key);return r?r==="true":this.el.checked}setLocalStorage(r){Q.setItem(this.key,r.toString()),this.value=r,this.handleValueChange()}handleValueChange(){this.el.checked=this.value,document.documentElement.classList.toggle(this.key,this.value),this.app.filterChanged(),document.querySelectorAll(".tsd-index-section").forEach(r=>{r.style.display="block";let n=Array.from(r.querySelectorAll(".tsd-index-link")).every(i=>i.offsetParent==null);r.style.display=n?"none":"block"})}};var Z=class extends P{constructor(r){super(r);this.summary=this.el.querySelector(".tsd-accordion-summary"),this.icon=this.summary.querySelector("svg"),this.key=`tsd-accordion-${this.summary.dataset.key??this.summary.textContent.trim().replace(/\s+/g,"-").toLowerCase()}`;let n=Q.getItem(this.key);this.el.open=n?n==="true":this.el.open,this.el.addEventListener("toggle",()=>this.update()),this.update()}update(){this.icon.style.transform=`rotate(${this.el.open?0:-90}deg)`,Q.setItem(this.key,this.el.open.toString())}};function ve(t){let e=Q.getItem("tsd-theme")||"os";t.value=e,ye(e),t.addEventListener("change",()=>{Q.setItem("tsd-theme",t.value),ye(t.value)})}function ye(t){document.documentElement.dataset.theme=t}de();G(X,"a[data-toggle]");G(Z,".tsd-index-accordion");G(Y,".tsd-filter-item input[type=checkbox]");var ge=document.getElementById("tsd-theme");ge&&ve(ge);var Ae=new U;Object.defineProperty(window,"app",{value:Ae});document.querySelectorAll("summary a").forEach(t=>{t.addEventListener("click",()=>{location.assign(t.href)})});})(); /*! Bundled license information: lunr/lunr.js: (** * lunr - http://lunrjs.com - A bit like Solr, but much smaller and not as bright - 2.3.9 * Copyright (C) 2020 Oliver Nightingale * @license MIT *) (*! * lunr.utils * Copyright (C) 2020 Oliver Nightingale *) (*! * lunr.Set * Copyright (C) 2020 Oliver Nightingale *) (*! * lunr.tokenizer * Copyright (C) 2020 Oliver Nightingale *) (*! * lunr.Pipeline * Copyright (C) 2020 Oliver Nightingale *) (*! * lunr.Vector * Copyright (C) 2020 Oliver Nightingale *) (*! * lunr.stemmer * Copyright (C) 2020 Oliver Nightingale * Includes code from - http://tartarus.org/~martin/PorterStemmer/js.txt *) (*! * lunr.stopWordFilter * Copyright (C) 2020 Oliver Nightingale *) (*! * lunr.trimmer * Copyright (C) 2020 Oliver Nightingale *) (*! * lunr.TokenSet * Copyright (C) 2020 Oliver Nightingale *) (*! * lunr.Index * Copyright (C) 2020 Oliver Nightingale *) (*! * lunr.Builder * Copyright (C) 2020 Oliver Nightingale *) */ ================================================ FILE: docs/assets/search.js ================================================ window.searchData = JSON.parse("{\"rows\":[{\"kind\":8,\"name\":\"ApiList\",\"url\":\"enums/ApiList.html\",\"classes\":\"\"},{\"kind\":16,\"name\":\"GLOSSARY\",\"url\":\"enums/ApiList.html#GLOSSARY\",\"classes\":\"\",\"parent\":\"ApiList\"},{\"kind\":16,\"name\":\"HOLIDAY_TRADING\",\"url\":\"enums/ApiList.html#HOLIDAY_TRADING\",\"classes\":\"\",\"parent\":\"ApiList\"},{\"kind\":16,\"name\":\"HOLIDAY_CLEARING\",\"url\":\"enums/ApiList.html#HOLIDAY_CLEARING\",\"classes\":\"\",\"parent\":\"ApiList\"},{\"kind\":16,\"name\":\"MARKET_STATUS\",\"url\":\"enums/ApiList.html#MARKET_STATUS\",\"classes\":\"\",\"parent\":\"ApiList\"},{\"kind\":16,\"name\":\"MARKET_TURNOVER\",\"url\":\"enums/ApiList.html#MARKET_TURNOVER\",\"classes\":\"\",\"parent\":\"ApiList\"},{\"kind\":16,\"name\":\"ALL_INDICES\",\"url\":\"enums/ApiList.html#ALL_INDICES\",\"classes\":\"\",\"parent\":\"ApiList\"},{\"kind\":16,\"name\":\"INDEX_NAMES\",\"url\":\"enums/ApiList.html#INDEX_NAMES\",\"classes\":\"\",\"parent\":\"ApiList\"},{\"kind\":16,\"name\":\"CIRCULARS\",\"url\":\"enums/ApiList.html#CIRCULARS\",\"classes\":\"\",\"parent\":\"ApiList\"},{\"kind\":16,\"name\":\"LATEST_CIRCULARS\",\"url\":\"enums/ApiList.html#LATEST_CIRCULARS\",\"classes\":\"\",\"parent\":\"ApiList\"},{\"kind\":16,\"name\":\"EQUITY_MASTER\",\"url\":\"enums/ApiList.html#EQUITY_MASTER\",\"classes\":\"\",\"parent\":\"ApiList\"},{\"kind\":16,\"name\":\"MARKET_DATA_PRE_OPEN\",\"url\":\"enums/ApiList.html#MARKET_DATA_PRE_OPEN\",\"classes\":\"\",\"parent\":\"ApiList\"},{\"kind\":16,\"name\":\"MERGED_DAILY_REPORTS_CAPITAL\",\"url\":\"enums/ApiList.html#MERGED_DAILY_REPORTS_CAPITAL\",\"classes\":\"\",\"parent\":\"ApiList\"},{\"kind\":16,\"name\":\"MERGED_DAILY_REPORTS_DERIVATIVES\",\"url\":\"enums/ApiList.html#MERGED_DAILY_REPORTS_DERIVATIVES\",\"classes\":\"\",\"parent\":\"ApiList\"},{\"kind\":16,\"name\":\"MERGED_DAILY_REPORTS_DEBT\",\"url\":\"enums/ApiList.html#MERGED_DAILY_REPORTS_DEBT\",\"classes\":\"\",\"parent\":\"ApiList\"},{\"kind\":128,\"name\":\"NseIndia\",\"url\":\"classes/NseIndia.html\",\"classes\":\"\"},{\"kind\":512,\"name\":\"constructor\",\"url\":\"classes/NseIndia.html#constructor\",\"classes\":\"\",\"parent\":\"NseIndia\"},{\"kind\":2048,\"name\":\"getData\",\"url\":\"classes/NseIndia.html#getData\",\"classes\":\"\",\"parent\":\"NseIndia\"},{\"kind\":2048,\"name\":\"getDataByEndpoint\",\"url\":\"classes/NseIndia.html#getDataByEndpoint\",\"classes\":\"\",\"parent\":\"NseIndia\"},{\"kind\":2048,\"name\":\"getAllStockSymbols\",\"url\":\"classes/NseIndia.html#getAllStockSymbols\",\"classes\":\"\",\"parent\":\"NseIndia\"},{\"kind\":2048,\"name\":\"getEquityDetails\",\"url\":\"classes/NseIndia.html#getEquityDetails\",\"classes\":\"\",\"parent\":\"NseIndia\"},{\"kind\":2048,\"name\":\"getEquityTradeInfo\",\"url\":\"classes/NseIndia.html#getEquityTradeInfo\",\"classes\":\"\",\"parent\":\"NseIndia\"},{\"kind\":2048,\"name\":\"getEquityCorporateInfo\",\"url\":\"classes/NseIndia.html#getEquityCorporateInfo\",\"classes\":\"\",\"parent\":\"NseIndia\"},{\"kind\":2048,\"name\":\"getEquityIntradayData\",\"url\":\"classes/NseIndia.html#getEquityIntradayData\",\"classes\":\"\",\"parent\":\"NseIndia\"},{\"kind\":2048,\"name\":\"getEquityHistoricalData\",\"url\":\"classes/NseIndia.html#getEquityHistoricalData\",\"classes\":\"\",\"parent\":\"NseIndia\"},{\"kind\":2048,\"name\":\"getEquitySeries\",\"url\":\"classes/NseIndia.html#getEquitySeries\",\"classes\":\"\",\"parent\":\"NseIndia\"},{\"kind\":2048,\"name\":\"getEquityStockIndices\",\"url\":\"classes/NseIndia.html#getEquityStockIndices\",\"classes\":\"\",\"parent\":\"NseIndia\"},{\"kind\":2048,\"name\":\"getIndexIntradayData\",\"url\":\"classes/NseIndia.html#getIndexIntradayData\",\"classes\":\"\",\"parent\":\"NseIndia\"},{\"kind\":2048,\"name\":\"getIndexOptionChainContractInfo\",\"url\":\"classes/NseIndia.html#getIndexOptionChainContractInfo\",\"classes\":\"\",\"parent\":\"NseIndia\"},{\"kind\":2048,\"name\":\"getIndexOptionChain\",\"url\":\"classes/NseIndia.html#getIndexOptionChain\",\"classes\":\"\",\"parent\":\"NseIndia\"},{\"kind\":2048,\"name\":\"getEquityOptionChain\",\"url\":\"classes/NseIndia.html#getEquityOptionChain\",\"classes\":\"\",\"parent\":\"NseIndia\"},{\"kind\":2048,\"name\":\"getCommodityOptionChain\",\"url\":\"classes/NseIndia.html#getCommodityOptionChain\",\"classes\":\"\",\"parent\":\"NseIndia\"},{\"kind\":2048,\"name\":\"getGlossary\",\"url\":\"classes/NseIndia.html#getGlossary\",\"classes\":\"\",\"parent\":\"NseIndia\"},{\"kind\":2048,\"name\":\"getTradingHolidays\",\"url\":\"classes/NseIndia.html#getTradingHolidays\",\"classes\":\"\",\"parent\":\"NseIndia\"},{\"kind\":2048,\"name\":\"getClearingHolidays\",\"url\":\"classes/NseIndia.html#getClearingHolidays\",\"classes\":\"\",\"parent\":\"NseIndia\"},{\"kind\":2048,\"name\":\"getMarketStatus\",\"url\":\"classes/NseIndia.html#getMarketStatus\",\"classes\":\"\",\"parent\":\"NseIndia\"},{\"kind\":2048,\"name\":\"getMarketTurnover\",\"url\":\"classes/NseIndia.html#getMarketTurnover\",\"classes\":\"\",\"parent\":\"NseIndia\"},{\"kind\":2048,\"name\":\"getAllIndices\",\"url\":\"classes/NseIndia.html#getAllIndices\",\"classes\":\"\",\"parent\":\"NseIndia\"},{\"kind\":2048,\"name\":\"getIndexNames\",\"url\":\"classes/NseIndia.html#getIndexNames\",\"classes\":\"\",\"parent\":\"NseIndia\"},{\"kind\":2048,\"name\":\"getCirculars\",\"url\":\"classes/NseIndia.html#getCirculars\",\"classes\":\"\",\"parent\":\"NseIndia\"},{\"kind\":2048,\"name\":\"getLatestCirculars\",\"url\":\"classes/NseIndia.html#getLatestCirculars\",\"classes\":\"\",\"parent\":\"NseIndia\"},{\"kind\":2048,\"name\":\"getEquityMaster\",\"url\":\"classes/NseIndia.html#getEquityMaster\",\"classes\":\"\",\"parent\":\"NseIndia\"},{\"kind\":2048,\"name\":\"getPreOpenMarketData\",\"url\":\"classes/NseIndia.html#getPreOpenMarketData\",\"classes\":\"\",\"parent\":\"NseIndia\"},{\"kind\":2048,\"name\":\"getMergedDailyReportsCapital\",\"url\":\"classes/NseIndia.html#getMergedDailyReportsCapital\",\"classes\":\"\",\"parent\":\"NseIndia\"},{\"kind\":2048,\"name\":\"getMergedDailyReportsDerivatives\",\"url\":\"classes/NseIndia.html#getMergedDailyReportsDerivatives\",\"classes\":\"\",\"parent\":\"NseIndia\"},{\"kind\":2048,\"name\":\"getMergedDailyReportsDebt\",\"url\":\"classes/NseIndia.html#getMergedDailyReportsDebt\",\"classes\":\"\",\"parent\":\"NseIndia\"},{\"kind\":2048,\"name\":\"getTechnicalIndicators\",\"url\":\"classes/NseIndia.html#getTechnicalIndicators\",\"classes\":\"\",\"parent\":\"NseIndia\"},{\"kind\":256,\"name\":\"DateRange\",\"url\":\"interfaces/DateRange.html\",\"classes\":\"\"},{\"kind\":1024,\"name\":\"start\",\"url\":\"interfaces/DateRange.html#start\",\"classes\":\"\",\"parent\":\"DateRange\"},{\"kind\":1024,\"name\":\"end\",\"url\":\"interfaces/DateRange.html#end\",\"classes\":\"\",\"parent\":\"DateRange\"},{\"kind\":256,\"name\":\"IntradayData\",\"url\":\"interfaces/IntradayData.html\",\"classes\":\"\"},{\"kind\":1024,\"name\":\"identifier\",\"url\":\"interfaces/IntradayData.html#identifier\",\"classes\":\"\",\"parent\":\"IntradayData\"},{\"kind\":1024,\"name\":\"name\",\"url\":\"interfaces/IntradayData.html#name\",\"classes\":\"\",\"parent\":\"IntradayData\"},{\"kind\":1024,\"name\":\"grapthData\",\"url\":\"interfaces/IntradayData.html#grapthData\",\"classes\":\"\",\"parent\":\"IntradayData\"},{\"kind\":1024,\"name\":\"closePrice\",\"url\":\"interfaces/IntradayData.html#closePrice\",\"classes\":\"\",\"parent\":\"IntradayData\"},{\"kind\":256,\"name\":\"EquityDetails\",\"url\":\"interfaces/EquityDetails.html\",\"classes\":\"\"},{\"kind\":1024,\"name\":\"info\",\"url\":\"interfaces/EquityDetails.html#info\",\"classes\":\"\",\"parent\":\"EquityDetails\"},{\"kind\":1024,\"name\":\"metadata\",\"url\":\"interfaces/EquityDetails.html#metadata\",\"classes\":\"\",\"parent\":\"EquityDetails\"},{\"kind\":1024,\"name\":\"securityInfo\",\"url\":\"interfaces/EquityDetails.html#securityInfo\",\"classes\":\"\",\"parent\":\"EquityDetails\"},{\"kind\":1024,\"name\":\"sddDetails\",\"url\":\"interfaces/EquityDetails.html#sddDetails\",\"classes\":\"\",\"parent\":\"EquityDetails\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"interfaces/EquityDetails.html#sddDetails.__type-1\",\"classes\":\"\",\"parent\":\"EquityDetails.sddDetails\"},{\"kind\":1024,\"name\":\"SDDAuditor\",\"url\":\"interfaces/EquityDetails.html#sddDetails.__type-1.SDDAuditor\",\"classes\":\"\",\"parent\":\"EquityDetails.sddDetails.__type\"},{\"kind\":1024,\"name\":\"SDDStatus\",\"url\":\"interfaces/EquityDetails.html#sddDetails.__type-1.SDDStatus\",\"classes\":\"\",\"parent\":\"EquityDetails.sddDetails.__type\"},{\"kind\":1024,\"name\":\"currentMarketType\",\"url\":\"interfaces/EquityDetails.html#currentMarketType\",\"classes\":\"\",\"parent\":\"EquityDetails\"},{\"kind\":1024,\"name\":\"priceInfo\",\"url\":\"interfaces/EquityDetails.html#priceInfo\",\"classes\":\"\",\"parent\":\"EquityDetails\"},{\"kind\":1024,\"name\":\"industryInfo\",\"url\":\"interfaces/EquityDetails.html#industryInfo\",\"classes\":\"\",\"parent\":\"EquityDetails\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"interfaces/EquityDetails.html#industryInfo.__type\",\"classes\":\"\",\"parent\":\"EquityDetails.industryInfo\"},{\"kind\":1024,\"name\":\"macro\",\"url\":\"interfaces/EquityDetails.html#industryInfo.__type.macro\",\"classes\":\"\",\"parent\":\"EquityDetails.industryInfo.__type\"},{\"kind\":1024,\"name\":\"sector\",\"url\":\"interfaces/EquityDetails.html#industryInfo.__type.sector\",\"classes\":\"\",\"parent\":\"EquityDetails.industryInfo.__type\"},{\"kind\":1024,\"name\":\"industry\",\"url\":\"interfaces/EquityDetails.html#industryInfo.__type.industry\",\"classes\":\"\",\"parent\":\"EquityDetails.industryInfo.__type\"},{\"kind\":1024,\"name\":\"basicIndustry\",\"url\":\"interfaces/EquityDetails.html#industryInfo.__type.basicIndustry\",\"classes\":\"\",\"parent\":\"EquityDetails.industryInfo.__type\"},{\"kind\":1024,\"name\":\"preOpenMarket\",\"url\":\"interfaces/EquityDetails.html#preOpenMarket\",\"classes\":\"\",\"parent\":\"EquityDetails\"},{\"kind\":256,\"name\":\"EquityTradeInfo\",\"url\":\"interfaces/EquityTradeInfo.html\",\"classes\":\"\"},{\"kind\":1024,\"name\":\"noBlockDeals\",\"url\":\"interfaces/EquityTradeInfo.html#noBlockDeals\",\"classes\":\"\",\"parent\":\"EquityTradeInfo\"},{\"kind\":1024,\"name\":\"bulkBlockDeals\",\"url\":\"interfaces/EquityTradeInfo.html#bulkBlockDeals\",\"classes\":\"\",\"parent\":\"EquityTradeInfo\"},{\"kind\":1024,\"name\":\"marketDeptOrderBook\",\"url\":\"interfaces/EquityTradeInfo.html#marketDeptOrderBook\",\"classes\":\"\",\"parent\":\"EquityTradeInfo\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"interfaces/EquityTradeInfo.html#marketDeptOrderBook.__type\",\"classes\":\"\",\"parent\":\"EquityTradeInfo.marketDeptOrderBook\"},{\"kind\":1024,\"name\":\"totalBuyQuantity\",\"url\":\"interfaces/EquityTradeInfo.html#marketDeptOrderBook.__type.totalBuyQuantity\",\"classes\":\"\",\"parent\":\"EquityTradeInfo.marketDeptOrderBook.__type\"},{\"kind\":1024,\"name\":\"totalSellQuantity\",\"url\":\"interfaces/EquityTradeInfo.html#marketDeptOrderBook.__type.totalSellQuantity\",\"classes\":\"\",\"parent\":\"EquityTradeInfo.marketDeptOrderBook.__type\"},{\"kind\":1024,\"name\":\"open\",\"url\":\"interfaces/EquityTradeInfo.html#marketDeptOrderBook.__type.open\",\"classes\":\"\",\"parent\":\"EquityTradeInfo.marketDeptOrderBook.__type\"},{\"kind\":1024,\"name\":\"bid\",\"url\":\"interfaces/EquityTradeInfo.html#marketDeptOrderBook.__type.bid\",\"classes\":\"\",\"parent\":\"EquityTradeInfo.marketDeptOrderBook.__type\"},{\"kind\":1024,\"name\":\"ask\",\"url\":\"interfaces/EquityTradeInfo.html#marketDeptOrderBook.__type.ask\",\"classes\":\"\",\"parent\":\"EquityTradeInfo.marketDeptOrderBook.__type\"},{\"kind\":1024,\"name\":\"tradeInfo\",\"url\":\"interfaces/EquityTradeInfo.html#marketDeptOrderBook.__type.tradeInfo\",\"classes\":\"\",\"parent\":\"EquityTradeInfo.marketDeptOrderBook.__type\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"interfaces/EquityTradeInfo.html#marketDeptOrderBook.__type.tradeInfo.__type-1\",\"classes\":\"\",\"parent\":\"EquityTradeInfo.marketDeptOrderBook.__type.tradeInfo\"},{\"kind\":1024,\"name\":\"totalTradedVolume\",\"url\":\"interfaces/EquityTradeInfo.html#marketDeptOrderBook.__type.tradeInfo.__type-1.totalTradedVolume\",\"classes\":\"\",\"parent\":\"EquityTradeInfo.marketDeptOrderBook.__type.tradeInfo.__type\"},{\"kind\":1024,\"name\":\"totalTradedValue\",\"url\":\"interfaces/EquityTradeInfo.html#marketDeptOrderBook.__type.tradeInfo.__type-1.totalTradedValue\",\"classes\":\"\",\"parent\":\"EquityTradeInfo.marketDeptOrderBook.__type.tradeInfo.__type\"},{\"kind\":1024,\"name\":\"totalMarketCap\",\"url\":\"interfaces/EquityTradeInfo.html#marketDeptOrderBook.__type.tradeInfo.__type-1.totalMarketCap\",\"classes\":\"\",\"parent\":\"EquityTradeInfo.marketDeptOrderBook.__type.tradeInfo.__type\"},{\"kind\":1024,\"name\":\"ffmc\",\"url\":\"interfaces/EquityTradeInfo.html#marketDeptOrderBook.__type.tradeInfo.__type-1.ffmc\",\"classes\":\"\",\"parent\":\"EquityTradeInfo.marketDeptOrderBook.__type.tradeInfo.__type\"},{\"kind\":1024,\"name\":\"impactCost\",\"url\":\"interfaces/EquityTradeInfo.html#marketDeptOrderBook.__type.tradeInfo.__type-1.impactCost\",\"classes\":\"\",\"parent\":\"EquityTradeInfo.marketDeptOrderBook.__type.tradeInfo.__type\"},{\"kind\":1024,\"name\":\"cmDailyVolatility\",\"url\":\"interfaces/EquityTradeInfo.html#marketDeptOrderBook.__type.tradeInfo.__type-1.cmDailyVolatility\",\"classes\":\"\",\"parent\":\"EquityTradeInfo.marketDeptOrderBook.__type.tradeInfo.__type\"},{\"kind\":1024,\"name\":\"cmAnnualVolatility\",\"url\":\"interfaces/EquityTradeInfo.html#marketDeptOrderBook.__type.tradeInfo.__type-1.cmAnnualVolatility\",\"classes\":\"\",\"parent\":\"EquityTradeInfo.marketDeptOrderBook.__type.tradeInfo.__type\"},{\"kind\":1024,\"name\":\"marketLot\",\"url\":\"interfaces/EquityTradeInfo.html#marketDeptOrderBook.__type.tradeInfo.__type-1.marketLot\",\"classes\":\"\",\"parent\":\"EquityTradeInfo.marketDeptOrderBook.__type.tradeInfo.__type\"},{\"kind\":1024,\"name\":\"activeSeries\",\"url\":\"interfaces/EquityTradeInfo.html#marketDeptOrderBook.__type.tradeInfo.__type-1.activeSeries\",\"classes\":\"\",\"parent\":\"EquityTradeInfo.marketDeptOrderBook.__type.tradeInfo.__type\"},{\"kind\":1024,\"name\":\"valueAtRisk\",\"url\":\"interfaces/EquityTradeInfo.html#marketDeptOrderBook.__type.valueAtRisk\",\"classes\":\"\",\"parent\":\"EquityTradeInfo.marketDeptOrderBook.__type\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"interfaces/EquityTradeInfo.html#marketDeptOrderBook.__type.valueAtRisk.__type-2\",\"classes\":\"\",\"parent\":\"EquityTradeInfo.marketDeptOrderBook.__type.valueAtRisk\"},{\"kind\":1024,\"name\":\"securityVar\",\"url\":\"interfaces/EquityTradeInfo.html#marketDeptOrderBook.__type.valueAtRisk.__type-2.securityVar\",\"classes\":\"\",\"parent\":\"EquityTradeInfo.marketDeptOrderBook.__type.valueAtRisk.__type\"},{\"kind\":1024,\"name\":\"indexVar\",\"url\":\"interfaces/EquityTradeInfo.html#marketDeptOrderBook.__type.valueAtRisk.__type-2.indexVar\",\"classes\":\"\",\"parent\":\"EquityTradeInfo.marketDeptOrderBook.__type.valueAtRisk.__type\"},{\"kind\":1024,\"name\":\"varMargin\",\"url\":\"interfaces/EquityTradeInfo.html#marketDeptOrderBook.__type.valueAtRisk.__type-2.varMargin\",\"classes\":\"\",\"parent\":\"EquityTradeInfo.marketDeptOrderBook.__type.valueAtRisk.__type\"},{\"kind\":1024,\"name\":\"extremeLossMargin\",\"url\":\"interfaces/EquityTradeInfo.html#marketDeptOrderBook.__type.valueAtRisk.__type-2.extremeLossMargin\",\"classes\":\"\",\"parent\":\"EquityTradeInfo.marketDeptOrderBook.__type.valueAtRisk.__type\"},{\"kind\":1024,\"name\":\"adhocMargin\",\"url\":\"interfaces/EquityTradeInfo.html#marketDeptOrderBook.__type.valueAtRisk.__type-2.adhocMargin\",\"classes\":\"\",\"parent\":\"EquityTradeInfo.marketDeptOrderBook.__type.valueAtRisk.__type\"},{\"kind\":1024,\"name\":\"applicableMargin\",\"url\":\"interfaces/EquityTradeInfo.html#marketDeptOrderBook.__type.valueAtRisk.__type-2.applicableMargin\",\"classes\":\"\",\"parent\":\"EquityTradeInfo.marketDeptOrderBook.__type.valueAtRisk.__type\"},{\"kind\":1024,\"name\":\"securityWiseDP\",\"url\":\"interfaces/EquityTradeInfo.html#securityWiseDP\",\"classes\":\"\",\"parent\":\"EquityTradeInfo\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"interfaces/EquityTradeInfo.html#securityWiseDP.__type-3\",\"classes\":\"\",\"parent\":\"EquityTradeInfo.securityWiseDP\"},{\"kind\":1024,\"name\":\"quantityTraded\",\"url\":\"interfaces/EquityTradeInfo.html#securityWiseDP.__type-3.quantityTraded\",\"classes\":\"\",\"parent\":\"EquityTradeInfo.securityWiseDP.__type\"},{\"kind\":1024,\"name\":\"deliveryQuantity\",\"url\":\"interfaces/EquityTradeInfo.html#securityWiseDP.__type-3.deliveryQuantity\",\"classes\":\"\",\"parent\":\"EquityTradeInfo.securityWiseDP.__type\"},{\"kind\":1024,\"name\":\"deliveryToTradedQuantity\",\"url\":\"interfaces/EquityTradeInfo.html#securityWiseDP.__type-3.deliveryToTradedQuantity\",\"classes\":\"\",\"parent\":\"EquityTradeInfo.securityWiseDP.__type\"},{\"kind\":1024,\"name\":\"seriesRemarks\",\"url\":\"interfaces/EquityTradeInfo.html#securityWiseDP.__type-3.seriesRemarks\",\"classes\":\"\",\"parent\":\"EquityTradeInfo.securityWiseDP.__type\"},{\"kind\":1024,\"name\":\"secWiseDelPosDate\",\"url\":\"interfaces/EquityTradeInfo.html#securityWiseDP.__type-3.secWiseDelPosDate\",\"classes\":\"\",\"parent\":\"EquityTradeInfo.securityWiseDP.__type\"},{\"kind\":256,\"name\":\"EquityHistoricalData\",\"url\":\"interfaces/EquityHistoricalData.html\",\"classes\":\"\"},{\"kind\":1024,\"name\":\"data\",\"url\":\"interfaces/EquityHistoricalData.html#data\",\"classes\":\"\",\"parent\":\"EquityHistoricalData\"},{\"kind\":1024,\"name\":\"meta\",\"url\":\"interfaces/EquityHistoricalData.html#meta\",\"classes\":\"\",\"parent\":\"EquityHistoricalData\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"interfaces/EquityHistoricalData.html#meta.__type\",\"classes\":\"\",\"parent\":\"EquityHistoricalData.meta\"},{\"kind\":1024,\"name\":\"series\",\"url\":\"interfaces/EquityHistoricalData.html#meta.__type.series\",\"classes\":\"\",\"parent\":\"EquityHistoricalData.meta.__type\"},{\"kind\":1024,\"name\":\"fromDate\",\"url\":\"interfaces/EquityHistoricalData.html#meta.__type.fromDate\",\"classes\":\"\",\"parent\":\"EquityHistoricalData.meta.__type\"},{\"kind\":1024,\"name\":\"toDate\",\"url\":\"interfaces/EquityHistoricalData.html#meta.__type.toDate\",\"classes\":\"\",\"parent\":\"EquityHistoricalData.meta.__type\"},{\"kind\":1024,\"name\":\"symbols\",\"url\":\"interfaces/EquityHistoricalData.html#meta.__type.symbols\",\"classes\":\"\",\"parent\":\"EquityHistoricalData.meta.__type\"},{\"kind\":256,\"name\":\"SeriesData\",\"url\":\"interfaces/SeriesData.html\",\"classes\":\"\"},{\"kind\":1024,\"name\":\"data\",\"url\":\"interfaces/SeriesData.html#data\",\"classes\":\"\",\"parent\":\"SeriesData\"},{\"kind\":256,\"name\":\"IndexDetails\",\"url\":\"interfaces/IndexDetails.html\",\"classes\":\"\"},{\"kind\":1024,\"name\":\"name\",\"url\":\"interfaces/IndexDetails.html#name\",\"classes\":\"\",\"parent\":\"IndexDetails\"},{\"kind\":1024,\"name\":\"advance\",\"url\":\"interfaces/IndexDetails.html#advance\",\"classes\":\"\",\"parent\":\"IndexDetails\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"interfaces/IndexDetails.html#advance.__type\",\"classes\":\"\",\"parent\":\"IndexDetails.advance\"},{\"kind\":1024,\"name\":\"declines\",\"url\":\"interfaces/IndexDetails.html#advance.__type.declines\",\"classes\":\"\",\"parent\":\"IndexDetails.advance.__type\"},{\"kind\":1024,\"name\":\"advances\",\"url\":\"interfaces/IndexDetails.html#advance.__type.advances\",\"classes\":\"\",\"parent\":\"IndexDetails.advance.__type\"},{\"kind\":1024,\"name\":\"unchanged\",\"url\":\"interfaces/IndexDetails.html#advance.__type.unchanged\",\"classes\":\"\",\"parent\":\"IndexDetails.advance.__type\"},{\"kind\":1024,\"name\":\"timestamp\",\"url\":\"interfaces/IndexDetails.html#timestamp\",\"classes\":\"\",\"parent\":\"IndexDetails\"},{\"kind\":1024,\"name\":\"data\",\"url\":\"interfaces/IndexDetails.html#data\",\"classes\":\"\",\"parent\":\"IndexDetails\"},{\"kind\":1024,\"name\":\"metadata\",\"url\":\"interfaces/IndexDetails.html#metadata\",\"classes\":\"\",\"parent\":\"IndexDetails\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"interfaces/IndexDetails.html#metadata.__type-2\",\"classes\":\"\",\"parent\":\"IndexDetails.metadata\"},{\"kind\":1024,\"name\":\"indexName\",\"url\":\"interfaces/IndexDetails.html#metadata.__type-2.indexName\",\"classes\":\"\",\"parent\":\"IndexDetails.metadata.__type\"},{\"kind\":1024,\"name\":\"open\",\"url\":\"interfaces/IndexDetails.html#metadata.__type-2.open\",\"classes\":\"\",\"parent\":\"IndexDetails.metadata.__type\"},{\"kind\":1024,\"name\":\"high\",\"url\":\"interfaces/IndexDetails.html#metadata.__type-2.high\",\"classes\":\"\",\"parent\":\"IndexDetails.metadata.__type\"},{\"kind\":1024,\"name\":\"low\",\"url\":\"interfaces/IndexDetails.html#metadata.__type-2.low\",\"classes\":\"\",\"parent\":\"IndexDetails.metadata.__type\"},{\"kind\":1024,\"name\":\"previousClose\",\"url\":\"interfaces/IndexDetails.html#metadata.__type-2.previousClose\",\"classes\":\"\",\"parent\":\"IndexDetails.metadata.__type\"},{\"kind\":1024,\"name\":\"last\",\"url\":\"interfaces/IndexDetails.html#metadata.__type-2.last-1\",\"classes\":\"\",\"parent\":\"IndexDetails.metadata.__type\"},{\"kind\":1024,\"name\":\"percChange\",\"url\":\"interfaces/IndexDetails.html#metadata.__type-2.percChange\",\"classes\":\"\",\"parent\":\"IndexDetails.metadata.__type\"},{\"kind\":1024,\"name\":\"change\",\"url\":\"interfaces/IndexDetails.html#metadata.__type-2.change\",\"classes\":\"\",\"parent\":\"IndexDetails.metadata.__type\"},{\"kind\":1024,\"name\":\"timeVal\",\"url\":\"interfaces/IndexDetails.html#metadata.__type-2.timeVal\",\"classes\":\"\",\"parent\":\"IndexDetails.metadata.__type\"},{\"kind\":1024,\"name\":\"yearHigh\",\"url\":\"interfaces/IndexDetails.html#metadata.__type-2.yearHigh\",\"classes\":\"\",\"parent\":\"IndexDetails.metadata.__type\"},{\"kind\":1024,\"name\":\"yearLow\",\"url\":\"interfaces/IndexDetails.html#metadata.__type-2.yearLow\",\"classes\":\"\",\"parent\":\"IndexDetails.metadata.__type\"},{\"kind\":1024,\"name\":\"indicativeClose\",\"url\":\"interfaces/IndexDetails.html#metadata.__type-2.indicativeClose\",\"classes\":\"\",\"parent\":\"IndexDetails.metadata.__type\"},{\"kind\":1024,\"name\":\"perChange365d\",\"url\":\"interfaces/IndexDetails.html#metadata.__type-2.perChange365d\",\"classes\":\"\",\"parent\":\"IndexDetails.metadata.__type\"},{\"kind\":1024,\"name\":\"perChange30d\",\"url\":\"interfaces/IndexDetails.html#metadata.__type-2.perChange30d\",\"classes\":\"\",\"parent\":\"IndexDetails.metadata.__type\"},{\"kind\":1024,\"name\":\"date365dAgo\",\"url\":\"interfaces/IndexDetails.html#metadata.__type-2.date365dAgo-1\",\"classes\":\"\",\"parent\":\"IndexDetails.metadata.__type\"},{\"kind\":1024,\"name\":\"date30dAgo\",\"url\":\"interfaces/IndexDetails.html#metadata.__type-2.date30dAgo-1\",\"classes\":\"\",\"parent\":\"IndexDetails.metadata.__type\"},{\"kind\":1024,\"name\":\"chartTodayPath\",\"url\":\"interfaces/IndexDetails.html#metadata.__type-2.chartTodayPath\",\"classes\":\"\",\"parent\":\"IndexDetails.metadata.__type\"},{\"kind\":1024,\"name\":\"chart30dPath\",\"url\":\"interfaces/IndexDetails.html#metadata.__type-2.chart30dPath\",\"classes\":\"\",\"parent\":\"IndexDetails.metadata.__type\"},{\"kind\":1024,\"name\":\"chart365dPath\",\"url\":\"interfaces/IndexDetails.html#metadata.__type-2.chart365dPath\",\"classes\":\"\",\"parent\":\"IndexDetails.metadata.__type\"},{\"kind\":1024,\"name\":\"totalTradedVolume\",\"url\":\"interfaces/IndexDetails.html#metadata.__type-2.totalTradedVolume\",\"classes\":\"\",\"parent\":\"IndexDetails.metadata.__type\"},{\"kind\":1024,\"name\":\"totalTradedValue\",\"url\":\"interfaces/IndexDetails.html#metadata.__type-2.totalTradedValue\",\"classes\":\"\",\"parent\":\"IndexDetails.metadata.__type\"},{\"kind\":1024,\"name\":\"ffmc_sum\",\"url\":\"interfaces/IndexDetails.html#metadata.__type-2.ffmc_sum\",\"classes\":\"\",\"parent\":\"IndexDetails.metadata.__type\"},{\"kind\":1024,\"name\":\"marketStatus\",\"url\":\"interfaces/IndexDetails.html#marketStatus\",\"classes\":\"\",\"parent\":\"IndexDetails\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"interfaces/IndexDetails.html#marketStatus.__type-1\",\"classes\":\"\",\"parent\":\"IndexDetails.marketStatus\"},{\"kind\":1024,\"name\":\"market\",\"url\":\"interfaces/IndexDetails.html#marketStatus.__type-1.market\",\"classes\":\"\",\"parent\":\"IndexDetails.marketStatus.__type\"},{\"kind\":1024,\"name\":\"marketStatus\",\"url\":\"interfaces/IndexDetails.html#marketStatus.__type-1.marketStatus-1\",\"classes\":\"\",\"parent\":\"IndexDetails.marketStatus.__type\"},{\"kind\":1024,\"name\":\"tradeDate\",\"url\":\"interfaces/IndexDetails.html#marketStatus.__type-1.tradeDate\",\"classes\":\"\",\"parent\":\"IndexDetails.marketStatus.__type\"},{\"kind\":1024,\"name\":\"index\",\"url\":\"interfaces/IndexDetails.html#marketStatus.__type-1.index\",\"classes\":\"\",\"parent\":\"IndexDetails.marketStatus.__type\"},{\"kind\":1024,\"name\":\"last\",\"url\":\"interfaces/IndexDetails.html#marketStatus.__type-1.last\",\"classes\":\"\",\"parent\":\"IndexDetails.marketStatus.__type\"},{\"kind\":1024,\"name\":\"variation\",\"url\":\"interfaces/IndexDetails.html#marketStatus.__type-1.variation\",\"classes\":\"\",\"parent\":\"IndexDetails.marketStatus.__type\"},{\"kind\":1024,\"name\":\"percentChange\",\"url\":\"interfaces/IndexDetails.html#marketStatus.__type-1.percentChange\",\"classes\":\"\",\"parent\":\"IndexDetails.marketStatus.__type\"},{\"kind\":1024,\"name\":\"marketStatusMessage\",\"url\":\"interfaces/IndexDetails.html#marketStatus.__type-1.marketStatusMessage\",\"classes\":\"\",\"parent\":\"IndexDetails.marketStatus.__type\"},{\"kind\":1024,\"name\":\"date30dAgo\",\"url\":\"interfaces/IndexDetails.html#date30dAgo\",\"classes\":\"\",\"parent\":\"IndexDetails\"},{\"kind\":1024,\"name\":\"date365dAgo\",\"url\":\"interfaces/IndexDetails.html#date365dAgo\",\"classes\":\"\",\"parent\":\"IndexDetails\"},{\"kind\":256,\"name\":\"EquityOptionChainData\",\"url\":\"interfaces/EquityOptionChainData.html\",\"classes\":\"\"},{\"kind\":1024,\"name\":\"data\",\"url\":\"interfaces/EquityOptionChainData.html#data\",\"classes\":\"\",\"parent\":\"EquityOptionChainData\"},{\"kind\":1024,\"name\":\"timestamp\",\"url\":\"interfaces/EquityOptionChainData.html#timestamp\",\"classes\":\"\",\"parent\":\"EquityOptionChainData\"},{\"kind\":256,\"name\":\"IndexOptionChainData\",\"url\":\"interfaces/IndexOptionChainData.html\",\"classes\":\"\"},{\"kind\":1024,\"name\":\"records\",\"url\":\"interfaces/IndexOptionChainData.html#records\",\"classes\":\"\",\"parent\":\"IndexOptionChainData\"},{\"kind\":1024,\"name\":\"filtered\",\"url\":\"interfaces/IndexOptionChainData.html#filtered\",\"classes\":\"\",\"parent\":\"IndexOptionChainData\"},{\"kind\":256,\"name\":\"CommodityOptionChainData\",\"url\":\"interfaces/CommodityOptionChainData.html\",\"classes\":\"\"},{\"kind\":1024,\"name\":\"records\",\"url\":\"interfaces/CommodityOptionChainData.html#records\",\"classes\":\"\",\"parent\":\"CommodityOptionChainData\"},{\"kind\":1024,\"name\":\"filtered\",\"url\":\"interfaces/CommodityOptionChainData.html#filtered\",\"classes\":\"\",\"parent\":\"CommodityOptionChainData\"},{\"kind\":256,\"name\":\"OptionChainContractInfo\",\"url\":\"interfaces/OptionChainContractInfo.html\",\"classes\":\"\"},{\"kind\":1024,\"name\":\"expiryDates\",\"url\":\"interfaces/OptionChainContractInfo.html#expiryDates\",\"classes\":\"\",\"parent\":\"OptionChainContractInfo\"},{\"kind\":1024,\"name\":\"strikePrice\",\"url\":\"interfaces/OptionChainContractInfo.html#strikePrice\",\"classes\":\"\",\"parent\":\"OptionChainContractInfo\"},{\"kind\":256,\"name\":\"EquityCorporateInfo\",\"url\":\"interfaces/EquityCorporateInfo.html\",\"classes\":\"\"},{\"kind\":1024,\"name\":\"latest_announcements\",\"url\":\"interfaces/EquityCorporateInfo.html#latest_announcements\",\"classes\":\"\",\"parent\":\"EquityCorporateInfo\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"interfaces/EquityCorporateInfo.html#latest_announcements.__type-3\",\"classes\":\"\",\"parent\":\"EquityCorporateInfo.latest_announcements\"},{\"kind\":1024,\"name\":\"data\",\"url\":\"interfaces/EquityCorporateInfo.html#latest_announcements.__type-3.data-3\",\"classes\":\"\",\"parent\":\"EquityCorporateInfo.latest_announcements.__type\"},{\"kind\":1024,\"name\":\"corporate_actions\",\"url\":\"interfaces/EquityCorporateInfo.html#corporate_actions\",\"classes\":\"\",\"parent\":\"EquityCorporateInfo\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"interfaces/EquityCorporateInfo.html#corporate_actions.__type-1\",\"classes\":\"\",\"parent\":\"EquityCorporateInfo.corporate_actions\"},{\"kind\":1024,\"name\":\"data\",\"url\":\"interfaces/EquityCorporateInfo.html#corporate_actions.__type-1.data-1\",\"classes\":\"\",\"parent\":\"EquityCorporateInfo.corporate_actions.__type\"},{\"kind\":1024,\"name\":\"shareholdings_patterns\",\"url\":\"interfaces/EquityCorporateInfo.html#shareholdings_patterns\",\"classes\":\"\",\"parent\":\"EquityCorporateInfo\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"interfaces/EquityCorporateInfo.html#shareholdings_patterns.__type-4\",\"classes\":\"\",\"parent\":\"EquityCorporateInfo.shareholdings_patterns\"},{\"kind\":1024,\"name\":\"data\",\"url\":\"interfaces/EquityCorporateInfo.html#shareholdings_patterns.__type-4.data-4\",\"classes\":\"\",\"parent\":\"EquityCorporateInfo.shareholdings_patterns.__type\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"interfaces/EquityCorporateInfo.html#shareholdings_patterns.__type-4.data-4.__type-5\",\"classes\":\"\",\"parent\":\"EquityCorporateInfo.shareholdings_patterns.__type.data\"},{\"kind\":1024,\"name\":\"financial_results\",\"url\":\"interfaces/EquityCorporateInfo.html#financial_results\",\"classes\":\"\",\"parent\":\"EquityCorporateInfo\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"interfaces/EquityCorporateInfo.html#financial_results.__type-2\",\"classes\":\"\",\"parent\":\"EquityCorporateInfo.financial_results\"},{\"kind\":1024,\"name\":\"data\",\"url\":\"interfaces/EquityCorporateInfo.html#financial_results.__type-2.data-2\",\"classes\":\"\",\"parent\":\"EquityCorporateInfo.financial_results.__type\"},{\"kind\":1024,\"name\":\"borad_meeting\",\"url\":\"interfaces/EquityCorporateInfo.html#borad_meeting\",\"classes\":\"\",\"parent\":\"EquityCorporateInfo\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"interfaces/EquityCorporateInfo.html#borad_meeting.__type\",\"classes\":\"\",\"parent\":\"EquityCorporateInfo.borad_meeting\"},{\"kind\":1024,\"name\":\"data\",\"url\":\"interfaces/EquityCorporateInfo.html#borad_meeting.__type.data\",\"classes\":\"\",\"parent\":\"EquityCorporateInfo.borad_meeting.__type\"},{\"kind\":256,\"name\":\"Glossary\",\"url\":\"interfaces/Glossary.html\",\"classes\":\"\"},{\"kind\":1024,\"name\":\"content\",\"url\":\"interfaces/Glossary.html#content\",\"classes\":\"\",\"parent\":\"Glossary\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"interfaces/Glossary.html#content.__type\",\"classes\":\"\",\"parent\":\"Glossary.content\"},{\"kind\":1024,\"name\":\"title\",\"url\":\"interfaces/Glossary.html#content.__type.title\",\"classes\":\"\",\"parent\":\"Glossary.content.__type\"},{\"kind\":1024,\"name\":\"body\",\"url\":\"interfaces/Glossary.html#content.__type.body\",\"classes\":\"\",\"parent\":\"Glossary.content.__type\"},{\"kind\":1024,\"name\":\"field_glossary_items\",\"url\":\"interfaces/Glossary.html#content.__type.field_glossary_items\",\"classes\":\"\",\"parent\":\"Glossary.content.__type\"},{\"kind\":1024,\"name\":\"field_labels\",\"url\":\"interfaces/Glossary.html#content.__type.field_labels\",\"classes\":\"\",\"parent\":\"Glossary.content.__type\"},{\"kind\":1024,\"name\":\"field_reference\",\"url\":\"interfaces/Glossary.html#content.__type.field_reference\",\"classes\":\"\",\"parent\":\"Glossary.content.__type\"},{\"kind\":1024,\"name\":\"field_unique_url\",\"url\":\"interfaces/Glossary.html#content.__type.field_unique_url\",\"classes\":\"\",\"parent\":\"Glossary.content.__type\"},{\"kind\":1024,\"name\":\"id\",\"url\":\"interfaces/Glossary.html#id\",\"classes\":\"\",\"parent\":\"Glossary\"},{\"kind\":1024,\"name\":\"type\",\"url\":\"interfaces/Glossary.html#type\",\"classes\":\"\",\"parent\":\"Glossary\"},{\"kind\":1024,\"name\":\"changed\",\"url\":\"interfaces/Glossary.html#changed\",\"classes\":\"\",\"parent\":\"Glossary\"},{\"kind\":256,\"name\":\"HolidaysBySegment\",\"url\":\"interfaces/HolidaysBySegment.html\",\"classes\":\"\"},{\"kind\":256,\"name\":\"MarketStatus\",\"url\":\"interfaces/MarketStatus.html\",\"classes\":\"\"},{\"kind\":1024,\"name\":\"marketState\",\"url\":\"interfaces/MarketStatus.html#marketState\",\"classes\":\"\",\"parent\":\"MarketStatus\"},{\"kind\":1024,\"name\":\"marketcap\",\"url\":\"interfaces/MarketStatus.html#marketcap\",\"classes\":\"\",\"parent\":\"MarketStatus\"},{\"kind\":1024,\"name\":\"indicativenifty50\",\"url\":\"interfaces/MarketStatus.html#indicativenifty50\",\"classes\":\"\",\"parent\":\"MarketStatus\"},{\"kind\":1024,\"name\":\"giftnifty\",\"url\":\"interfaces/MarketStatus.html#giftnifty\",\"classes\":\"\",\"parent\":\"MarketStatus\"},{\"kind\":256,\"name\":\"MarketTurnover\",\"url\":\"interfaces/MarketTurnover.html\",\"classes\":\"\"},{\"kind\":1024,\"name\":\"totalTradedValue\",\"url\":\"interfaces/MarketTurnover.html#totalTradedValue\",\"classes\":\"\",\"parent\":\"MarketTurnover\"},{\"kind\":1024,\"name\":\"totalTradedVolume\",\"url\":\"interfaces/MarketTurnover.html#totalTradedVolume\",\"classes\":\"\",\"parent\":\"MarketTurnover\"},{\"kind\":1024,\"name\":\"totalTrades\",\"url\":\"interfaces/MarketTurnover.html#totalTrades\",\"classes\":\"\",\"parent\":\"MarketTurnover\"},{\"kind\":1024,\"name\":\"lastUpdateTime\",\"url\":\"interfaces/MarketTurnover.html#lastUpdateTime\",\"classes\":\"\",\"parent\":\"MarketTurnover\"},{\"kind\":256,\"name\":\"AllIndicesData\",\"url\":\"interfaces/AllIndicesData.html\",\"classes\":\"\"},{\"kind\":1024,\"name\":\"data\",\"url\":\"interfaces/AllIndicesData.html#data\",\"classes\":\"\",\"parent\":\"AllIndicesData\"},{\"kind\":256,\"name\":\"IndexNamesData\",\"url\":\"interfaces/IndexNamesData.html\",\"classes\":\"\"},{\"kind\":1024,\"name\":\"stn\",\"url\":\"interfaces/IndexNamesData.html#stn\",\"classes\":\"\",\"parent\":\"IndexNamesData\"},{\"kind\":1024,\"name\":\"nts\",\"url\":\"interfaces/IndexNamesData.html#nts\",\"classes\":\"\",\"parent\":\"IndexNamesData\"},{\"kind\":256,\"name\":\"CircularsData\",\"url\":\"interfaces/CircularsData.html\",\"classes\":\"\"},{\"kind\":1024,\"name\":\"data\",\"url\":\"interfaces/CircularsData.html#data\",\"classes\":\"\",\"parent\":\"CircularsData\"},{\"kind\":1024,\"name\":\"fromDate\",\"url\":\"interfaces/CircularsData.html#fromDate\",\"classes\":\"\",\"parent\":\"CircularsData\"},{\"kind\":1024,\"name\":\"toDate\",\"url\":\"interfaces/CircularsData.html#toDate\",\"classes\":\"\",\"parent\":\"CircularsData\"},{\"kind\":256,\"name\":\"LatestCircularData\",\"url\":\"interfaces/LatestCircularData.html\",\"classes\":\"\"},{\"kind\":1024,\"name\":\"data\",\"url\":\"interfaces/LatestCircularData.html#data\",\"classes\":\"\",\"parent\":\"LatestCircularData\"},{\"kind\":256,\"name\":\"EquityMaster\",\"url\":\"interfaces/EquityMaster.html\",\"classes\":\"\"},{\"kind\":256,\"name\":\"PreOpenMarketData\",\"url\":\"interfaces/PreOpenMarketData.html\",\"classes\":\"\"},{\"kind\":1024,\"name\":\"data\",\"url\":\"interfaces/PreOpenMarketData.html#data\",\"classes\":\"\",\"parent\":\"PreOpenMarketData\"},{\"kind\":1024,\"name\":\"timestamp\",\"url\":\"interfaces/PreOpenMarketData.html#timestamp\",\"classes\":\"\",\"parent\":\"PreOpenMarketData\"},{\"kind\":1024,\"name\":\"advances\",\"url\":\"interfaces/PreOpenMarketData.html#advances\",\"classes\":\"\",\"parent\":\"PreOpenMarketData\"},{\"kind\":1024,\"name\":\"declines\",\"url\":\"interfaces/PreOpenMarketData.html#declines\",\"classes\":\"\",\"parent\":\"PreOpenMarketData\"},{\"kind\":1024,\"name\":\"unchanged\",\"url\":\"interfaces/PreOpenMarketData.html#unchanged\",\"classes\":\"\",\"parent\":\"PreOpenMarketData\"},{\"kind\":1024,\"name\":\"totalTradedValue\",\"url\":\"interfaces/PreOpenMarketData.html#totalTradedValue\",\"classes\":\"\",\"parent\":\"PreOpenMarketData\"},{\"kind\":1024,\"name\":\"totalmarketcap\",\"url\":\"interfaces/PreOpenMarketData.html#totalmarketcap\",\"classes\":\"\",\"parent\":\"PreOpenMarketData\"},{\"kind\":1024,\"name\":\"totalTradedVolume\",\"url\":\"interfaces/PreOpenMarketData.html#totalTradedVolume\",\"classes\":\"\",\"parent\":\"PreOpenMarketData\"},{\"kind\":256,\"name\":\"MergedDailyReportsData\",\"url\":\"interfaces/MergedDailyReportsData.html\",\"classes\":\"\"},{\"kind\":1024,\"name\":\"name\",\"url\":\"interfaces/MergedDailyReportsData.html#name\",\"classes\":\"\",\"parent\":\"MergedDailyReportsData\"},{\"kind\":1024,\"name\":\"type\",\"url\":\"interfaces/MergedDailyReportsData.html#type\",\"classes\":\"\",\"parent\":\"MergedDailyReportsData\"},{\"kind\":1024,\"name\":\"category\",\"url\":\"interfaces/MergedDailyReportsData.html#category\",\"classes\":\"\",\"parent\":\"MergedDailyReportsData\"},{\"kind\":1024,\"name\":\"section\",\"url\":\"interfaces/MergedDailyReportsData.html#section\",\"classes\":\"\",\"parent\":\"MergedDailyReportsData\"},{\"kind\":1024,\"name\":\"link\",\"url\":\"interfaces/MergedDailyReportsData.html#link\",\"classes\":\"\",\"parent\":\"MergedDailyReportsData\"},{\"kind\":256,\"name\":\"TechnicalIndicators\",\"url\":\"interfaces/TechnicalIndicators.html\",\"classes\":\"\"},{\"kind\":1024,\"name\":\"sma\",\"url\":\"interfaces/TechnicalIndicators.html#sma\",\"classes\":\"\",\"parent\":\"TechnicalIndicators\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"interfaces/TechnicalIndicators.html#sma.__type-3\",\"classes\":\"\",\"parent\":\"TechnicalIndicators.sma\"},{\"kind\":1024,\"name\":\"ema\",\"url\":\"interfaces/TechnicalIndicators.html#ema\",\"classes\":\"\",\"parent\":\"TechnicalIndicators\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"interfaces/TechnicalIndicators.html#ema.__type-1\",\"classes\":\"\",\"parent\":\"TechnicalIndicators.ema\"},{\"kind\":1024,\"name\":\"rsi\",\"url\":\"interfaces/TechnicalIndicators.html#rsi\",\"classes\":\"\",\"parent\":\"TechnicalIndicators\"},{\"kind\":1024,\"name\":\"macd\",\"url\":\"interfaces/TechnicalIndicators.html#macd\",\"classes\":\"\",\"parent\":\"TechnicalIndicators\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"interfaces/TechnicalIndicators.html#macd.__type-2\",\"classes\":\"\",\"parent\":\"TechnicalIndicators.macd\"},{\"kind\":1024,\"name\":\"macd\",\"url\":\"interfaces/TechnicalIndicators.html#macd.__type-2.macd-1\",\"classes\":\"\",\"parent\":\"TechnicalIndicators.macd.__type\"},{\"kind\":1024,\"name\":\"signal\",\"url\":\"interfaces/TechnicalIndicators.html#macd.__type-2.signal\",\"classes\":\"\",\"parent\":\"TechnicalIndicators.macd.__type\"},{\"kind\":1024,\"name\":\"histogram\",\"url\":\"interfaces/TechnicalIndicators.html#macd.__type-2.histogram\",\"classes\":\"\",\"parent\":\"TechnicalIndicators.macd.__type\"},{\"kind\":1024,\"name\":\"bollingerBands\",\"url\":\"interfaces/TechnicalIndicators.html#bollingerBands\",\"classes\":\"\",\"parent\":\"TechnicalIndicators\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"interfaces/TechnicalIndicators.html#bollingerBands.__type\",\"classes\":\"\",\"parent\":\"TechnicalIndicators.bollingerBands\"},{\"kind\":1024,\"name\":\"upper\",\"url\":\"interfaces/TechnicalIndicators.html#bollingerBands.__type.upper\",\"classes\":\"\",\"parent\":\"TechnicalIndicators.bollingerBands.__type\"},{\"kind\":1024,\"name\":\"middle\",\"url\":\"interfaces/TechnicalIndicators.html#bollingerBands.__type.middle\",\"classes\":\"\",\"parent\":\"TechnicalIndicators.bollingerBands.__type\"},{\"kind\":1024,\"name\":\"lower\",\"url\":\"interfaces/TechnicalIndicators.html#bollingerBands.__type.lower\",\"classes\":\"\",\"parent\":\"TechnicalIndicators.bollingerBands.__type\"},{\"kind\":1024,\"name\":\"stochastic\",\"url\":\"interfaces/TechnicalIndicators.html#stochastic\",\"classes\":\"\",\"parent\":\"TechnicalIndicators\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"interfaces/TechnicalIndicators.html#stochastic.__type-4\",\"classes\":\"\",\"parent\":\"TechnicalIndicators.stochastic\"},{\"kind\":1024,\"name\":\"k\",\"url\":\"interfaces/TechnicalIndicators.html#stochastic.__type-4.k\",\"classes\":\"\",\"parent\":\"TechnicalIndicators.stochastic.__type\"},{\"kind\":1024,\"name\":\"d\",\"url\":\"interfaces/TechnicalIndicators.html#stochastic.__type-4.d\",\"classes\":\"\",\"parent\":\"TechnicalIndicators.stochastic.__type\"},{\"kind\":1024,\"name\":\"williamsR\",\"url\":\"interfaces/TechnicalIndicators.html#williamsR\",\"classes\":\"\",\"parent\":\"TechnicalIndicators\"},{\"kind\":1024,\"name\":\"atr\",\"url\":\"interfaces/TechnicalIndicators.html#atr\",\"classes\":\"\",\"parent\":\"TechnicalIndicators\"},{\"kind\":1024,\"name\":\"adx\",\"url\":\"interfaces/TechnicalIndicators.html#adx\",\"classes\":\"\",\"parent\":\"TechnicalIndicators\"},{\"kind\":1024,\"name\":\"obv\",\"url\":\"interfaces/TechnicalIndicators.html#obv\",\"classes\":\"\",\"parent\":\"TechnicalIndicators\"},{\"kind\":1024,\"name\":\"cci\",\"url\":\"interfaces/TechnicalIndicators.html#cci\",\"classes\":\"\",\"parent\":\"TechnicalIndicators\"},{\"kind\":1024,\"name\":\"mfi\",\"url\":\"interfaces/TechnicalIndicators.html#mfi\",\"classes\":\"\",\"parent\":\"TechnicalIndicators\"},{\"kind\":1024,\"name\":\"roc\",\"url\":\"interfaces/TechnicalIndicators.html#roc\",\"classes\":\"\",\"parent\":\"TechnicalIndicators\"},{\"kind\":1024,\"name\":\"momentum\",\"url\":\"interfaces/TechnicalIndicators.html#momentum\",\"classes\":\"\",\"parent\":\"TechnicalIndicators\"},{\"kind\":1024,\"name\":\"ad\",\"url\":\"interfaces/TechnicalIndicators.html#ad\",\"classes\":\"\",\"parent\":\"TechnicalIndicators\"},{\"kind\":1024,\"name\":\"vwap\",\"url\":\"interfaces/TechnicalIndicators.html#vwap\",\"classes\":\"\",\"parent\":\"TechnicalIndicators\"},{\"kind\":256,\"name\":\"EquityInfo\",\"url\":\"interfaces/EquityInfo.html\",\"classes\":\"\"},{\"kind\":1024,\"name\":\"symbol\",\"url\":\"interfaces/EquityInfo.html#symbol\",\"classes\":\"\",\"parent\":\"EquityInfo\"},{\"kind\":1024,\"name\":\"companyName\",\"url\":\"interfaces/EquityInfo.html#companyName\",\"classes\":\"\",\"parent\":\"EquityInfo\"},{\"kind\":1024,\"name\":\"industry\",\"url\":\"interfaces/EquityInfo.html#industry\",\"classes\":\"\",\"parent\":\"EquityInfo\"},{\"kind\":1024,\"name\":\"activeSeries\",\"url\":\"interfaces/EquityInfo.html#activeSeries\",\"classes\":\"\",\"parent\":\"EquityInfo\"},{\"kind\":1024,\"name\":\"debtSeries\",\"url\":\"interfaces/EquityInfo.html#debtSeries\",\"classes\":\"\",\"parent\":\"EquityInfo\"},{\"kind\":1024,\"name\":\"tempSuspendedSeries\",\"url\":\"interfaces/EquityInfo.html#tempSuspendedSeries\",\"classes\":\"\",\"parent\":\"EquityInfo\"},{\"kind\":1024,\"name\":\"isFNOSec\",\"url\":\"interfaces/EquityInfo.html#isFNOSec\",\"classes\":\"\",\"parent\":\"EquityInfo\"},{\"kind\":1024,\"name\":\"isCASec\",\"url\":\"interfaces/EquityInfo.html#isCASec\",\"classes\":\"\",\"parent\":\"EquityInfo\"},{\"kind\":1024,\"name\":\"isSLBSec\",\"url\":\"interfaces/EquityInfo.html#isSLBSec\",\"classes\":\"\",\"parent\":\"EquityInfo\"},{\"kind\":1024,\"name\":\"isDebtSec\",\"url\":\"interfaces/EquityInfo.html#isDebtSec\",\"classes\":\"\",\"parent\":\"EquityInfo\"},{\"kind\":1024,\"name\":\"isSuspended\",\"url\":\"interfaces/EquityInfo.html#isSuspended\",\"classes\":\"\",\"parent\":\"EquityInfo\"},{\"kind\":1024,\"name\":\"isETFSec\",\"url\":\"interfaces/EquityInfo.html#isETFSec\",\"classes\":\"\",\"parent\":\"EquityInfo\"},{\"kind\":1024,\"name\":\"isDelisted\",\"url\":\"interfaces/EquityInfo.html#isDelisted\",\"classes\":\"\",\"parent\":\"EquityInfo\"},{\"kind\":1024,\"name\":\"isin\",\"url\":\"interfaces/EquityInfo.html#isin\",\"classes\":\"\",\"parent\":\"EquityInfo\"},{\"kind\":1024,\"name\":\"slb_isin\",\"url\":\"interfaces/EquityInfo.html#slb_isin\",\"classes\":\"\",\"parent\":\"EquityInfo\"},{\"kind\":1024,\"name\":\"listingDate\",\"url\":\"interfaces/EquityInfo.html#listingDate\",\"classes\":\"\",\"parent\":\"EquityInfo\"},{\"kind\":1024,\"name\":\"isMunicipalBond\",\"url\":\"interfaces/EquityInfo.html#isMunicipalBond\",\"classes\":\"\",\"parent\":\"EquityInfo\"},{\"kind\":1024,\"name\":\"isHybridSymbol\",\"url\":\"interfaces/EquityInfo.html#isHybridSymbol\",\"classes\":\"\",\"parent\":\"EquityInfo\"},{\"kind\":1024,\"name\":\"segment\",\"url\":\"interfaces/EquityInfo.html#segment\",\"classes\":\"\",\"parent\":\"EquityInfo\"},{\"kind\":1024,\"name\":\"isTop10\",\"url\":\"interfaces/EquityInfo.html#isTop10\",\"classes\":\"\",\"parent\":\"EquityInfo\"},{\"kind\":1024,\"name\":\"identifier\",\"url\":\"interfaces/EquityInfo.html#identifier\",\"classes\":\"\",\"parent\":\"EquityInfo\"},{\"kind\":256,\"name\":\"EquityMetadata\",\"url\":\"interfaces/EquityMetadata.html\",\"classes\":\"\"},{\"kind\":1024,\"name\":\"series\",\"url\":\"interfaces/EquityMetadata.html#series\",\"classes\":\"\",\"parent\":\"EquityMetadata\"},{\"kind\":1024,\"name\":\"symbol\",\"url\":\"interfaces/EquityMetadata.html#symbol\",\"classes\":\"\",\"parent\":\"EquityMetadata\"},{\"kind\":1024,\"name\":\"isin\",\"url\":\"interfaces/EquityMetadata.html#isin\",\"classes\":\"\",\"parent\":\"EquityMetadata\"},{\"kind\":1024,\"name\":\"status\",\"url\":\"interfaces/EquityMetadata.html#status\",\"classes\":\"\",\"parent\":\"EquityMetadata\"},{\"kind\":1024,\"name\":\"listingDate\",\"url\":\"interfaces/EquityMetadata.html#listingDate\",\"classes\":\"\",\"parent\":\"EquityMetadata\"},{\"kind\":1024,\"name\":\"industry\",\"url\":\"interfaces/EquityMetadata.html#industry\",\"classes\":\"\",\"parent\":\"EquityMetadata\"},{\"kind\":1024,\"name\":\"lastUpdateTime\",\"url\":\"interfaces/EquityMetadata.html#lastUpdateTime\",\"classes\":\"\",\"parent\":\"EquityMetadata\"},{\"kind\":1024,\"name\":\"pdSectorPe\",\"url\":\"interfaces/EquityMetadata.html#pdSectorPe\",\"classes\":\"\",\"parent\":\"EquityMetadata\"},{\"kind\":1024,\"name\":\"pdSymbolPe\",\"url\":\"interfaces/EquityMetadata.html#pdSymbolPe\",\"classes\":\"\",\"parent\":\"EquityMetadata\"},{\"kind\":1024,\"name\":\"pdSectorInd\",\"url\":\"interfaces/EquityMetadata.html#pdSectorInd\",\"classes\":\"\",\"parent\":\"EquityMetadata\"},{\"kind\":1024,\"name\":\"pdSectorIndAll\",\"url\":\"interfaces/EquityMetadata.html#pdSectorIndAll\",\"classes\":\"\",\"parent\":\"EquityMetadata\"},{\"kind\":256,\"name\":\"EquitySecurityInfo\",\"url\":\"interfaces/EquitySecurityInfo.html\",\"classes\":\"\"},{\"kind\":1024,\"name\":\"boardStatus\",\"url\":\"interfaces/EquitySecurityInfo.html#boardStatus\",\"classes\":\"\",\"parent\":\"EquitySecurityInfo\"},{\"kind\":1024,\"name\":\"tradingStatus\",\"url\":\"interfaces/EquitySecurityInfo.html#tradingStatus\",\"classes\":\"\",\"parent\":\"EquitySecurityInfo\"},{\"kind\":1024,\"name\":\"tradingSegment\",\"url\":\"interfaces/EquitySecurityInfo.html#tradingSegment\",\"classes\":\"\",\"parent\":\"EquitySecurityInfo\"},{\"kind\":1024,\"name\":\"sessionNo\",\"url\":\"interfaces/EquitySecurityInfo.html#sessionNo\",\"classes\":\"\",\"parent\":\"EquitySecurityInfo\"},{\"kind\":1024,\"name\":\"slb\",\"url\":\"interfaces/EquitySecurityInfo.html#slb\",\"classes\":\"\",\"parent\":\"EquitySecurityInfo\"},{\"kind\":1024,\"name\":\"classOfShare\",\"url\":\"interfaces/EquitySecurityInfo.html#classOfShare\",\"classes\":\"\",\"parent\":\"EquitySecurityInfo\"},{\"kind\":1024,\"name\":\"derivatives\",\"url\":\"interfaces/EquitySecurityInfo.html#derivatives\",\"classes\":\"\",\"parent\":\"EquitySecurityInfo\"},{\"kind\":1024,\"name\":\"surveillance\",\"url\":\"interfaces/EquitySecurityInfo.html#surveillance\",\"classes\":\"\",\"parent\":\"EquitySecurityInfo\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"interfaces/EquitySecurityInfo.html#surveillance.__type\",\"classes\":\"\",\"parent\":\"EquitySecurityInfo.surveillance\"},{\"kind\":1024,\"name\":\"surv\",\"url\":\"interfaces/EquitySecurityInfo.html#surveillance.__type.surv\",\"classes\":\"\",\"parent\":\"EquitySecurityInfo.surveillance.__type\"},{\"kind\":1024,\"name\":\"desc\",\"url\":\"interfaces/EquitySecurityInfo.html#surveillance.__type.desc\",\"classes\":\"\",\"parent\":\"EquitySecurityInfo.surveillance.__type\"},{\"kind\":1024,\"name\":\"faceValue\",\"url\":\"interfaces/EquitySecurityInfo.html#faceValue\",\"classes\":\"\",\"parent\":\"EquitySecurityInfo\"},{\"kind\":1024,\"name\":\"issuedSize\",\"url\":\"interfaces/EquitySecurityInfo.html#issuedSize\",\"classes\":\"\",\"parent\":\"EquitySecurityInfo\"},{\"kind\":256,\"name\":\"EquityPriceInfo\",\"url\":\"interfaces/EquityPriceInfo.html\",\"classes\":\"\"},{\"kind\":1024,\"name\":\"lastPrice\",\"url\":\"interfaces/EquityPriceInfo.html#lastPrice\",\"classes\":\"\",\"parent\":\"EquityPriceInfo\"},{\"kind\":1024,\"name\":\"change\",\"url\":\"interfaces/EquityPriceInfo.html#change\",\"classes\":\"\",\"parent\":\"EquityPriceInfo\"},{\"kind\":1024,\"name\":\"pChange\",\"url\":\"interfaces/EquityPriceInfo.html#pChange\",\"classes\":\"\",\"parent\":\"EquityPriceInfo\"},{\"kind\":1024,\"name\":\"previousClose\",\"url\":\"interfaces/EquityPriceInfo.html#previousClose\",\"classes\":\"\",\"parent\":\"EquityPriceInfo\"},{\"kind\":1024,\"name\":\"open\",\"url\":\"interfaces/EquityPriceInfo.html#open\",\"classes\":\"\",\"parent\":\"EquityPriceInfo\"},{\"kind\":1024,\"name\":\"close\",\"url\":\"interfaces/EquityPriceInfo.html#close\",\"classes\":\"\",\"parent\":\"EquityPriceInfo\"},{\"kind\":1024,\"name\":\"vwap\",\"url\":\"interfaces/EquityPriceInfo.html#vwap\",\"classes\":\"\",\"parent\":\"EquityPriceInfo\"},{\"kind\":1024,\"name\":\"stockIndClosePrice\",\"url\":\"interfaces/EquityPriceInfo.html#stockIndClosePrice\",\"classes\":\"\",\"parent\":\"EquityPriceInfo\"},{\"kind\":1024,\"name\":\"lowerCP\",\"url\":\"interfaces/EquityPriceInfo.html#lowerCP\",\"classes\":\"\",\"parent\":\"EquityPriceInfo\"},{\"kind\":1024,\"name\":\"upperCP\",\"url\":\"interfaces/EquityPriceInfo.html#upperCP\",\"classes\":\"\",\"parent\":\"EquityPriceInfo\"},{\"kind\":1024,\"name\":\"pPriceBand\",\"url\":\"interfaces/EquityPriceInfo.html#pPriceBand\",\"classes\":\"\",\"parent\":\"EquityPriceInfo\"},{\"kind\":1024,\"name\":\"basePrice\",\"url\":\"interfaces/EquityPriceInfo.html#basePrice\",\"classes\":\"\",\"parent\":\"EquityPriceInfo\"},{\"kind\":1024,\"name\":\"intraDayHighLow\",\"url\":\"interfaces/EquityPriceInfo.html#intraDayHighLow\",\"classes\":\"\",\"parent\":\"EquityPriceInfo\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"interfaces/EquityPriceInfo.html#intraDayHighLow.__type\",\"classes\":\"\",\"parent\":\"EquityPriceInfo.intraDayHighLow\"},{\"kind\":1024,\"name\":\"min\",\"url\":\"interfaces/EquityPriceInfo.html#intraDayHighLow.__type.min\",\"classes\":\"\",\"parent\":\"EquityPriceInfo.intraDayHighLow.__type\"},{\"kind\":1024,\"name\":\"max\",\"url\":\"interfaces/EquityPriceInfo.html#intraDayHighLow.__type.max\",\"classes\":\"\",\"parent\":\"EquityPriceInfo.intraDayHighLow.__type\"},{\"kind\":1024,\"name\":\"value\",\"url\":\"interfaces/EquityPriceInfo.html#intraDayHighLow.__type.value\",\"classes\":\"\",\"parent\":\"EquityPriceInfo.intraDayHighLow.__type\"},{\"kind\":1024,\"name\":\"weekHighLow\",\"url\":\"interfaces/EquityPriceInfo.html#weekHighLow\",\"classes\":\"\",\"parent\":\"EquityPriceInfo\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"interfaces/EquityPriceInfo.html#weekHighLow.__type-1\",\"classes\":\"\",\"parent\":\"EquityPriceInfo.weekHighLow\"},{\"kind\":1024,\"name\":\"min\",\"url\":\"interfaces/EquityPriceInfo.html#weekHighLow.__type-1.min-1\",\"classes\":\"\",\"parent\":\"EquityPriceInfo.weekHighLow.__type\"},{\"kind\":1024,\"name\":\"minDate\",\"url\":\"interfaces/EquityPriceInfo.html#weekHighLow.__type-1.minDate\",\"classes\":\"\",\"parent\":\"EquityPriceInfo.weekHighLow.__type\"},{\"kind\":1024,\"name\":\"max\",\"url\":\"interfaces/EquityPriceInfo.html#weekHighLow.__type-1.max-1\",\"classes\":\"\",\"parent\":\"EquityPriceInfo.weekHighLow.__type\"},{\"kind\":1024,\"name\":\"maxDate\",\"url\":\"interfaces/EquityPriceInfo.html#weekHighLow.__type-1.maxDate\",\"classes\":\"\",\"parent\":\"EquityPriceInfo.weekHighLow.__type\"},{\"kind\":1024,\"name\":\"value\",\"url\":\"interfaces/EquityPriceInfo.html#weekHighLow.__type-1.value-1\",\"classes\":\"\",\"parent\":\"EquityPriceInfo.weekHighLow.__type\"},{\"kind\":1024,\"name\":\"iNavValue\",\"url\":\"interfaces/EquityPriceInfo.html#iNavValue\",\"classes\":\"\",\"parent\":\"EquityPriceInfo\"},{\"kind\":1024,\"name\":\"checkINAV\",\"url\":\"interfaces/EquityPriceInfo.html#checkINAV\",\"classes\":\"\",\"parent\":\"EquityPriceInfo\"},{\"kind\":1024,\"name\":\"tickSize\",\"url\":\"interfaces/EquityPriceInfo.html#tickSize\",\"classes\":\"\",\"parent\":\"EquityPriceInfo\"},{\"kind\":1024,\"name\":\"ieq\",\"url\":\"interfaces/EquityPriceInfo.html#ieq\",\"classes\":\"\",\"parent\":\"EquityPriceInfo\"},{\"kind\":256,\"name\":\"EquityPreOpenMarket\",\"url\":\"interfaces/EquityPreOpenMarket.html\",\"classes\":\"\"},{\"kind\":1024,\"name\":\"preopen\",\"url\":\"interfaces/EquityPreOpenMarket.html#preopen\",\"classes\":\"\",\"parent\":\"EquityPreOpenMarket\"},{\"kind\":1024,\"name\":\"ato\",\"url\":\"interfaces/EquityPreOpenMarket.html#ato\",\"classes\":\"\",\"parent\":\"EquityPreOpenMarket\"},{\"kind\":65536,\"name\":\"__type\",\"url\":\"interfaces/EquityPreOpenMarket.html#ato.__type\",\"classes\":\"\",\"parent\":\"EquityPreOpenMarket.ato\"},{\"kind\":1024,\"name\":\"buy\",\"url\":\"interfaces/EquityPreOpenMarket.html#ato.__type.buy\",\"classes\":\"\",\"parent\":\"EquityPreOpenMarket.ato.__type\"},{\"kind\":1024,\"name\":\"sell\",\"url\":\"interfaces/EquityPreOpenMarket.html#ato.__type.sell\",\"classes\":\"\",\"parent\":\"EquityPreOpenMarket.ato.__type\"},{\"kind\":1024,\"name\":\"IEP\",\"url\":\"interfaces/EquityPreOpenMarket.html#IEP\",\"classes\":\"\",\"parent\":\"EquityPreOpenMarket\"},{\"kind\":1024,\"name\":\"totalTradedVolume\",\"url\":\"interfaces/EquityPreOpenMarket.html#totalTradedVolume\",\"classes\":\"\",\"parent\":\"EquityPreOpenMarket\"},{\"kind\":1024,\"name\":\"finalPrice\",\"url\":\"interfaces/EquityPreOpenMarket.html#finalPrice\",\"classes\":\"\",\"parent\":\"EquityPreOpenMarket\"},{\"kind\":1024,\"name\":\"finalQuantity\",\"url\":\"interfaces/EquityPreOpenMarket.html#finalQuantity\",\"classes\":\"\",\"parent\":\"EquityPreOpenMarket\"},{\"kind\":1024,\"name\":\"lastUpdateTime\",\"url\":\"interfaces/EquityPreOpenMarket.html#lastUpdateTime\",\"classes\":\"\",\"parent\":\"EquityPreOpenMarket\"},{\"kind\":1024,\"name\":\"totalBuyQuantity\",\"url\":\"interfaces/EquityPreOpenMarket.html#totalBuyQuantity\",\"classes\":\"\",\"parent\":\"EquityPreOpenMarket\"},{\"kind\":1024,\"name\":\"totalSellQuantity\",\"url\":\"interfaces/EquityPreOpenMarket.html#totalSellQuantity\",\"classes\":\"\",\"parent\":\"EquityPreOpenMarket\"},{\"kind\":1024,\"name\":\"atoBuyQty\",\"url\":\"interfaces/EquityPreOpenMarket.html#atoBuyQty\",\"classes\":\"\",\"parent\":\"EquityPreOpenMarket\"},{\"kind\":1024,\"name\":\"atoSellQty\",\"url\":\"interfaces/EquityPreOpenMarket.html#atoSellQty\",\"classes\":\"\",\"parent\":\"EquityPreOpenMarket\"},{\"kind\":256,\"name\":\"EquityHistoricalInfo\",\"url\":\"interfaces/EquityHistoricalInfo.html\",\"classes\":\"\"},{\"kind\":1024,\"name\":\"chSymbol\",\"url\":\"interfaces/EquityHistoricalInfo.html#chSymbol\",\"classes\":\"\",\"parent\":\"EquityHistoricalInfo\"},{\"kind\":1024,\"name\":\"chSeries\",\"url\":\"interfaces/EquityHistoricalInfo.html#chSeries\",\"classes\":\"\",\"parent\":\"EquityHistoricalInfo\"},{\"kind\":1024,\"name\":\"chPreviousClsPrice\",\"url\":\"interfaces/EquityHistoricalInfo.html#chPreviousClsPrice\",\"classes\":\"\",\"parent\":\"EquityHistoricalInfo\"},{\"kind\":1024,\"name\":\"chOpeningPrice\",\"url\":\"interfaces/EquityHistoricalInfo.html#chOpeningPrice\",\"classes\":\"\",\"parent\":\"EquityHistoricalInfo\"},{\"kind\":1024,\"name\":\"chTradeHighPrice\",\"url\":\"interfaces/EquityHistoricalInfo.html#chTradeHighPrice\",\"classes\":\"\",\"parent\":\"EquityHistoricalInfo\"},{\"kind\":1024,\"name\":\"chTradeLowPrice\",\"url\":\"interfaces/EquityHistoricalInfo.html#chTradeLowPrice\",\"classes\":\"\",\"parent\":\"EquityHistoricalInfo\"},{\"kind\":1024,\"name\":\"chLastTradedPrice\",\"url\":\"interfaces/EquityHistoricalInfo.html#chLastTradedPrice\",\"classes\":\"\",\"parent\":\"EquityHistoricalInfo\"},{\"kind\":1024,\"name\":\"chClosingPrice\",\"url\":\"interfaces/EquityHistoricalInfo.html#chClosingPrice\",\"classes\":\"\",\"parent\":\"EquityHistoricalInfo\"},{\"kind\":1024,\"name\":\"vwap\",\"url\":\"interfaces/EquityHistoricalInfo.html#vwap\",\"classes\":\"\",\"parent\":\"EquityHistoricalInfo\"},{\"kind\":1024,\"name\":\"chTotTradedQty\",\"url\":\"interfaces/EquityHistoricalInfo.html#chTotTradedQty\",\"classes\":\"\",\"parent\":\"EquityHistoricalInfo\"},{\"kind\":1024,\"name\":\"chTotTradedVal\",\"url\":\"interfaces/EquityHistoricalInfo.html#chTotTradedVal\",\"classes\":\"\",\"parent\":\"EquityHistoricalInfo\"},{\"kind\":1024,\"name\":\"chTotalTrades\",\"url\":\"interfaces/EquityHistoricalInfo.html#chTotalTrades\",\"classes\":\"\",\"parent\":\"EquityHistoricalInfo\"},{\"kind\":1024,\"name\":\"ch52WeekHighPrice\",\"url\":\"interfaces/EquityHistoricalInfo.html#ch52WeekHighPrice\",\"classes\":\"\",\"parent\":\"EquityHistoricalInfo\"},{\"kind\":1024,\"name\":\"ch52WeekLowPrice\",\"url\":\"interfaces/EquityHistoricalInfo.html#ch52WeekLowPrice\",\"classes\":\"\",\"parent\":\"EquityHistoricalInfo\"},{\"kind\":1024,\"name\":\"mtimestamp\",\"url\":\"interfaces/EquityHistoricalInfo.html#mtimestamp\",\"classes\":\"\",\"parent\":\"EquityHistoricalInfo\"},{\"kind\":256,\"name\":\"EquityOptionChainItem\",\"url\":\"interfaces/EquityOptionChainItem.html\",\"classes\":\"\"},{\"kind\":1024,\"name\":\"identifier\",\"url\":\"interfaces/EquityOptionChainItem.html#identifier\",\"classes\":\"\",\"parent\":\"EquityOptionChainItem\"},{\"kind\":1024,\"name\":\"instrumentType\",\"url\":\"interfaces/EquityOptionChainItem.html#instrumentType\",\"classes\":\"\",\"parent\":\"EquityOptionChainItem\"},{\"kind\":1024,\"name\":\"underlying\",\"url\":\"interfaces/EquityOptionChainItem.html#underlying\",\"classes\":\"\",\"parent\":\"EquityOptionChainItem\"},{\"kind\":1024,\"name\":\"expiryDate\",\"url\":\"interfaces/EquityOptionChainItem.html#expiryDate\",\"classes\":\"\",\"parent\":\"EquityOptionChainItem\"},{\"kind\":1024,\"name\":\"optionType\",\"url\":\"interfaces/EquityOptionChainItem.html#optionType\",\"classes\":\"\",\"parent\":\"EquityOptionChainItem\"},{\"kind\":1024,\"name\":\"strikePrice\",\"url\":\"interfaces/EquityOptionChainItem.html#strikePrice\",\"classes\":\"\",\"parent\":\"EquityOptionChainItem\"},{\"kind\":1024,\"name\":\"openPrice\",\"url\":\"interfaces/EquityOptionChainItem.html#openPrice\",\"classes\":\"\",\"parent\":\"EquityOptionChainItem\"},{\"kind\":1024,\"name\":\"highPrice\",\"url\":\"interfaces/EquityOptionChainItem.html#highPrice\",\"classes\":\"\",\"parent\":\"EquityOptionChainItem\"},{\"kind\":1024,\"name\":\"lowPrice\",\"url\":\"interfaces/EquityOptionChainItem.html#lowPrice\",\"classes\":\"\",\"parent\":\"EquityOptionChainItem\"},{\"kind\":1024,\"name\":\"closePrice\",\"url\":\"interfaces/EquityOptionChainItem.html#closePrice\",\"classes\":\"\",\"parent\":\"EquityOptionChainItem\"},{\"kind\":1024,\"name\":\"prevClose\",\"url\":\"interfaces/EquityOptionChainItem.html#prevClose\",\"classes\":\"\",\"parent\":\"EquityOptionChainItem\"},{\"kind\":1024,\"name\":\"lastPrice\",\"url\":\"interfaces/EquityOptionChainItem.html#lastPrice\",\"classes\":\"\",\"parent\":\"EquityOptionChainItem\"},{\"kind\":1024,\"name\":\"change\",\"url\":\"interfaces/EquityOptionChainItem.html#change\",\"classes\":\"\",\"parent\":\"EquityOptionChainItem\"},{\"kind\":1024,\"name\":\"totalTradedVolume\",\"url\":\"interfaces/EquityOptionChainItem.html#totalTradedVolume\",\"classes\":\"\",\"parent\":\"EquityOptionChainItem\"},{\"kind\":1024,\"name\":\"totalTurnover\",\"url\":\"interfaces/EquityOptionChainItem.html#totalTurnover\",\"classes\":\"\",\"parent\":\"EquityOptionChainItem\"},{\"kind\":1024,\"name\":\"openInterest\",\"url\":\"interfaces/EquityOptionChainItem.html#openInterest\",\"classes\":\"\",\"parent\":\"EquityOptionChainItem\"},{\"kind\":1024,\"name\":\"changeinOpenInterest\",\"url\":\"interfaces/EquityOptionChainItem.html#changeinOpenInterest\",\"classes\":\"\",\"parent\":\"EquityOptionChainItem\"},{\"kind\":1024,\"name\":\"pchangeinOpenInterest\",\"url\":\"interfaces/EquityOptionChainItem.html#pchangeinOpenInterest\",\"classes\":\"\",\"parent\":\"EquityOptionChainItem\"},{\"kind\":1024,\"name\":\"underlyingValue\",\"url\":\"interfaces/EquityOptionChainItem.html#underlyingValue\",\"classes\":\"\",\"parent\":\"EquityOptionChainItem\"},{\"kind\":1024,\"name\":\"volumeFreezeQuantity\",\"url\":\"interfaces/EquityOptionChainItem.html#volumeFreezeQuantity\",\"classes\":\"\",\"parent\":\"EquityOptionChainItem\"},{\"kind\":1024,\"name\":\"ticksize\",\"url\":\"interfaces/EquityOptionChainItem.html#ticksize\",\"classes\":\"\",\"parent\":\"EquityOptionChainItem\"},{\"kind\":1024,\"name\":\"pchange\",\"url\":\"interfaces/EquityOptionChainItem.html#pchange\",\"classes\":\"\",\"parent\":\"EquityOptionChainItem\"},{\"kind\":256,\"name\":\"IndexEquityInfo\",\"url\":\"interfaces/IndexEquityInfo.html\",\"classes\":\"\"},{\"kind\":1024,\"name\":\"priority\",\"url\":\"interfaces/IndexEquityInfo.html#priority\",\"classes\":\"\",\"parent\":\"IndexEquityInfo\"},{\"kind\":1024,\"name\":\"symbol\",\"url\":\"interfaces/IndexEquityInfo.html#symbol\",\"classes\":\"\",\"parent\":\"IndexEquityInfo\"},{\"kind\":1024,\"name\":\"identifier\",\"url\":\"interfaces/IndexEquityInfo.html#identifier\",\"classes\":\"\",\"parent\":\"IndexEquityInfo\"},{\"kind\":1024,\"name\":\"series\",\"url\":\"interfaces/IndexEquityInfo.html#series\",\"classes\":\"\",\"parent\":\"IndexEquityInfo\"},{\"kind\":1024,\"name\":\"open\",\"url\":\"interfaces/IndexEquityInfo.html#open\",\"classes\":\"\",\"parent\":\"IndexEquityInfo\"},{\"kind\":1024,\"name\":\"dayHigh\",\"url\":\"interfaces/IndexEquityInfo.html#dayHigh\",\"classes\":\"\",\"parent\":\"IndexEquityInfo\"},{\"kind\":1024,\"name\":\"dayLow\",\"url\":\"interfaces/IndexEquityInfo.html#dayLow\",\"classes\":\"\",\"parent\":\"IndexEquityInfo\"},{\"kind\":1024,\"name\":\"lastPrice\",\"url\":\"interfaces/IndexEquityInfo.html#lastPrice\",\"classes\":\"\",\"parent\":\"IndexEquityInfo\"},{\"kind\":1024,\"name\":\"previousClose\",\"url\":\"interfaces/IndexEquityInfo.html#previousClose\",\"classes\":\"\",\"parent\":\"IndexEquityInfo\"},{\"kind\":1024,\"name\":\"change\",\"url\":\"interfaces/IndexEquityInfo.html#change\",\"classes\":\"\",\"parent\":\"IndexEquityInfo\"},{\"kind\":1024,\"name\":\"pChange\",\"url\":\"interfaces/IndexEquityInfo.html#pChange\",\"classes\":\"\",\"parent\":\"IndexEquityInfo\"},{\"kind\":1024,\"name\":\"totalTradedVolume\",\"url\":\"interfaces/IndexEquityInfo.html#totalTradedVolume\",\"classes\":\"\",\"parent\":\"IndexEquityInfo\"},{\"kind\":1024,\"name\":\"stockIndClosePrice\",\"url\":\"interfaces/IndexEquityInfo.html#stockIndClosePrice\",\"classes\":\"\",\"parent\":\"IndexEquityInfo\"},{\"kind\":1024,\"name\":\"totalTradedValue\",\"url\":\"interfaces/IndexEquityInfo.html#totalTradedValue\",\"classes\":\"\",\"parent\":\"IndexEquityInfo\"},{\"kind\":1024,\"name\":\"lastUpdateTime\",\"url\":\"interfaces/IndexEquityInfo.html#lastUpdateTime\",\"classes\":\"\",\"parent\":\"IndexEquityInfo\"},{\"kind\":1024,\"name\":\"yearHigh\",\"url\":\"interfaces/IndexEquityInfo.html#yearHigh\",\"classes\":\"\",\"parent\":\"IndexEquityInfo\"},{\"kind\":1024,\"name\":\"ffmc\",\"url\":\"interfaces/IndexEquityInfo.html#ffmc\",\"classes\":\"\",\"parent\":\"IndexEquityInfo\"},{\"kind\":1024,\"name\":\"yearLow\",\"url\":\"interfaces/IndexEquityInfo.html#yearLow\",\"classes\":\"\",\"parent\":\"IndexEquityInfo\"},{\"kind\":1024,\"name\":\"nearWKH\",\"url\":\"interfaces/IndexEquityInfo.html#nearWKH\",\"classes\":\"\",\"parent\":\"IndexEquityInfo\"},{\"kind\":1024,\"name\":\"nearWKL\",\"url\":\"interfaces/IndexEquityInfo.html#nearWKL\",\"classes\":\"\",\"parent\":\"IndexEquityInfo\"},{\"kind\":1024,\"name\":\"perChange365d\",\"url\":\"interfaces/IndexEquityInfo.html#perChange365d\",\"classes\":\"\",\"parent\":\"IndexEquityInfo\"},{\"kind\":1024,\"name\":\"perChange30d\",\"url\":\"interfaces/IndexEquityInfo.html#perChange30d\",\"classes\":\"\",\"parent\":\"IndexEquityInfo\"},{\"kind\":1024,\"name\":\"date365dAgo\",\"url\":\"interfaces/IndexEquityInfo.html#date365dAgo\",\"classes\":\"\",\"parent\":\"IndexEquityInfo\"},{\"kind\":1024,\"name\":\"date30dAgo\",\"url\":\"interfaces/IndexEquityInfo.html#date30dAgo\",\"classes\":\"\",\"parent\":\"IndexEquityInfo\"},{\"kind\":1024,\"name\":\"chartTodayPath\",\"url\":\"interfaces/IndexEquityInfo.html#chartTodayPath\",\"classes\":\"\",\"parent\":\"IndexEquityInfo\"},{\"kind\":1024,\"name\":\"chart30dPath\",\"url\":\"interfaces/IndexEquityInfo.html#chart30dPath\",\"classes\":\"\",\"parent\":\"IndexEquityInfo\"},{\"kind\":1024,\"name\":\"chart365dPath\",\"url\":\"interfaces/IndexEquityInfo.html#chart365dPath\",\"classes\":\"\",\"parent\":\"IndexEquityInfo\"},{\"kind\":1024,\"name\":\"meta\",\"url\":\"interfaces/IndexEquityInfo.html#meta\",\"classes\":\"\",\"parent\":\"IndexEquityInfo\"},{\"kind\":256,\"name\":\"IndexRecords\",\"url\":\"interfaces/IndexRecords.html\",\"classes\":\"\"},{\"kind\":1024,\"name\":\"strikePrices\",\"url\":\"interfaces/IndexRecords.html#strikePrices\",\"classes\":\"\",\"parent\":\"IndexRecords\"},{\"kind\":1024,\"name\":\"expiryDates\",\"url\":\"interfaces/IndexRecords.html#expiryDates\",\"classes\":\"tsd-is-inherited\",\"parent\":\"IndexRecords\"},{\"kind\":1024,\"name\":\"data\",\"url\":\"interfaces/IndexRecords.html#data\",\"classes\":\"tsd-is-inherited\",\"parent\":\"IndexRecords\"},{\"kind\":1024,\"name\":\"timestamp\",\"url\":\"interfaces/IndexRecords.html#timestamp\",\"classes\":\"tsd-is-inherited\",\"parent\":\"IndexRecords\"},{\"kind\":1024,\"name\":\"underlyingValue\",\"url\":\"interfaces/IndexRecords.html#underlyingValue\",\"classes\":\"tsd-is-inherited\",\"parent\":\"IndexRecords\"},{\"kind\":256,\"name\":\"CommodityRecords\",\"url\":\"interfaces/CommodityRecords.html\",\"classes\":\"\"},{\"kind\":1024,\"name\":\"strikePrices\",\"url\":\"interfaces/CommodityRecords.html#strikePrices\",\"classes\":\"\",\"parent\":\"CommodityRecords\"},{\"kind\":1024,\"name\":\"expiryDates\",\"url\":\"interfaces/CommodityRecords.html#expiryDates\",\"classes\":\"tsd-is-inherited\",\"parent\":\"CommodityRecords\"},{\"kind\":1024,\"name\":\"data\",\"url\":\"interfaces/CommodityRecords.html#data\",\"classes\":\"tsd-is-inherited\",\"parent\":\"CommodityRecords\"},{\"kind\":1024,\"name\":\"timestamp\",\"url\":\"interfaces/CommodityRecords.html#timestamp\",\"classes\":\"tsd-is-inherited\",\"parent\":\"CommodityRecords\"},{\"kind\":1024,\"name\":\"underlyingValue\",\"url\":\"interfaces/CommodityRecords.html#underlyingValue\",\"classes\":\"tsd-is-inherited\",\"parent\":\"CommodityRecords\"},{\"kind\":256,\"name\":\"Filtered\",\"url\":\"interfaces/Filtered.html\",\"classes\":\"\"},{\"kind\":1024,\"name\":\"data\",\"url\":\"interfaces/Filtered.html#data\",\"classes\":\"\",\"parent\":\"Filtered\"},{\"kind\":1024,\"name\":\"CE\",\"url\":\"interfaces/Filtered.html#CE\",\"classes\":\"\",\"parent\":\"Filtered\"},{\"kind\":1024,\"name\":\"PE\",\"url\":\"interfaces/Filtered.html#PE\",\"classes\":\"\",\"parent\":\"Filtered\"},{\"kind\":256,\"name\":\"Holiday\",\"url\":\"interfaces/Holiday.html\",\"classes\":\"\"},{\"kind\":1024,\"name\":\"tradingDate\",\"url\":\"interfaces/Holiday.html#tradingDate\",\"classes\":\"\",\"parent\":\"Holiday\"},{\"kind\":1024,\"name\":\"weekDay\",\"url\":\"interfaces/Holiday.html#weekDay\",\"classes\":\"\",\"parent\":\"Holiday\"},{\"kind\":1024,\"name\":\"description\",\"url\":\"interfaces/Holiday.html#description\",\"classes\":\"\",\"parent\":\"Holiday\"},{\"kind\":1024,\"name\":\"morning_session\",\"url\":\"interfaces/Holiday.html#morning_session\",\"classes\":\"\",\"parent\":\"Holiday\"},{\"kind\":1024,\"name\":\"evening_session\",\"url\":\"interfaces/Holiday.html#evening_session\",\"classes\":\"\",\"parent\":\"Holiday\"},{\"kind\":1024,\"name\":\"Sr_no\",\"url\":\"interfaces/Holiday.html#Sr_no\",\"classes\":\"\",\"parent\":\"Holiday\"},{\"kind\":256,\"name\":\"MarketState\",\"url\":\"interfaces/MarketState.html\",\"classes\":\"\"},{\"kind\":1024,\"name\":\"market\",\"url\":\"interfaces/MarketState.html#market\",\"classes\":\"\",\"parent\":\"MarketState\"},{\"kind\":1024,\"name\":\"marketStatus\",\"url\":\"interfaces/MarketState.html#marketStatus\",\"classes\":\"\",\"parent\":\"MarketState\"},{\"kind\":1024,\"name\":\"tradeDate\",\"url\":\"interfaces/MarketState.html#tradeDate\",\"classes\":\"\",\"parent\":\"MarketState\"},{\"kind\":1024,\"name\":\"index\",\"url\":\"interfaces/MarketState.html#index\",\"classes\":\"\",\"parent\":\"MarketState\"},{\"kind\":1024,\"name\":\"last\",\"url\":\"interfaces/MarketState.html#last\",\"classes\":\"\",\"parent\":\"MarketState\"},{\"kind\":1024,\"name\":\"variation\",\"url\":\"interfaces/MarketState.html#variation\",\"classes\":\"\",\"parent\":\"MarketState\"},{\"kind\":1024,\"name\":\"percentChange\",\"url\":\"interfaces/MarketState.html#percentChange\",\"classes\":\"\",\"parent\":\"MarketState\"},{\"kind\":1024,\"name\":\"marketStatusMessage\",\"url\":\"interfaces/MarketState.html#marketStatusMessage\",\"classes\":\"\",\"parent\":\"MarketState\"},{\"kind\":1024,\"name\":\"expiryDate\",\"url\":\"interfaces/MarketState.html#expiryDate\",\"classes\":\"\",\"parent\":\"MarketState\"},{\"kind\":1024,\"name\":\"underlying\",\"url\":\"interfaces/MarketState.html#underlying\",\"classes\":\"\",\"parent\":\"MarketState\"},{\"kind\":1024,\"name\":\"updated_time\",\"url\":\"interfaces/MarketState.html#updated_time\",\"classes\":\"\",\"parent\":\"MarketState\"},{\"kind\":1024,\"name\":\"tradeDateFormatted\",\"url\":\"interfaces/MarketState.html#tradeDateFormatted\",\"classes\":\"\",\"parent\":\"MarketState\"},{\"kind\":1024,\"name\":\"slickclass\",\"url\":\"interfaces/MarketState.html#slickclass\",\"classes\":\"\",\"parent\":\"MarketState\"},{\"kind\":256,\"name\":\"MarketCap\",\"url\":\"interfaces/MarketCap.html\",\"classes\":\"\"},{\"kind\":1024,\"name\":\"timeStamp\",\"url\":\"interfaces/MarketCap.html#timeStamp\",\"classes\":\"\",\"parent\":\"MarketCap\"},{\"kind\":1024,\"name\":\"marketCapinTRDollars\",\"url\":\"interfaces/MarketCap.html#marketCapinTRDollars\",\"classes\":\"\",\"parent\":\"MarketCap\"},{\"kind\":1024,\"name\":\"marketCapinLACCRRupees\",\"url\":\"interfaces/MarketCap.html#marketCapinLACCRRupees\",\"classes\":\"\",\"parent\":\"MarketCap\"},{\"kind\":1024,\"name\":\"marketCapinCRRupees\",\"url\":\"interfaces/MarketCap.html#marketCapinCRRupees\",\"classes\":\"\",\"parent\":\"MarketCap\"},{\"kind\":1024,\"name\":\"marketCapinCRRupeesFormatted\",\"url\":\"interfaces/MarketCap.html#marketCapinCRRupeesFormatted\",\"classes\":\"\",\"parent\":\"MarketCap\"},{\"kind\":1024,\"name\":\"marketCapinLACCRRupeesFormatted\",\"url\":\"interfaces/MarketCap.html#marketCapinLACCRRupeesFormatted\",\"classes\":\"\",\"parent\":\"MarketCap\"},{\"kind\":1024,\"name\":\"underlying\",\"url\":\"interfaces/MarketCap.html#underlying\",\"classes\":\"\",\"parent\":\"MarketCap\"},{\"kind\":256,\"name\":\"IndicativeNifty50\",\"url\":\"interfaces/IndicativeNifty50.html\",\"classes\":\"\"},{\"kind\":1024,\"name\":\"dateTime\",\"url\":\"interfaces/IndicativeNifty50.html#dateTime\",\"classes\":\"\",\"parent\":\"IndicativeNifty50\"},{\"kind\":1024,\"name\":\"indicativeTime\",\"url\":\"interfaces/IndicativeNifty50.html#indicativeTime\",\"classes\":\"\",\"parent\":\"IndicativeNifty50\"},{\"kind\":1024,\"name\":\"indexName\",\"url\":\"interfaces/IndicativeNifty50.html#indexName\",\"classes\":\"\",\"parent\":\"IndicativeNifty50\"},{\"kind\":1024,\"name\":\"indexLast\",\"url\":\"interfaces/IndicativeNifty50.html#indexLast\",\"classes\":\"\",\"parent\":\"IndicativeNifty50\"},{\"kind\":1024,\"name\":\"indexPercChange\",\"url\":\"interfaces/IndicativeNifty50.html#indexPercChange\",\"classes\":\"\",\"parent\":\"IndicativeNifty50\"},{\"kind\":1024,\"name\":\"indexTimeVal\",\"url\":\"interfaces/IndicativeNifty50.html#indexTimeVal\",\"classes\":\"\",\"parent\":\"IndicativeNifty50\"},{\"kind\":1024,\"name\":\"closingValue\",\"url\":\"interfaces/IndicativeNifty50.html#closingValue\",\"classes\":\"\",\"parent\":\"IndicativeNifty50\"},{\"kind\":1024,\"name\":\"finalClosingValue\",\"url\":\"interfaces/IndicativeNifty50.html#finalClosingValue\",\"classes\":\"\",\"parent\":\"IndicativeNifty50\"},{\"kind\":1024,\"name\":\"change\",\"url\":\"interfaces/IndicativeNifty50.html#change\",\"classes\":\"\",\"parent\":\"IndicativeNifty50\"},{\"kind\":1024,\"name\":\"perChange\",\"url\":\"interfaces/IndicativeNifty50.html#perChange\",\"classes\":\"\",\"parent\":\"IndicativeNifty50\"},{\"kind\":1024,\"name\":\"status\",\"url\":\"interfaces/IndicativeNifty50.html#status\",\"classes\":\"\",\"parent\":\"IndicativeNifty50\"},{\"kind\":256,\"name\":\"GiftNifty\",\"url\":\"interfaces/GiftNifty.html\",\"classes\":\"\"},{\"kind\":1024,\"name\":\"INSTRUMENTTYPE\",\"url\":\"interfaces/GiftNifty.html#INSTRUMENTTYPE\",\"classes\":\"\",\"parent\":\"GiftNifty\"},{\"kind\":1024,\"name\":\"SYMBOL\",\"url\":\"interfaces/GiftNifty.html#SYMBOL\",\"classes\":\"\",\"parent\":\"GiftNifty\"},{\"kind\":1024,\"name\":\"EXPIRYDATE\",\"url\":\"interfaces/GiftNifty.html#EXPIRYDATE\",\"classes\":\"\",\"parent\":\"GiftNifty\"},{\"kind\":1024,\"name\":\"OPTIONTYPE\",\"url\":\"interfaces/GiftNifty.html#OPTIONTYPE\",\"classes\":\"\",\"parent\":\"GiftNifty\"},{\"kind\":1024,\"name\":\"STRIKEPRICE\",\"url\":\"interfaces/GiftNifty.html#STRIKEPRICE\",\"classes\":\"\",\"parent\":\"GiftNifty\"},{\"kind\":1024,\"name\":\"LASTPRICE\",\"url\":\"interfaces/GiftNifty.html#LASTPRICE\",\"classes\":\"\",\"parent\":\"GiftNifty\"},{\"kind\":1024,\"name\":\"DAYCHANGE\",\"url\":\"interfaces/GiftNifty.html#DAYCHANGE\",\"classes\":\"\",\"parent\":\"GiftNifty\"},{\"kind\":1024,\"name\":\"PERCHANGE\",\"url\":\"interfaces/GiftNifty.html#PERCHANGE\",\"classes\":\"\",\"parent\":\"GiftNifty\"},{\"kind\":1024,\"name\":\"CONTRACTSTRADED\",\"url\":\"interfaces/GiftNifty.html#CONTRACTSTRADED\",\"classes\":\"\",\"parent\":\"GiftNifty\"},{\"kind\":1024,\"name\":\"TIMESTMP\",\"url\":\"interfaces/GiftNifty.html#TIMESTMP\",\"classes\":\"\",\"parent\":\"GiftNifty\"},{\"kind\":1024,\"name\":\"id\",\"url\":\"interfaces/GiftNifty.html#id\",\"classes\":\"\",\"parent\":\"GiftNifty\"},{\"kind\":256,\"name\":\"Datum\",\"url\":\"interfaces/Datum.html\",\"classes\":\"\"},{\"kind\":1024,\"name\":\"strikePrice\",\"url\":\"interfaces/Datum.html#strikePrice\",\"classes\":\"\",\"parent\":\"Datum\"},{\"kind\":1024,\"name\":\"expiryDates\",\"url\":\"interfaces/Datum.html#expiryDates\",\"classes\":\"\",\"parent\":\"Datum\"},{\"kind\":1024,\"name\":\"expiryDate\",\"url\":\"interfaces/Datum.html#expiryDate\",\"classes\":\"\",\"parent\":\"Datum\"},{\"kind\":1024,\"name\":\"PE\",\"url\":\"interfaces/Datum.html#PE\",\"classes\":\"\",\"parent\":\"Datum\"},{\"kind\":1024,\"name\":\"CE\",\"url\":\"interfaces/Datum.html#CE\",\"classes\":\"\",\"parent\":\"Datum\"},{\"kind\":256,\"name\":\"PreOpenDetails\",\"url\":\"interfaces/PreOpenDetails.html\",\"classes\":\"\"},{\"kind\":1024,\"name\":\"price\",\"url\":\"interfaces/PreOpenDetails.html#price\",\"classes\":\"\",\"parent\":\"PreOpenDetails\"},{\"kind\":1024,\"name\":\"buyQty\",\"url\":\"interfaces/PreOpenDetails.html#buyQty\",\"classes\":\"\",\"parent\":\"PreOpenDetails\"},{\"kind\":1024,\"name\":\"sellQty\",\"url\":\"interfaces/PreOpenDetails.html#sellQty\",\"classes\":\"\",\"parent\":\"PreOpenDetails\"},{\"kind\":1024,\"name\":\"iep\",\"url\":\"interfaces/PreOpenDetails.html#iep\",\"classes\":\"\",\"parent\":\"PreOpenDetails\"},{\"kind\":256,\"name\":\"OptionsData\",\"url\":\"interfaces/OptionsData.html\",\"classes\":\"\"},{\"kind\":1024,\"name\":\"totOI\",\"url\":\"interfaces/OptionsData.html#totOI\",\"classes\":\"\",\"parent\":\"OptionsData\"},{\"kind\":1024,\"name\":\"totVol\",\"url\":\"interfaces/OptionsData.html#totVol\",\"classes\":\"\",\"parent\":\"OptionsData\"},{\"kind\":256,\"name\":\"OptionsDetails\",\"url\":\"interfaces/OptionsDetails.html\",\"classes\":\"\"},{\"kind\":1024,\"name\":\"strikePrice\",\"url\":\"interfaces/OptionsDetails.html#strikePrice\",\"classes\":\"\",\"parent\":\"OptionsDetails\"},{\"kind\":1024,\"name\":\"expiryDate\",\"url\":\"interfaces/OptionsDetails.html#expiryDate\",\"classes\":\"\",\"parent\":\"OptionsDetails\"},{\"kind\":1024,\"name\":\"underlying\",\"url\":\"interfaces/OptionsDetails.html#underlying\",\"classes\":\"\",\"parent\":\"OptionsDetails\"},{\"kind\":1024,\"name\":\"identifier\",\"url\":\"interfaces/OptionsDetails.html#identifier\",\"classes\":\"\",\"parent\":\"OptionsDetails\"},{\"kind\":1024,\"name\":\"openInterest\",\"url\":\"interfaces/OptionsDetails.html#openInterest\",\"classes\":\"\",\"parent\":\"OptionsDetails\"},{\"kind\":1024,\"name\":\"changeinOpenInterest\",\"url\":\"interfaces/OptionsDetails.html#changeinOpenInterest\",\"classes\":\"\",\"parent\":\"OptionsDetails\"},{\"kind\":1024,\"name\":\"pchangeinOpenInterest\",\"url\":\"interfaces/OptionsDetails.html#pchangeinOpenInterest\",\"classes\":\"\",\"parent\":\"OptionsDetails\"},{\"kind\":1024,\"name\":\"totalTradedVolume\",\"url\":\"interfaces/OptionsDetails.html#totalTradedVolume\",\"classes\":\"\",\"parent\":\"OptionsDetails\"},{\"kind\":1024,\"name\":\"impliedVolatility\",\"url\":\"interfaces/OptionsDetails.html#impliedVolatility\",\"classes\":\"\",\"parent\":\"OptionsDetails\"},{\"kind\":1024,\"name\":\"lastPrice\",\"url\":\"interfaces/OptionsDetails.html#lastPrice\",\"classes\":\"\",\"parent\":\"OptionsDetails\"},{\"kind\":1024,\"name\":\"change\",\"url\":\"interfaces/OptionsDetails.html#change\",\"classes\":\"\",\"parent\":\"OptionsDetails\"},{\"kind\":1024,\"name\":\"pChange\",\"url\":\"interfaces/OptionsDetails.html#pChange\",\"classes\":\"\",\"parent\":\"OptionsDetails\"},{\"kind\":1024,\"name\":\"pchange\",\"url\":\"interfaces/OptionsDetails.html#pchange-1\",\"classes\":\"\",\"parent\":\"OptionsDetails\"},{\"kind\":1024,\"name\":\"totalBuyQuantity\",\"url\":\"interfaces/OptionsDetails.html#totalBuyQuantity\",\"classes\":\"\",\"parent\":\"OptionsDetails\"},{\"kind\":1024,\"name\":\"totalSellQuantity\",\"url\":\"interfaces/OptionsDetails.html#totalSellQuantity\",\"classes\":\"\",\"parent\":\"OptionsDetails\"},{\"kind\":1024,\"name\":\"bidQty\",\"url\":\"interfaces/OptionsDetails.html#bidQty\",\"classes\":\"\",\"parent\":\"OptionsDetails\"},{\"kind\":1024,\"name\":\"bidprice\",\"url\":\"interfaces/OptionsDetails.html#bidprice\",\"classes\":\"\",\"parent\":\"OptionsDetails\"},{\"kind\":1024,\"name\":\"askQty\",\"url\":\"interfaces/OptionsDetails.html#askQty\",\"classes\":\"\",\"parent\":\"OptionsDetails\"},{\"kind\":1024,\"name\":\"askPrice\",\"url\":\"interfaces/OptionsDetails.html#askPrice\",\"classes\":\"\",\"parent\":\"OptionsDetails\"},{\"kind\":1024,\"name\":\"buyPrice1\",\"url\":\"interfaces/OptionsDetails.html#buyPrice1\",\"classes\":\"\",\"parent\":\"OptionsDetails\"},{\"kind\":1024,\"name\":\"buyQuantity1\",\"url\":\"interfaces/OptionsDetails.html#buyQuantity1\",\"classes\":\"\",\"parent\":\"OptionsDetails\"},{\"kind\":1024,\"name\":\"sellPrice1\",\"url\":\"interfaces/OptionsDetails.html#sellPrice1\",\"classes\":\"\",\"parent\":\"OptionsDetails\"},{\"kind\":1024,\"name\":\"sellQuantity1\",\"url\":\"interfaces/OptionsDetails.html#sellQuantity1\",\"classes\":\"\",\"parent\":\"OptionsDetails\"},{\"kind\":1024,\"name\":\"underlyingValue\",\"url\":\"interfaces/OptionsDetails.html#underlyingValue\",\"classes\":\"\",\"parent\":\"OptionsDetails\"},{\"kind\":1024,\"name\":\"optionType\",\"url\":\"interfaces/OptionsDetails.html#optionType\",\"classes\":\"\",\"parent\":\"OptionsDetails\"}],\"index\":{\"version\":\"2.3.9\",\"fields\":[\"name\",\"comment\"],\"fieldVectors\":[[\"name/0\",[0,58.898]],[\"comment/0\",[]],[\"name/1\",[1,53.79]],[\"comment/1\",[]],[\"name/2\",[2,58.898]],[\"comment/2\",[]],[\"name/3\",[3,58.898]],[\"comment/3\",[]],[\"name/4\",[4,58.898]],[\"comment/4\",[]],[\"name/5\",[5,58.898]],[\"comment/5\",[]],[\"name/6\",[6,58.898]],[\"comment/6\",[]],[\"name/7\",[7,58.898]],[\"comment/7\",[]],[\"name/8\",[8,58.898]],[\"comment/8\",[]],[\"name/9\",[9,58.898]],[\"comment/9\",[]],[\"name/10\",[10,58.898]],[\"comment/10\",[]],[\"name/11\",[11,58.898]],[\"comment/11\",[]],[\"name/12\",[12,58.898]],[\"comment/12\",[]],[\"name/13\",[13,58.898]],[\"comment/13\",[]],[\"name/14\",[14,58.898]],[\"comment/14\",[]],[\"name/15\",[15,58.898]],[\"comment/15\",[]],[\"name/16\",[16,58.898]],[\"comment/16\",[]],[\"name/17\",[17,58.898]],[\"comment/17\",[]],[\"name/18\",[18,58.898]],[\"comment/18\",[]],[\"name/19\",[19,58.898]],[\"comment/19\",[]],[\"name/20\",[20,58.898]],[\"comment/20\",[]],[\"name/21\",[21,58.898]],[\"comment/21\",[]],[\"name/22\",[22,58.898]],[\"comment/22\",[]],[\"name/23\",[23,58.898]],[\"comment/23\",[]],[\"name/24\",[24,58.898]],[\"comment/24\",[]],[\"name/25\",[25,58.898]],[\"comment/25\",[]],[\"name/26\",[26,58.898]],[\"comment/26\",[]],[\"name/27\",[27,58.898]],[\"comment/27\",[]],[\"name/28\",[28,58.898]],[\"comment/28\",[]],[\"name/29\",[29,58.898]],[\"comment/29\",[]],[\"name/30\",[30,58.898]],[\"comment/30\",[]],[\"name/31\",[31,58.898]],[\"comment/31\",[]],[\"name/32\",[32,58.898]],[\"comment/32\",[]],[\"name/33\",[33,58.898]],[\"comment/33\",[]],[\"name/34\",[34,58.898]],[\"comment/34\",[]],[\"name/35\",[35,58.898]],[\"comment/35\",[]],[\"name/36\",[36,58.898]],[\"comment/36\",[]],[\"name/37\",[37,58.898]],[\"comment/37\",[]],[\"name/38\",[38,58.898]],[\"comment/38\",[]],[\"name/39\",[39,58.898]],[\"comment/39\",[]],[\"name/40\",[40,58.898]],[\"comment/40\",[]],[\"name/41\",[41,58.898]],[\"comment/41\",[]],[\"name/42\",[42,58.898]],[\"comment/42\",[]],[\"name/43\",[43,58.898]],[\"comment/43\",[]],[\"name/44\",[44,58.898]],[\"comment/44\",[]],[\"name/45\",[45,58.898]],[\"comment/45\",[]],[\"name/46\",[46,58.898]],[\"comment/46\",[]],[\"name/47\",[47,58.898]],[\"comment/47\",[]],[\"name/48\",[48,58.898]],[\"comment/48\",[]],[\"name/49\",[49,58.898]],[\"comment/49\",[]],[\"name/50\",[50,58.898]],[\"comment/50\",[]],[\"name/51\",[51,45.905]],[\"comment/51\",[]],[\"name/52\",[52,50.425]],[\"comment/52\",[]],[\"name/53\",[53,58.898]],[\"comment/53\",[]],[\"name/54\",[54,53.79]],[\"comment/54\",[]],[\"name/55\",[55,58.898]],[\"comment/55\",[]],[\"name/56\",[56,58.898]],[\"comment/56\",[]],[\"name/57\",[57,53.79]],[\"comment/57\",[]],[\"name/58\",[58,58.898]],[\"comment/58\",[]],[\"name/59\",[59,58.898]],[\"comment/59\",[]],[\"name/60\",[60,30.181]],[\"comment/60\",[]],[\"name/61\",[61,58.898]],[\"comment/61\",[]],[\"name/62\",[62,58.898]],[\"comment/62\",[]],[\"name/63\",[63,58.898]],[\"comment/63\",[]],[\"name/64\",[64,58.898]],[\"comment/64\",[]],[\"name/65\",[65,58.898]],[\"comment/65\",[]],[\"name/66\",[60,30.181]],[\"comment/66\",[]],[\"name/67\",[66,58.898]],[\"comment/67\",[]],[\"name/68\",[67,58.898]],[\"comment/68\",[]],[\"name/69\",[68,50.425]],[\"comment/69\",[]],[\"name/70\",[69,58.898]],[\"comment/70\",[]],[\"name/71\",[70,58.898]],[\"comment/71\",[]],[\"name/72\",[71,58.898]],[\"comment/72\",[]],[\"name/73\",[72,58.898]],[\"comment/73\",[]],[\"name/74\",[73,58.898]],[\"comment/74\",[]],[\"name/75\",[74,58.898]],[\"comment/75\",[]],[\"name/76\",[60,30.181]],[\"comment/76\",[]],[\"name/77\",[75,50.425]],[\"comment/77\",[]],[\"name/78\",[76,50.425]],[\"comment/78\",[]],[\"name/79\",[77,47.912]],[\"comment/79\",[]],[\"name/80\",[78,58.898]],[\"comment/80\",[]],[\"name/81\",[79,58.898]],[\"comment/81\",[]],[\"name/82\",[80,58.898]],[\"comment/82\",[]],[\"name/83\",[60,30.181]],[\"comment/83\",[]],[\"name/84\",[81,41.552]],[\"comment/84\",[]],[\"name/85\",[82,45.905]],[\"comment/85\",[]],[\"name/86\",[83,53.79]],[\"comment/86\",[]],[\"name/87\",[84,53.79]],[\"comment/87\",[]],[\"name/88\",[85,58.898]],[\"comment/88\",[]],[\"name/89\",[86,58.898]],[\"comment/89\",[]],[\"name/90\",[87,58.898]],[\"comment/90\",[]],[\"name/91\",[88,58.898]],[\"comment/91\",[]],[\"name/92\",[89,53.79]],[\"comment/92\",[]],[\"name/93\",[90,58.898]],[\"comment/93\",[]],[\"name/94\",[60,30.181]],[\"comment/94\",[]],[\"name/95\",[91,58.898]],[\"comment/95\",[]],[\"name/96\",[92,58.898]],[\"comment/96\",[]],[\"name/97\",[93,58.898]],[\"comment/97\",[]],[\"name/98\",[94,58.898]],[\"comment/98\",[]],[\"name/99\",[95,58.898]],[\"comment/99\",[]],[\"name/100\",[96,58.898]],[\"comment/100\",[]],[\"name/101\",[97,58.898]],[\"comment/101\",[]],[\"name/102\",[60,30.181]],[\"comment/102\",[]],[\"name/103\",[98,58.898]],[\"comment/103\",[]],[\"name/104\",[99,58.898]],[\"comment/104\",[]],[\"name/105\",[100,58.898]],[\"comment/105\",[]],[\"name/106\",[101,58.898]],[\"comment/106\",[]],[\"name/107\",[102,58.898]],[\"comment/107\",[]],[\"name/108\",[103,58.898]],[\"comment/108\",[]],[\"name/109\",[104,34.919]],[\"comment/109\",[]],[\"name/110\",[105,53.79]],[\"comment/110\",[]],[\"name/111\",[60,30.181]],[\"comment/111\",[]],[\"name/112\",[106,50.425]],[\"comment/112\",[]],[\"name/113\",[107,53.79]],[\"comment/113\",[]],[\"name/114\",[108,53.79]],[\"comment/114\",[]],[\"name/115\",[109,58.898]],[\"comment/115\",[]],[\"name/116\",[110,58.898]],[\"comment/116\",[]],[\"name/117\",[104,34.919]],[\"comment/117\",[]],[\"name/118\",[111,58.898]],[\"comment/118\",[]],[\"name/119\",[52,50.425]],[\"comment/119\",[]],[\"name/120\",[112,58.898]],[\"comment/120\",[]],[\"name/121\",[60,30.181]],[\"comment/121\",[]],[\"name/122\",[113,53.79]],[\"comment/122\",[]],[\"name/123\",[114,53.79]],[\"comment/123\",[]],[\"name/124\",[115,53.79]],[\"comment/124\",[]],[\"name/125\",[116,44.235]],[\"comment/125\",[]],[\"name/126\",[104,34.919]],[\"comment/126\",[]],[\"name/127\",[57,53.79]],[\"comment/127\",[]],[\"name/128\",[60,30.181]],[\"comment/128\",[]],[\"name/129\",[117,53.79]],[\"comment/129\",[]],[\"name/130\",[77,47.912]],[\"comment/130\",[]],[\"name/131\",[118,58.898]],[\"comment/131\",[]],[\"name/132\",[119,58.898]],[\"comment/132\",[]],[\"name/133\",[120,50.425]],[\"comment/133\",[]],[\"name/134\",[121,50.425]],[\"comment/134\",[]],[\"name/135\",[122,58.898]],[\"comment/135\",[]],[\"name/136\",[123,44.235]],[\"comment/136\",[]],[\"name/137\",[124,58.898]],[\"comment/137\",[]],[\"name/138\",[125,53.79]],[\"comment/138\",[]],[\"name/139\",[126,53.79]],[\"comment/139\",[]],[\"name/140\",[127,58.898]],[\"comment/140\",[]],[\"name/141\",[128,53.79]],[\"comment/141\",[]],[\"name/142\",[129,53.79]],[\"comment/142\",[]],[\"name/143\",[130,50.425]],[\"comment/143\",[]],[\"name/144\",[131,50.425]],[\"comment/144\",[]],[\"name/145\",[132,53.79]],[\"comment/145\",[]],[\"name/146\",[133,53.79]],[\"comment/146\",[]],[\"name/147\",[134,53.79]],[\"comment/147\",[]],[\"name/148\",[81,41.552]],[\"comment/148\",[]],[\"name/149\",[82,45.905]],[\"comment/149\",[]],[\"name/150\",[135,58.898]],[\"comment/150\",[]],[\"name/151\",[136,47.912]],[\"comment/151\",[]],[\"name/152\",[60,30.181]],[\"comment/152\",[]],[\"name/153\",[137,53.79]],[\"comment/153\",[]],[\"name/154\",[136,47.912]],[\"comment/154\",[]],[\"name/155\",[138,53.79]],[\"comment/155\",[]],[\"name/156\",[139,53.79]],[\"comment/156\",[]],[\"name/157\",[121,50.425]],[\"comment/157\",[]],[\"name/158\",[140,53.79]],[\"comment/158\",[]],[\"name/159\",[141,53.79]],[\"comment/159\",[]],[\"name/160\",[142,53.79]],[\"comment/160\",[]],[\"name/161\",[131,50.425]],[\"comment/161\",[]],[\"name/162\",[130,50.425]],[\"comment/162\",[]],[\"name/163\",[143,58.898]],[\"comment/163\",[]],[\"name/164\",[104,34.919]],[\"comment/164\",[]],[\"name/165\",[116,44.235]],[\"comment/165\",[]],[\"name/166\",[144,58.898]],[\"comment/166\",[]],[\"name/167\",[145,53.79]],[\"comment/167\",[]],[\"name/168\",[146,50.425]],[\"comment/168\",[]],[\"name/169\",[147,58.898]],[\"comment/169\",[]],[\"name/170\",[145,53.79]],[\"comment/170\",[]],[\"name/171\",[146,50.425]],[\"comment/171\",[]],[\"name/172\",[148,58.898]],[\"comment/172\",[]],[\"name/173\",[149,47.912]],[\"comment/173\",[]],[\"name/174\",[150,45.905]],[\"comment/174\",[]],[\"name/175\",[151,58.898]],[\"comment/175\",[]],[\"name/176\",[152,58.898]],[\"comment/176\",[]],[\"name/177\",[60,30.181]],[\"comment/177\",[]],[\"name/178\",[104,34.919]],[\"comment/178\",[]],[\"name/179\",[153,58.898]],[\"comment/179\",[]],[\"name/180\",[60,30.181]],[\"comment/180\",[]],[\"name/181\",[104,34.919]],[\"comment/181\",[]],[\"name/182\",[154,58.898]],[\"comment/182\",[]],[\"name/183\",[60,30.181]],[\"comment/183\",[]],[\"name/184\",[104,34.919]],[\"comment/184\",[]],[\"name/185\",[60,30.181]],[\"comment/185\",[]],[\"name/186\",[155,58.898]],[\"comment/186\",[]],[\"name/187\",[60,30.181]],[\"comment/187\",[]],[\"name/188\",[104,34.919]],[\"comment/188\",[]],[\"name/189\",[156,58.898]],[\"comment/189\",[]],[\"name/190\",[60,30.181]],[\"comment/190\",[]],[\"name/191\",[104,34.919]],[\"comment/191\",[]],[\"name/192\",[1,53.79]],[\"comment/192\",[]],[\"name/193\",[157,58.898]],[\"comment/193\",[]],[\"name/194\",[60,30.181]],[\"comment/194\",[]],[\"name/195\",[158,58.898]],[\"comment/195\",[]],[\"name/196\",[159,58.898]],[\"comment/196\",[]],[\"name/197\",[160,58.898]],[\"comment/197\",[]],[\"name/198\",[161,58.898]],[\"comment/198\",[]],[\"name/199\",[162,58.898]],[\"comment/199\",[]],[\"name/200\",[163,58.898]],[\"comment/200\",[]],[\"name/201\",[164,53.79]],[\"comment/201\",[]],[\"name/202\",[165,53.79]],[\"comment/202\",[]],[\"name/203\",[166,58.898]],[\"comment/203\",[]],[\"name/204\",[167,58.898]],[\"comment/204\",[]],[\"name/205\",[136,47.912]],[\"comment/205\",[]],[\"name/206\",[168,53.79]],[\"comment/206\",[]],[\"name/207\",[169,53.79]],[\"comment/207\",[]],[\"name/208\",[170,53.79]],[\"comment/208\",[]],[\"name/209\",[171,53.79]],[\"comment/209\",[]],[\"name/210\",[172,58.898]],[\"comment/210\",[]],[\"name/211\",[82,45.905]],[\"comment/211\",[]],[\"name/212\",[81,41.552]],[\"comment/212\",[]],[\"name/213\",[173,58.898]],[\"comment/213\",[]],[\"name/214\",[174,47.912]],[\"comment/214\",[]],[\"name/215\",[175,58.898]],[\"comment/215\",[]],[\"name/216\",[104,34.919]],[\"comment/216\",[]],[\"name/217\",[176,58.898]],[\"comment/217\",[]],[\"name/218\",[177,58.898]],[\"comment/218\",[]],[\"name/219\",[178,58.898]],[\"comment/219\",[]],[\"name/220\",[179,58.898]],[\"comment/220\",[]],[\"name/221\",[104,34.919]],[\"comment/221\",[]],[\"name/222\",[107,53.79]],[\"comment/222\",[]],[\"name/223\",[108,53.79]],[\"comment/223\",[]],[\"name/224\",[180,58.898]],[\"comment/224\",[]],[\"name/225\",[104,34.919]],[\"comment/225\",[]],[\"name/226\",[181,58.898]],[\"comment/226\",[]],[\"name/227\",[182,58.898]],[\"comment/227\",[]],[\"name/228\",[104,34.919]],[\"comment/228\",[]],[\"name/229\",[116,44.235]],[\"comment/229\",[]],[\"name/230\",[114,53.79]],[\"comment/230\",[]],[\"name/231\",[113,53.79]],[\"comment/231\",[]],[\"name/232\",[115,53.79]],[\"comment/232\",[]],[\"name/233\",[82,45.905]],[\"comment/233\",[]],[\"name/234\",[83,53.79]],[\"comment/234\",[]],[\"name/235\",[81,41.552]],[\"comment/235\",[]],[\"name/236\",[183,58.898]],[\"comment/236\",[]],[\"name/237\",[52,50.425]],[\"comment/237\",[]],[\"name/238\",[165,53.79]],[\"comment/238\",[]],[\"name/239\",[184,58.898]],[\"comment/239\",[]],[\"name/240\",[185,58.898]],[\"comment/240\",[]],[\"name/241\",[186,58.898]],[\"comment/241\",[]],[\"name/242\",[187,58.898]],[\"comment/242\",[]],[\"name/243\",[188,58.898]],[\"comment/243\",[]],[\"name/244\",[60,30.181]],[\"comment/244\",[]],[\"name/245\",[189,58.898]],[\"comment/245\",[]],[\"name/246\",[60,30.181]],[\"comment/246\",[]],[\"name/247\",[190,58.898]],[\"comment/247\",[]],[\"name/248\",[191,53.79]],[\"comment/248\",[]],[\"name/249\",[60,30.181]],[\"comment/249\",[]],[\"name/250\",[191,53.79]],[\"comment/250\",[]],[\"name/251\",[192,58.898]],[\"comment/251\",[]],[\"name/252\",[193,58.898]],[\"comment/252\",[]],[\"name/253\",[194,58.898]],[\"comment/253\",[]],[\"name/254\",[60,30.181]],[\"comment/254\",[]],[\"name/255\",[195,58.898]],[\"comment/255\",[]],[\"name/256\",[196,58.898]],[\"comment/256\",[]],[\"name/257\",[197,58.898]],[\"comment/257\",[]],[\"name/258\",[198,58.898]],[\"comment/258\",[]],[\"name/259\",[60,30.181]],[\"comment/259\",[]],[\"name/260\",[199,58.898]],[\"comment/260\",[]],[\"name/261\",[200,58.898]],[\"comment/261\",[]],[\"name/262\",[201,58.898]],[\"comment/262\",[]],[\"name/263\",[202,58.898]],[\"comment/263\",[]],[\"name/264\",[203,58.898]],[\"comment/264\",[]],[\"name/265\",[204,58.898]],[\"comment/265\",[]],[\"name/266\",[205,58.898]],[\"comment/266\",[]],[\"name/267\",[206,58.898]],[\"comment/267\",[]],[\"name/268\",[207,58.898]],[\"comment/268\",[]],[\"name/269\",[208,58.898]],[\"comment/269\",[]],[\"name/270\",[209,58.898]],[\"comment/270\",[]],[\"name/271\",[210,50.425]],[\"comment/271\",[]],[\"name/272\",[211,58.898]],[\"comment/272\",[]],[\"name/273\",[212,47.912]],[\"comment/273\",[]],[\"name/274\",[213,58.898]],[\"comment/274\",[]],[\"name/275\",[68,50.425]],[\"comment/275\",[]],[\"name/276\",[89,53.79]],[\"comment/276\",[]],[\"name/277\",[214,58.898]],[\"comment/277\",[]],[\"name/278\",[215,58.898]],[\"comment/278\",[]],[\"name/279\",[216,58.898]],[\"comment/279\",[]],[\"name/280\",[217,58.898]],[\"comment/280\",[]],[\"name/281\",[218,58.898]],[\"comment/281\",[]],[\"name/282\",[219,58.898]],[\"comment/282\",[]],[\"name/283\",[220,58.898]],[\"comment/283\",[]],[\"name/284\",[221,58.898]],[\"comment/284\",[]],[\"name/285\",[222,58.898]],[\"comment/285\",[]],[\"name/286\",[223,53.79]],[\"comment/286\",[]],[\"name/287\",[224,58.898]],[\"comment/287\",[]],[\"name/288\",[225,53.79]],[\"comment/288\",[]],[\"name/289\",[226,58.898]],[\"comment/289\",[]],[\"name/290\",[227,58.898]],[\"comment/290\",[]],[\"name/291\",[228,58.898]],[\"comment/291\",[]],[\"name/292\",[229,58.898]],[\"comment/292\",[]],[\"name/293\",[51,45.905]],[\"comment/293\",[]],[\"name/294\",[230,58.898]],[\"comment/294\",[]],[\"name/295\",[106,50.425]],[\"comment/295\",[]],[\"name/296\",[212,47.912]],[\"comment/296\",[]],[\"name/297\",[223,53.79]],[\"comment/297\",[]],[\"name/298\",[231,53.79]],[\"comment/298\",[]],[\"name/299\",[225,53.79]],[\"comment/299\",[]],[\"name/300\",[68,50.425]],[\"comment/300\",[]],[\"name/301\",[174,47.912]],[\"comment/301\",[]],[\"name/302\",[232,58.898]],[\"comment/302\",[]],[\"name/303\",[233,58.898]],[\"comment/303\",[]],[\"name/304\",[234,58.898]],[\"comment/304\",[]],[\"name/305\",[235,58.898]],[\"comment/305\",[]],[\"name/306\",[236,58.898]],[\"comment/306\",[]],[\"name/307\",[237,58.898]],[\"comment/307\",[]],[\"name/308\",[238,58.898]],[\"comment/308\",[]],[\"name/309\",[239,58.898]],[\"comment/309\",[]],[\"name/310\",[240,58.898]],[\"comment/310\",[]],[\"name/311\",[241,58.898]],[\"comment/311\",[]],[\"name/312\",[242,58.898]],[\"comment/312\",[]],[\"name/313\",[243,58.898]],[\"comment/313\",[]],[\"name/314\",[244,58.898]],[\"comment/314\",[]],[\"name/315\",[60,30.181]],[\"comment/315\",[]],[\"name/316\",[245,58.898]],[\"comment/316\",[]],[\"name/317\",[246,58.898]],[\"comment/317\",[]],[\"name/318\",[247,58.898]],[\"comment/318\",[]],[\"name/319\",[248,58.898]],[\"comment/319\",[]],[\"name/320\",[249,58.898]],[\"comment/320\",[]],[\"name/321\",[250,45.905]],[\"comment/321\",[]],[\"name/322\",[123,44.235]],[\"comment/322\",[]],[\"name/323\",[251,45.905]],[\"comment/323\",[]],[\"name/324\",[120,50.425]],[\"comment/324\",[]],[\"name/325\",[77,47.912]],[\"comment/325\",[]],[\"name/326\",[252,58.898]],[\"comment/326\",[]],[\"name/327\",[210,50.425]],[\"comment/327\",[]],[\"name/328\",[253,53.79]],[\"comment/328\",[]],[\"name/329\",[254,58.898]],[\"comment/329\",[]],[\"name/330\",[255,58.898]],[\"comment/330\",[]],[\"name/331\",[256,58.898]],[\"comment/331\",[]],[\"name/332\",[257,58.898]],[\"comment/332\",[]],[\"name/333\",[258,58.898]],[\"comment/333\",[]],[\"name/334\",[60,30.181]],[\"comment/334\",[]],[\"name/335\",[259,53.79]],[\"comment/335\",[]],[\"name/336\",[260,53.79]],[\"comment/336\",[]],[\"name/337\",[261,53.79]],[\"comment/337\",[]],[\"name/338\",[262,58.898]],[\"comment/338\",[]],[\"name/339\",[60,30.181]],[\"comment/339\",[]],[\"name/340\",[259,53.79]],[\"comment/340\",[]],[\"name/341\",[263,58.898]],[\"comment/341\",[]],[\"name/342\",[260,53.79]],[\"comment/342\",[]],[\"name/343\",[264,58.898]],[\"comment/343\",[]],[\"name/344\",[261,53.79]],[\"comment/344\",[]],[\"name/345\",[265,58.898]],[\"comment/345\",[]],[\"name/346\",[266,58.898]],[\"comment/346\",[]],[\"name/347\",[267,53.79]],[\"comment/347\",[]],[\"name/348\",[268,58.898]],[\"comment/348\",[]],[\"name/349\",[269,58.898]],[\"comment/349\",[]],[\"name/350\",[270,58.898]],[\"comment/350\",[]],[\"name/351\",[271,58.898]],[\"comment/351\",[]],[\"name/352\",[60,30.181]],[\"comment/352\",[]],[\"name/353\",[272,58.898]],[\"comment/353\",[]],[\"name/354\",[273,58.898]],[\"comment/354\",[]],[\"name/355\",[274,53.79]],[\"comment/355\",[]],[\"name/356\",[81,41.552]],[\"comment/356\",[]],[\"name/357\",[275,58.898]],[\"comment/357\",[]],[\"name/358\",[276,58.898]],[\"comment/358\",[]],[\"name/359\",[174,47.912]],[\"comment/359\",[]],[\"name/360\",[75,50.425]],[\"comment/360\",[]],[\"name/361\",[76,50.425]],[\"comment/361\",[]],[\"name/362\",[277,58.898]],[\"comment/362\",[]],[\"name/363\",[278,58.898]],[\"comment/363\",[]],[\"name/364\",[279,58.898]],[\"comment/364\",[]],[\"name/365\",[280,58.898]],[\"comment/365\",[]],[\"name/366\",[281,58.898]],[\"comment/366\",[]],[\"name/367\",[282,58.898]],[\"comment/367\",[]],[\"name/368\",[283,58.898]],[\"comment/368\",[]],[\"name/369\",[284,58.898]],[\"comment/369\",[]],[\"name/370\",[285,58.898]],[\"comment/370\",[]],[\"name/371\",[286,58.898]],[\"comment/371\",[]],[\"name/372\",[287,58.898]],[\"comment/372\",[]],[\"name/373\",[210,50.425]],[\"comment/373\",[]],[\"name/374\",[288,58.898]],[\"comment/374\",[]],[\"name/375\",[289,58.898]],[\"comment/375\",[]],[\"name/376\",[290,58.898]],[\"comment/376\",[]],[\"name/377\",[291,58.898]],[\"comment/377\",[]],[\"name/378\",[292,58.898]],[\"comment/378\",[]],[\"name/379\",[293,58.898]],[\"comment/379\",[]],[\"name/380\",[294,58.898]],[\"comment/380\",[]],[\"name/381\",[51,45.905]],[\"comment/381\",[]],[\"name/382\",[295,53.79]],[\"comment/382\",[]],[\"name/383\",[296,47.912]],[\"comment/383\",[]],[\"name/384\",[297,45.905]],[\"comment/384\",[]],[\"name/385\",[298,50.425]],[\"comment/385\",[]],[\"name/386\",[150,45.905]],[\"comment/386\",[]],[\"name/387\",[299,58.898]],[\"comment/387\",[]],[\"name/388\",[300,58.898]],[\"comment/388\",[]],[\"name/389\",[301,58.898]],[\"comment/389\",[]],[\"name/390\",[54,53.79]],[\"comment/390\",[]],[\"name/391\",[302,58.898]],[\"comment/391\",[]],[\"name/392\",[250,45.905]],[\"comment/392\",[]],[\"name/393\",[123,44.235]],[\"comment/393\",[]],[\"name/394\",[81,41.552]],[\"comment/394\",[]],[\"name/395\",[303,58.898]],[\"comment/395\",[]],[\"name/396\",[304,53.79]],[\"comment/396\",[]],[\"name/397\",[305,53.79]],[\"comment/397\",[]],[\"name/398\",[306,53.79]],[\"comment/398\",[]],[\"name/399\",[307,47.912]],[\"comment/399\",[]],[\"name/400\",[308,58.898]],[\"comment/400\",[]],[\"name/401\",[267,53.79]],[\"comment/401\",[]],[\"name/402\",[251,45.905]],[\"comment/402\",[]],[\"name/403\",[309,58.898]],[\"comment/403\",[]],[\"name/404\",[310,58.898]],[\"comment/404\",[]],[\"name/405\",[212,47.912]],[\"comment/405\",[]],[\"name/406\",[51,45.905]],[\"comment/406\",[]],[\"name/407\",[106,50.425]],[\"comment/407\",[]],[\"name/408\",[77,47.912]],[\"comment/408\",[]],[\"name/409\",[311,58.898]],[\"comment/409\",[]],[\"name/410\",[312,58.898]],[\"comment/410\",[]],[\"name/411\",[250,45.905]],[\"comment/411\",[]],[\"name/412\",[120,50.425]],[\"comment/412\",[]],[\"name/413\",[123,44.235]],[\"comment/413\",[]],[\"name/414\",[251,45.905]],[\"comment/414\",[]],[\"name/415\",[81,41.552]],[\"comment/415\",[]],[\"name/416\",[253,53.79]],[\"comment/416\",[]],[\"name/417\",[82,45.905]],[\"comment/417\",[]],[\"name/418\",[174,47.912]],[\"comment/418\",[]],[\"name/419\",[125,53.79]],[\"comment/419\",[]],[\"name/420\",[84,53.79]],[\"comment/420\",[]],[\"name/421\",[126,53.79]],[\"comment/421\",[]],[\"name/422\",[313,58.898]],[\"comment/422\",[]],[\"name/423\",[314,58.898]],[\"comment/423\",[]],[\"name/424\",[128,53.79]],[\"comment/424\",[]],[\"name/425\",[129,53.79]],[\"comment/425\",[]],[\"name/426\",[130,50.425]],[\"comment/426\",[]],[\"name/427\",[131,50.425]],[\"comment/427\",[]],[\"name/428\",[132,53.79]],[\"comment/428\",[]],[\"name/429\",[133,53.79]],[\"comment/429\",[]],[\"name/430\",[134,53.79]],[\"comment/430\",[]],[\"name/431\",[105,53.79]],[\"comment/431\",[]],[\"name/432\",[315,58.898]],[\"comment/432\",[]],[\"name/433\",[316,53.79]],[\"comment/433\",[]],[\"name/434\",[149,47.912]],[\"comment/434\",[]],[\"name/435\",[104,34.919]],[\"comment/435\",[]],[\"name/436\",[116,44.235]],[\"comment/436\",[]],[\"name/437\",[307,47.912]],[\"comment/437\",[]],[\"name/438\",[317,58.898]],[\"comment/438\",[]],[\"name/439\",[316,53.79]],[\"comment/439\",[]],[\"name/440\",[149,47.912]],[\"comment/440\",[]],[\"name/441\",[104,34.919]],[\"comment/441\",[]],[\"name/442\",[116,44.235]],[\"comment/442\",[]],[\"name/443\",[307,47.912]],[\"comment/443\",[]],[\"name/444\",[146,50.425]],[\"comment/444\",[]],[\"name/445\",[104,34.919]],[\"comment/445\",[]],[\"name/446\",[318,53.79]],[\"comment/446\",[]],[\"name/447\",[319,53.79]],[\"comment/447\",[]],[\"name/448\",[320,58.898]],[\"comment/448\",[]],[\"name/449\",[321,58.898]],[\"comment/449\",[]],[\"name/450\",[322,58.898]],[\"comment/450\",[]],[\"name/451\",[323,58.898]],[\"comment/451\",[]],[\"name/452\",[324,58.898]],[\"comment/452\",[]],[\"name/453\",[325,58.898]],[\"comment/453\",[]],[\"name/454\",[326,58.898]],[\"comment/454\",[]],[\"name/455\",[168,53.79]],[\"comment/455\",[]],[\"name/456\",[137,53.79]],[\"comment/456\",[]],[\"name/457\",[136,47.912]],[\"comment/457\",[]],[\"name/458\",[138,53.79]],[\"comment/458\",[]],[\"name/459\",[139,53.79]],[\"comment/459\",[]],[\"name/460\",[121,50.425]],[\"comment/460\",[]],[\"name/461\",[140,53.79]],[\"comment/461\",[]],[\"name/462\",[141,53.79]],[\"comment/462\",[]],[\"name/463\",[142,53.79]],[\"comment/463\",[]],[\"name/464\",[297,45.905]],[\"comment/464\",[]],[\"name/465\",[296,47.912]],[\"comment/465\",[]],[\"name/466\",[327,58.898]],[\"comment/466\",[]],[\"name/467\",[328,58.898]],[\"comment/467\",[]],[\"name/468\",[329,58.898]],[\"comment/468\",[]],[\"name/469\",[169,53.79]],[\"comment/469\",[]],[\"name/470\",[116,44.235]],[\"comment/470\",[]],[\"name/471\",[330,58.898]],[\"comment/471\",[]],[\"name/472\",[331,58.898]],[\"comment/472\",[]],[\"name/473\",[332,58.898]],[\"comment/473\",[]],[\"name/474\",[333,58.898]],[\"comment/474\",[]],[\"name/475\",[334,58.898]],[\"comment/475\",[]],[\"name/476\",[296,47.912]],[\"comment/476\",[]],[\"name/477\",[170,53.79]],[\"comment/477\",[]],[\"name/478\",[335,58.898]],[\"comment/478\",[]],[\"name/479\",[336,58.898]],[\"comment/479\",[]],[\"name/480\",[117,53.79]],[\"comment/480\",[]],[\"name/481\",[337,58.898]],[\"comment/481\",[]],[\"name/482\",[338,58.898]],[\"comment/482\",[]],[\"name/483\",[339,58.898]],[\"comment/483\",[]],[\"name/484\",[340,58.898]],[\"comment/484\",[]],[\"name/485\",[341,58.898]],[\"comment/485\",[]],[\"name/486\",[123,44.235]],[\"comment/486\",[]],[\"name/487\",[342,53.79]],[\"comment/487\",[]],[\"name/488\",[231,53.79]],[\"comment/488\",[]],[\"name/489\",[171,53.79]],[\"comment/489\",[]],[\"name/490\",[295,53.79]],[\"comment/490\",[]],[\"name/491\",[212,47.912]],[\"comment/491\",[]],[\"name/492\",[297,45.905]],[\"comment/492\",[]],[\"name/493\",[298,50.425]],[\"comment/493\",[]],[\"name/494\",[150,45.905]],[\"comment/494\",[]],[\"name/495\",[250,45.905]],[\"comment/495\",[]],[\"name/496\",[343,58.898]],[\"comment/496\",[]],[\"name/497\",[342,53.79]],[\"comment/497\",[]],[\"name/498\",[344,58.898]],[\"comment/498\",[]],[\"name/499\",[345,58.898]],[\"comment/499\",[]],[\"name/500\",[164,53.79]],[\"comment/500\",[]],[\"name/501\",[346,58.898]],[\"comment/501\",[]],[\"name/502\",[150,45.905]],[\"comment/502\",[]],[\"name/503\",[149,47.912]],[\"comment/503\",[]],[\"name/504\",[297,45.905]],[\"comment/504\",[]],[\"name/505\",[319,53.79]],[\"comment/505\",[]],[\"name/506\",[318,53.79]],[\"comment/506\",[]],[\"name/507\",[347,58.898]],[\"comment/507\",[]],[\"name/508\",[348,58.898]],[\"comment/508\",[]],[\"name/509\",[349,58.898]],[\"comment/509\",[]],[\"name/510\",[350,58.898]],[\"comment/510\",[]],[\"name/511\",[274,53.79]],[\"comment/511\",[]],[\"name/512\",[351,58.898]],[\"comment/512\",[]],[\"name/513\",[352,58.898]],[\"comment/513\",[]],[\"name/514\",[353,58.898]],[\"comment/514\",[]],[\"name/515\",[354,58.898]],[\"comment/515\",[]],[\"name/516\",[150,45.905]],[\"comment/516\",[]],[\"name/517\",[297,45.905]],[\"comment/517\",[]],[\"name/518\",[296,47.912]],[\"comment/518\",[]],[\"name/519\",[51,45.905]],[\"comment/519\",[]],[\"name/520\",[304,53.79]],[\"comment/520\",[]],[\"name/521\",[305,53.79]],[\"comment/521\",[]],[\"name/522\",[306,53.79]],[\"comment/522\",[]],[\"name/523\",[81,41.552]],[\"comment/523\",[]],[\"name/524\",[355,58.898]],[\"comment/524\",[]],[\"name/525\",[250,45.905]],[\"comment/525\",[]],[\"name/526\",[123,44.235]],[\"comment/526\",[]],[\"name/527\",[251,45.905]],[\"comment/527\",[]],[\"name/528\",[251,45.905]],[\"comment/528\",[]],[\"name/529\",[75,50.425]],[\"comment/529\",[]],[\"name/530\",[76,50.425]],[\"comment/530\",[]],[\"name/531\",[356,58.898]],[\"comment/531\",[]],[\"name/532\",[357,58.898]],[\"comment/532\",[]],[\"name/533\",[358,58.898]],[\"comment/533\",[]],[\"name/534\",[359,58.898]],[\"comment/534\",[]],[\"name/535\",[360,58.898]],[\"comment/535\",[]],[\"name/536\",[361,58.898]],[\"comment/536\",[]],[\"name/537\",[362,58.898]],[\"comment/537\",[]],[\"name/538\",[363,58.898]],[\"comment/538\",[]],[\"name/539\",[307,47.912]],[\"comment/539\",[]],[\"name/540\",[298,50.425]],[\"comment/540\",[]]],\"invertedIndex\":[[\"__type\",{\"_index\":60,\"name\":{\"60\":{},\"66\":{},\"76\":{},\"83\":{},\"94\":{},\"102\":{},\"111\":{},\"121\":{},\"128\":{},\"152\":{},\"177\":{},\"180\":{},\"183\":{},\"185\":{},\"187\":{},\"190\":{},\"194\":{},\"244\":{},\"246\":{},\"249\":{},\"254\":{},\"259\":{},\"315\":{},\"334\":{},\"339\":{},\"352\":{}},\"comment\":{}}],[\"activeseries\",{\"_index\":89,\"name\":{\"92\":{},\"276\":{}},\"comment\":{}}],[\"ad\",{\"_index\":209,\"name\":{\"270\":{}},\"comment\":{}}],[\"adhocmargin\",{\"_index\":95,\"name\":{\"99\":{}},\"comment\":{}}],[\"advance\",{\"_index\":112,\"name\":{\"120\":{}},\"comment\":{}}],[\"advances\",{\"_index\":114,\"name\":{\"123\":{},\"230\":{}},\"comment\":{}}],[\"adx\",{\"_index\":203,\"name\":{\"264\":{}},\"comment\":{}}],[\"all_indices\",{\"_index\":6,\"name\":{\"6\":{}},\"comment\":{}}],[\"allindicesdata\",{\"_index\":175,\"name\":{\"215\":{}},\"comment\":{}}],[\"apilist\",{\"_index\":0,\"name\":{\"0\":{}},\"comment\":{}}],[\"applicablemargin\",{\"_index\":96,\"name\":{\"100\":{}},\"comment\":{}}],[\"ask\",{\"_index\":79,\"name\":{\"81\":{}},\"comment\":{}}],[\"askprice\",{\"_index\":359,\"name\":{\"534\":{}},\"comment\":{}}],[\"askqty\",{\"_index\":358,\"name\":{\"533\":{}},\"comment\":{}}],[\"ato\",{\"_index\":271,\"name\":{\"351\":{}},\"comment\":{}}],[\"atobuyqty\",{\"_index\":277,\"name\":{\"362\":{}},\"comment\":{}}],[\"atosellqty\",{\"_index\":278,\"name\":{\"363\":{}},\"comment\":{}}],[\"atr\",{\"_index\":202,\"name\":{\"263\":{}},\"comment\":{}}],[\"baseprice\",{\"_index\":257,\"name\":{\"332\":{}},\"comment\":{}}],[\"basicindustry\",{\"_index\":69,\"name\":{\"70\":{}},\"comment\":{}}],[\"bid\",{\"_index\":78,\"name\":{\"80\":{}},\"comment\":{}}],[\"bidprice\",{\"_index\":357,\"name\":{\"532\":{}},\"comment\":{}}],[\"bidqty\",{\"_index\":356,\"name\":{\"531\":{}},\"comment\":{}}],[\"boardstatus\",{\"_index\":237,\"name\":{\"307\":{}},\"comment\":{}}],[\"body\",{\"_index\":159,\"name\":{\"196\":{}},\"comment\":{}}],[\"bollingerbands\",{\"_index\":194,\"name\":{\"253\":{}},\"comment\":{}}],[\"borad_meeting\",{\"_index\":156,\"name\":{\"189\":{}},\"comment\":{}}],[\"bulkblockdeals\",{\"_index\":73,\"name\":{\"74\":{}},\"comment\":{}}],[\"buy\",{\"_index\":272,\"name\":{\"353\":{}},\"comment\":{}}],[\"buyprice1\",{\"_index\":360,\"name\":{\"535\":{}},\"comment\":{}}],[\"buyqty\",{\"_index\":349,\"name\":{\"509\":{}},\"comment\":{}}],[\"buyquantity1\",{\"_index\":361,\"name\":{\"536\":{}},\"comment\":{}}],[\"category\",{\"_index\":184,\"name\":{\"239\":{}},\"comment\":{}}],[\"cci\",{\"_index\":205,\"name\":{\"266\":{}},\"comment\":{}}],[\"ce\",{\"_index\":318,\"name\":{\"446\":{},\"506\":{}},\"comment\":{}}],[\"ch52weekhighprice\",{\"_index\":291,\"name\":{\"377\":{}},\"comment\":{}}],[\"ch52weeklowprice\",{\"_index\":292,\"name\":{\"378\":{}},\"comment\":{}}],[\"change\",{\"_index\":123,\"name\":{\"136\":{},\"322\":{},\"393\":{},\"413\":{},\"486\":{},\"526\":{}},\"comment\":{}}],[\"changed\",{\"_index\":166,\"name\":{\"203\":{}},\"comment\":{}}],[\"changeinopeninterest\",{\"_index\":305,\"name\":{\"397\":{},\"521\":{}},\"comment\":{}}],[\"chart30dpath\",{\"_index\":133,\"name\":{\"146\":{},\"429\":{}},\"comment\":{}}],[\"chart365dpath\",{\"_index\":134,\"name\":{\"147\":{},\"430\":{}},\"comment\":{}}],[\"charttodaypath\",{\"_index\":132,\"name\":{\"145\":{},\"428\":{}},\"comment\":{}}],[\"chclosingprice\",{\"_index\":287,\"name\":{\"372\":{}},\"comment\":{}}],[\"checkinav\",{\"_index\":266,\"name\":{\"346\":{}},\"comment\":{}}],[\"chlasttradedprice\",{\"_index\":286,\"name\":{\"371\":{}},\"comment\":{}}],[\"chopeningprice\",{\"_index\":283,\"name\":{\"368\":{}},\"comment\":{}}],[\"chpreviousclsprice\",{\"_index\":282,\"name\":{\"367\":{}},\"comment\":{}}],[\"chseries\",{\"_index\":281,\"name\":{\"366\":{}},\"comment\":{}}],[\"chsymbol\",{\"_index\":280,\"name\":{\"365\":{}},\"comment\":{}}],[\"chtotaltrades\",{\"_index\":290,\"name\":{\"376\":{}},\"comment\":{}}],[\"chtottradedqty\",{\"_index\":288,\"name\":{\"374\":{}},\"comment\":{}}],[\"chtottradedval\",{\"_index\":289,\"name\":{\"375\":{}},\"comment\":{}}],[\"chtradehighprice\",{\"_index\":284,\"name\":{\"369\":{}},\"comment\":{}}],[\"chtradelowprice\",{\"_index\":285,\"name\":{\"370\":{}},\"comment\":{}}],[\"circulars\",{\"_index\":8,\"name\":{\"8\":{}},\"comment\":{}}],[\"circularsdata\",{\"_index\":179,\"name\":{\"220\":{}},\"comment\":{}}],[\"classofshare\",{\"_index\":242,\"name\":{\"312\":{}},\"comment\":{}}],[\"close\",{\"_index\":252,\"name\":{\"326\":{}},\"comment\":{}}],[\"closeprice\",{\"_index\":54,\"name\":{\"54\":{},\"390\":{}},\"comment\":{}}],[\"closingvalue\",{\"_index\":340,\"name\":{\"484\":{}},\"comment\":{}}],[\"cmannualvolatility\",{\"_index\":87,\"name\":{\"90\":{}},\"comment\":{}}],[\"cmdailyvolatility\",{\"_index\":86,\"name\":{\"89\":{}},\"comment\":{}}],[\"commodityoptionchaindata\",{\"_index\":147,\"name\":{\"169\":{}},\"comment\":{}}],[\"commodityrecords\",{\"_index\":317,\"name\":{\"438\":{}},\"comment\":{}}],[\"companyname\",{\"_index\":213,\"name\":{\"274\":{}},\"comment\":{}}],[\"constructor\",{\"_index\":16,\"name\":{\"16\":{}},\"comment\":{}}],[\"content\",{\"_index\":157,\"name\":{\"193\":{}},\"comment\":{}}],[\"contractstraded\",{\"_index\":344,\"name\":{\"498\":{}},\"comment\":{}}],[\"corporate_actions\",{\"_index\":153,\"name\":{\"179\":{}},\"comment\":{}}],[\"currentmarkettype\",{\"_index\":63,\"name\":{\"63\":{}},\"comment\":{}}],[\"d\",{\"_index\":200,\"name\":{\"261\":{}},\"comment\":{}}],[\"data\",{\"_index\":104,\"name\":{\"109\":{},\"117\":{},\"126\":{},\"164\":{},\"178\":{},\"181\":{},\"184\":{},\"188\":{},\"191\":{},\"216\":{},\"221\":{},\"225\":{},\"228\":{},\"435\":{},\"441\":{},\"445\":{}},\"comment\":{}}],[\"date30dago\",{\"_index\":131,\"name\":{\"144\":{},\"161\":{},\"427\":{}},\"comment\":{}}],[\"date365dago\",{\"_index\":130,\"name\":{\"143\":{},\"162\":{},\"426\":{}},\"comment\":{}}],[\"daterange\",{\"_index\":47,\"name\":{\"47\":{}},\"comment\":{}}],[\"datetime\",{\"_index\":335,\"name\":{\"478\":{}},\"comment\":{}}],[\"datum\",{\"_index\":346,\"name\":{\"501\":{}},\"comment\":{}}],[\"daychange\",{\"_index\":343,\"name\":{\"496\":{}},\"comment\":{}}],[\"dayhigh\",{\"_index\":311,\"name\":{\"409\":{}},\"comment\":{}}],[\"daylow\",{\"_index\":312,\"name\":{\"410\":{}},\"comment\":{}}],[\"debtseries\",{\"_index\":214,\"name\":{\"277\":{}},\"comment\":{}}],[\"declines\",{\"_index\":113,\"name\":{\"122\":{},\"231\":{}},\"comment\":{}}],[\"deliveryquantity\",{\"_index\":99,\"name\":{\"104\":{}},\"comment\":{}}],[\"deliverytotradedquantity\",{\"_index\":100,\"name\":{\"105\":{}},\"comment\":{}}],[\"derivatives\",{\"_index\":243,\"name\":{\"313\":{}},\"comment\":{}}],[\"desc\",{\"_index\":246,\"name\":{\"317\":{}},\"comment\":{}}],[\"description\",{\"_index\":323,\"name\":{\"451\":{}},\"comment\":{}}],[\"ema\",{\"_index\":189,\"name\":{\"245\":{}},\"comment\":{}}],[\"end\",{\"_index\":49,\"name\":{\"49\":{}},\"comment\":{}}],[\"equity_master\",{\"_index\":10,\"name\":{\"10\":{}},\"comment\":{}}],[\"equitycorporateinfo\",{\"_index\":151,\"name\":{\"175\":{}},\"comment\":{}}],[\"equitydetails\",{\"_index\":55,\"name\":{\"55\":{}},\"comment\":{}}],[\"equityhistoricaldata\",{\"_index\":103,\"name\":{\"108\":{}},\"comment\":{}}],[\"equityhistoricalinfo\",{\"_index\":279,\"name\":{\"364\":{}},\"comment\":{}}],[\"equityinfo\",{\"_index\":211,\"name\":{\"272\":{}},\"comment\":{}}],[\"equitymaster\",{\"_index\":181,\"name\":{\"226\":{}},\"comment\":{}}],[\"equitymetadata\",{\"_index\":230,\"name\":{\"294\":{}},\"comment\":{}}],[\"equityoptionchaindata\",{\"_index\":143,\"name\":{\"163\":{}},\"comment\":{}}],[\"equityoptionchainitem\",{\"_index\":294,\"name\":{\"380\":{}},\"comment\":{}}],[\"equitypreopenmarket\",{\"_index\":269,\"name\":{\"349\":{}},\"comment\":{}}],[\"equitypriceinfo\",{\"_index\":249,\"name\":{\"320\":{}},\"comment\":{}}],[\"equitysecurityinfo\",{\"_index\":236,\"name\":{\"306\":{}},\"comment\":{}}],[\"equitytradeinfo\",{\"_index\":71,\"name\":{\"72\":{}},\"comment\":{}}],[\"evening_session\",{\"_index\":325,\"name\":{\"453\":{}},\"comment\":{}}],[\"expirydate\",{\"_index\":297,\"name\":{\"384\":{},\"464\":{},\"492\":{},\"504\":{},\"517\":{}},\"comment\":{}}],[\"expirydates\",{\"_index\":149,\"name\":{\"173\":{},\"434\":{},\"440\":{},\"503\":{}},\"comment\":{}}],[\"extremelossmargin\",{\"_index\":94,\"name\":{\"98\":{}},\"comment\":{}}],[\"facevalue\",{\"_index\":247,\"name\":{\"318\":{}},\"comment\":{}}],[\"ffmc\",{\"_index\":84,\"name\":{\"87\":{},\"420\":{}},\"comment\":{}}],[\"ffmc_sum\",{\"_index\":135,\"name\":{\"150\":{}},\"comment\":{}}],[\"field_glossary_items\",{\"_index\":160,\"name\":{\"197\":{}},\"comment\":{}}],[\"field_labels\",{\"_index\":161,\"name\":{\"198\":{}},\"comment\":{}}],[\"field_reference\",{\"_index\":162,\"name\":{\"199\":{}},\"comment\":{}}],[\"field_unique_url\",{\"_index\":163,\"name\":{\"200\":{}},\"comment\":{}}],[\"filtered\",{\"_index\":146,\"name\":{\"168\":{},\"171\":{},\"444\":{}},\"comment\":{}}],[\"finalclosingvalue\",{\"_index\":341,\"name\":{\"485\":{}},\"comment\":{}}],[\"finalprice\",{\"_index\":275,\"name\":{\"357\":{}},\"comment\":{}}],[\"finalquantity\",{\"_index\":276,\"name\":{\"358\":{}},\"comment\":{}}],[\"financial_results\",{\"_index\":155,\"name\":{\"186\":{}},\"comment\":{}}],[\"fromdate\",{\"_index\":107,\"name\":{\"113\":{},\"222\":{}},\"comment\":{}}],[\"getallindices\",{\"_index\":37,\"name\":{\"37\":{}},\"comment\":{}}],[\"getallstocksymbols\",{\"_index\":19,\"name\":{\"19\":{}},\"comment\":{}}],[\"getcirculars\",{\"_index\":39,\"name\":{\"39\":{}},\"comment\":{}}],[\"getclearingholidays\",{\"_index\":34,\"name\":{\"34\":{}},\"comment\":{}}],[\"getcommodityoptionchain\",{\"_index\":31,\"name\":{\"31\":{}},\"comment\":{}}],[\"getdata\",{\"_index\":17,\"name\":{\"17\":{}},\"comment\":{}}],[\"getdatabyendpoint\",{\"_index\":18,\"name\":{\"18\":{}},\"comment\":{}}],[\"getequitycorporateinfo\",{\"_index\":22,\"name\":{\"22\":{}},\"comment\":{}}],[\"getequitydetails\",{\"_index\":20,\"name\":{\"20\":{}},\"comment\":{}}],[\"getequityhistoricaldata\",{\"_index\":24,\"name\":{\"24\":{}},\"comment\":{}}],[\"getequityintradaydata\",{\"_index\":23,\"name\":{\"23\":{}},\"comment\":{}}],[\"getequitymaster\",{\"_index\":41,\"name\":{\"41\":{}},\"comment\":{}}],[\"getequityoptionchain\",{\"_index\":30,\"name\":{\"30\":{}},\"comment\":{}}],[\"getequityseries\",{\"_index\":25,\"name\":{\"25\":{}},\"comment\":{}}],[\"getequitystockindices\",{\"_index\":26,\"name\":{\"26\":{}},\"comment\":{}}],[\"getequitytradeinfo\",{\"_index\":21,\"name\":{\"21\":{}},\"comment\":{}}],[\"getglossary\",{\"_index\":32,\"name\":{\"32\":{}},\"comment\":{}}],[\"getindexintradaydata\",{\"_index\":27,\"name\":{\"27\":{}},\"comment\":{}}],[\"getindexnames\",{\"_index\":38,\"name\":{\"38\":{}},\"comment\":{}}],[\"getindexoptionchain\",{\"_index\":29,\"name\":{\"29\":{}},\"comment\":{}}],[\"getindexoptionchaincontractinfo\",{\"_index\":28,\"name\":{\"28\":{}},\"comment\":{}}],[\"getlatestcirculars\",{\"_index\":40,\"name\":{\"40\":{}},\"comment\":{}}],[\"getmarketstatus\",{\"_index\":35,\"name\":{\"35\":{}},\"comment\":{}}],[\"getmarketturnover\",{\"_index\":36,\"name\":{\"36\":{}},\"comment\":{}}],[\"getmergeddailyreportscapital\",{\"_index\":43,\"name\":{\"43\":{}},\"comment\":{}}],[\"getmergeddailyreportsdebt\",{\"_index\":45,\"name\":{\"45\":{}},\"comment\":{}}],[\"getmergeddailyreportsderivatives\",{\"_index\":44,\"name\":{\"44\":{}},\"comment\":{}}],[\"getpreopenmarketdata\",{\"_index\":42,\"name\":{\"42\":{}},\"comment\":{}}],[\"gettechnicalindicators\",{\"_index\":46,\"name\":{\"46\":{}},\"comment\":{}}],[\"gettradingholidays\",{\"_index\":33,\"name\":{\"33\":{}},\"comment\":{}}],[\"giftnifty\",{\"_index\":171,\"name\":{\"209\":{},\"489\":{}},\"comment\":{}}],[\"glossary\",{\"_index\":1,\"name\":{\"1\":{},\"192\":{}},\"comment\":{}}],[\"grapthdata\",{\"_index\":53,\"name\":{\"53\":{}},\"comment\":{}}],[\"high\",{\"_index\":118,\"name\":{\"131\":{}},\"comment\":{}}],[\"highprice\",{\"_index\":300,\"name\":{\"388\":{}},\"comment\":{}}],[\"histogram\",{\"_index\":193,\"name\":{\"252\":{}},\"comment\":{}}],[\"holiday\",{\"_index\":320,\"name\":{\"448\":{}},\"comment\":{}}],[\"holiday_clearing\",{\"_index\":3,\"name\":{\"3\":{}},\"comment\":{}}],[\"holiday_trading\",{\"_index\":2,\"name\":{\"2\":{}},\"comment\":{}}],[\"holidaysbysegment\",{\"_index\":167,\"name\":{\"204\":{}},\"comment\":{}}],[\"id\",{\"_index\":164,\"name\":{\"201\":{},\"500\":{}},\"comment\":{}}],[\"identifier\",{\"_index\":51,\"name\":{\"51\":{},\"293\":{},\"381\":{},\"406\":{},\"519\":{}},\"comment\":{}}],[\"iep\",{\"_index\":274,\"name\":{\"355\":{},\"511\":{}},\"comment\":{}}],[\"ieq\",{\"_index\":268,\"name\":{\"348\":{}},\"comment\":{}}],[\"impactcost\",{\"_index\":85,\"name\":{\"88\":{}},\"comment\":{}}],[\"impliedvolatility\",{\"_index\":355,\"name\":{\"524\":{}},\"comment\":{}}],[\"inavvalue\",{\"_index\":265,\"name\":{\"345\":{}},\"comment\":{}}],[\"index\",{\"_index\":139,\"name\":{\"156\":{},\"459\":{}},\"comment\":{}}],[\"index_names\",{\"_index\":7,\"name\":{\"7\":{}},\"comment\":{}}],[\"indexdetails\",{\"_index\":111,\"name\":{\"118\":{}},\"comment\":{}}],[\"indexequityinfo\",{\"_index\":309,\"name\":{\"403\":{}},\"comment\":{}}],[\"indexlast\",{\"_index\":337,\"name\":{\"481\":{}},\"comment\":{}}],[\"indexname\",{\"_index\":117,\"name\":{\"129\":{},\"480\":{}},\"comment\":{}}],[\"indexnamesdata\",{\"_index\":176,\"name\":{\"217\":{}},\"comment\":{}}],[\"indexoptionchaindata\",{\"_index\":144,\"name\":{\"166\":{}},\"comment\":{}}],[\"indexpercchange\",{\"_index\":338,\"name\":{\"482\":{}},\"comment\":{}}],[\"indexrecords\",{\"_index\":315,\"name\":{\"432\":{}},\"comment\":{}}],[\"indextimeval\",{\"_index\":339,\"name\":{\"483\":{}},\"comment\":{}}],[\"indexvar\",{\"_index\":92,\"name\":{\"96\":{}},\"comment\":{}}],[\"indicativeclose\",{\"_index\":127,\"name\":{\"140\":{}},\"comment\":{}}],[\"indicativenifty50\",{\"_index\":170,\"name\":{\"208\":{},\"477\":{}},\"comment\":{}}],[\"indicativetime\",{\"_index\":336,\"name\":{\"479\":{}},\"comment\":{}}],[\"industry\",{\"_index\":68,\"name\":{\"69\":{},\"275\":{},\"300\":{}},\"comment\":{}}],[\"industryinfo\",{\"_index\":65,\"name\":{\"65\":{}},\"comment\":{}}],[\"info\",{\"_index\":56,\"name\":{\"56\":{}},\"comment\":{}}],[\"instrumenttype\",{\"_index\":295,\"name\":{\"382\":{},\"490\":{}},\"comment\":{}}],[\"intradaydata\",{\"_index\":50,\"name\":{\"50\":{}},\"comment\":{}}],[\"intradayhighlow\",{\"_index\":258,\"name\":{\"333\":{}},\"comment\":{}}],[\"iscasec\",{\"_index\":217,\"name\":{\"280\":{}},\"comment\":{}}],[\"isdebtsec\",{\"_index\":219,\"name\":{\"282\":{}},\"comment\":{}}],[\"isdelisted\",{\"_index\":222,\"name\":{\"285\":{}},\"comment\":{}}],[\"isetfsec\",{\"_index\":221,\"name\":{\"284\":{}},\"comment\":{}}],[\"isfnosec\",{\"_index\":216,\"name\":{\"279\":{}},\"comment\":{}}],[\"ishybridsymbol\",{\"_index\":227,\"name\":{\"290\":{}},\"comment\":{}}],[\"isin\",{\"_index\":223,\"name\":{\"286\":{},\"297\":{}},\"comment\":{}}],[\"ismunicipalbond\",{\"_index\":226,\"name\":{\"289\":{}},\"comment\":{}}],[\"isslbsec\",{\"_index\":218,\"name\":{\"281\":{}},\"comment\":{}}],[\"issuedsize\",{\"_index\":248,\"name\":{\"319\":{}},\"comment\":{}}],[\"issuspended\",{\"_index\":220,\"name\":{\"283\":{}},\"comment\":{}}],[\"istop10\",{\"_index\":229,\"name\":{\"292\":{}},\"comment\":{}}],[\"k\",{\"_index\":199,\"name\":{\"260\":{}},\"comment\":{}}],[\"last\",{\"_index\":121,\"name\":{\"134\":{},\"157\":{},\"460\":{}},\"comment\":{}}],[\"lastprice\",{\"_index\":250,\"name\":{\"321\":{},\"392\":{},\"411\":{},\"495\":{},\"525\":{}},\"comment\":{}}],[\"lastupdatetime\",{\"_index\":174,\"name\":{\"214\":{},\"301\":{},\"359\":{},\"418\":{}},\"comment\":{}}],[\"latest_announcements\",{\"_index\":152,\"name\":{\"176\":{}},\"comment\":{}}],[\"latest_circulars\",{\"_index\":9,\"name\":{\"9\":{}},\"comment\":{}}],[\"latestcirculardata\",{\"_index\":180,\"name\":{\"224\":{}},\"comment\":{}}],[\"link\",{\"_index\":186,\"name\":{\"241\":{}},\"comment\":{}}],[\"listingdate\",{\"_index\":225,\"name\":{\"288\":{},\"299\":{}},\"comment\":{}}],[\"low\",{\"_index\":119,\"name\":{\"132\":{}},\"comment\":{}}],[\"lower\",{\"_index\":197,\"name\":{\"257\":{}},\"comment\":{}}],[\"lowercp\",{\"_index\":254,\"name\":{\"329\":{}},\"comment\":{}}],[\"lowprice\",{\"_index\":301,\"name\":{\"389\":{}},\"comment\":{}}],[\"macd\",{\"_index\":191,\"name\":{\"248\":{},\"250\":{}},\"comment\":{}}],[\"macro\",{\"_index\":66,\"name\":{\"67\":{}},\"comment\":{}}],[\"market\",{\"_index\":137,\"name\":{\"153\":{},\"456\":{}},\"comment\":{}}],[\"market_data_pre_open\",{\"_index\":11,\"name\":{\"11\":{}},\"comment\":{}}],[\"market_status\",{\"_index\":4,\"name\":{\"4\":{}},\"comment\":{}}],[\"market_turnover\",{\"_index\":5,\"name\":{\"5\":{}},\"comment\":{}}],[\"marketcap\",{\"_index\":169,\"name\":{\"207\":{},\"469\":{}},\"comment\":{}}],[\"marketcapincrrupees\",{\"_index\":332,\"name\":{\"473\":{}},\"comment\":{}}],[\"marketcapincrrupeesformatted\",{\"_index\":333,\"name\":{\"474\":{}},\"comment\":{}}],[\"marketcapinlaccrrupees\",{\"_index\":331,\"name\":{\"472\":{}},\"comment\":{}}],[\"marketcapinlaccrrupeesformatted\",{\"_index\":334,\"name\":{\"475\":{}},\"comment\":{}}],[\"marketcapintrdollars\",{\"_index\":330,\"name\":{\"471\":{}},\"comment\":{}}],[\"marketdeptorderbook\",{\"_index\":74,\"name\":{\"75\":{}},\"comment\":{}}],[\"marketlot\",{\"_index\":88,\"name\":{\"91\":{}},\"comment\":{}}],[\"marketstate\",{\"_index\":168,\"name\":{\"206\":{},\"455\":{}},\"comment\":{}}],[\"marketstatus\",{\"_index\":136,\"name\":{\"151\":{},\"154\":{},\"205\":{},\"457\":{}},\"comment\":{}}],[\"marketstatusmessage\",{\"_index\":142,\"name\":{\"160\":{},\"463\":{}},\"comment\":{}}],[\"marketturnover\",{\"_index\":172,\"name\":{\"210\":{}},\"comment\":{}}],[\"max\",{\"_index\":260,\"name\":{\"336\":{},\"342\":{}},\"comment\":{}}],[\"maxdate\",{\"_index\":264,\"name\":{\"343\":{}},\"comment\":{}}],[\"merged_daily_reports_capital\",{\"_index\":12,\"name\":{\"12\":{}},\"comment\":{}}],[\"merged_daily_reports_debt\",{\"_index\":14,\"name\":{\"14\":{}},\"comment\":{}}],[\"merged_daily_reports_derivatives\",{\"_index\":13,\"name\":{\"13\":{}},\"comment\":{}}],[\"mergeddailyreportsdata\",{\"_index\":183,\"name\":{\"236\":{}},\"comment\":{}}],[\"meta\",{\"_index\":105,\"name\":{\"110\":{},\"431\":{}},\"comment\":{}}],[\"metadata\",{\"_index\":57,\"name\":{\"57\":{},\"127\":{}},\"comment\":{}}],[\"mfi\",{\"_index\":206,\"name\":{\"267\":{}},\"comment\":{}}],[\"middle\",{\"_index\":196,\"name\":{\"256\":{}},\"comment\":{}}],[\"min\",{\"_index\":259,\"name\":{\"335\":{},\"340\":{}},\"comment\":{}}],[\"mindate\",{\"_index\":263,\"name\":{\"341\":{}},\"comment\":{}}],[\"momentum\",{\"_index\":208,\"name\":{\"269\":{}},\"comment\":{}}],[\"morning_session\",{\"_index\":324,\"name\":{\"452\":{}},\"comment\":{}}],[\"mtimestamp\",{\"_index\":293,\"name\":{\"379\":{}},\"comment\":{}}],[\"name\",{\"_index\":52,\"name\":{\"52\":{},\"119\":{},\"237\":{}},\"comment\":{}}],[\"nearwkh\",{\"_index\":313,\"name\":{\"422\":{}},\"comment\":{}}],[\"nearwkl\",{\"_index\":314,\"name\":{\"423\":{}},\"comment\":{}}],[\"noblockdeals\",{\"_index\":72,\"name\":{\"73\":{}},\"comment\":{}}],[\"nseindia\",{\"_index\":15,\"name\":{\"15\":{}},\"comment\":{}}],[\"nts\",{\"_index\":178,\"name\":{\"219\":{}},\"comment\":{}}],[\"obv\",{\"_index\":204,\"name\":{\"265\":{}},\"comment\":{}}],[\"open\",{\"_index\":77,\"name\":{\"79\":{},\"130\":{},\"325\":{},\"408\":{}},\"comment\":{}}],[\"openinterest\",{\"_index\":304,\"name\":{\"396\":{},\"520\":{}},\"comment\":{}}],[\"openprice\",{\"_index\":299,\"name\":{\"387\":{}},\"comment\":{}}],[\"optionchaincontractinfo\",{\"_index\":148,\"name\":{\"172\":{}},\"comment\":{}}],[\"optionsdata\",{\"_index\":351,\"name\":{\"512\":{}},\"comment\":{}}],[\"optionsdetails\",{\"_index\":354,\"name\":{\"515\":{}},\"comment\":{}}],[\"optiontype\",{\"_index\":298,\"name\":{\"385\":{},\"493\":{},\"540\":{}},\"comment\":{}}],[\"pchange\",{\"_index\":251,\"name\":{\"323\":{},\"402\":{},\"414\":{},\"527\":{},\"528\":{}},\"comment\":{}}],[\"pchangeinopeninterest\",{\"_index\":306,\"name\":{\"398\":{},\"522\":{}},\"comment\":{}}],[\"pdsectorind\",{\"_index\":234,\"name\":{\"304\":{}},\"comment\":{}}],[\"pdsectorindall\",{\"_index\":235,\"name\":{\"305\":{}},\"comment\":{}}],[\"pdsectorpe\",{\"_index\":232,\"name\":{\"302\":{}},\"comment\":{}}],[\"pdsymbolpe\",{\"_index\":233,\"name\":{\"303\":{}},\"comment\":{}}],[\"pe\",{\"_index\":319,\"name\":{\"447\":{},\"505\":{}},\"comment\":{}}],[\"percchange\",{\"_index\":122,\"name\":{\"135\":{}},\"comment\":{}}],[\"percentchange\",{\"_index\":141,\"name\":{\"159\":{},\"462\":{}},\"comment\":{}}],[\"perchange\",{\"_index\":342,\"name\":{\"487\":{},\"497\":{}},\"comment\":{}}],[\"perchange30d\",{\"_index\":129,\"name\":{\"142\":{},\"425\":{}},\"comment\":{}}],[\"perchange365d\",{\"_index\":128,\"name\":{\"141\":{},\"424\":{}},\"comment\":{}}],[\"ppriceband\",{\"_index\":256,\"name\":{\"331\":{}},\"comment\":{}}],[\"preopen\",{\"_index\":270,\"name\":{\"350\":{}},\"comment\":{}}],[\"preopendetails\",{\"_index\":347,\"name\":{\"507\":{}},\"comment\":{}}],[\"preopenmarket\",{\"_index\":70,\"name\":{\"71\":{}},\"comment\":{}}],[\"preopenmarketdata\",{\"_index\":182,\"name\":{\"227\":{}},\"comment\":{}}],[\"prevclose\",{\"_index\":302,\"name\":{\"391\":{}},\"comment\":{}}],[\"previousclose\",{\"_index\":120,\"name\":{\"133\":{},\"324\":{},\"412\":{}},\"comment\":{}}],[\"price\",{\"_index\":348,\"name\":{\"508\":{}},\"comment\":{}}],[\"priceinfo\",{\"_index\":64,\"name\":{\"64\":{}},\"comment\":{}}],[\"priority\",{\"_index\":310,\"name\":{\"404\":{}},\"comment\":{}}],[\"quantitytraded\",{\"_index\":98,\"name\":{\"103\":{}},\"comment\":{}}],[\"records\",{\"_index\":145,\"name\":{\"167\":{},\"170\":{}},\"comment\":{}}],[\"roc\",{\"_index\":207,\"name\":{\"268\":{}},\"comment\":{}}],[\"rsi\",{\"_index\":190,\"name\":{\"247\":{}},\"comment\":{}}],[\"sddauditor\",{\"_index\":61,\"name\":{\"61\":{}},\"comment\":{}}],[\"sdddetails\",{\"_index\":59,\"name\":{\"59\":{}},\"comment\":{}}],[\"sddstatus\",{\"_index\":62,\"name\":{\"62\":{}},\"comment\":{}}],[\"section\",{\"_index\":185,\"name\":{\"240\":{}},\"comment\":{}}],[\"sector\",{\"_index\":67,\"name\":{\"68\":{}},\"comment\":{}}],[\"securityinfo\",{\"_index\":58,\"name\":{\"58\":{}},\"comment\":{}}],[\"securityvar\",{\"_index\":91,\"name\":{\"95\":{}},\"comment\":{}}],[\"securitywisedp\",{\"_index\":97,\"name\":{\"101\":{}},\"comment\":{}}],[\"secwisedelposdate\",{\"_index\":102,\"name\":{\"107\":{}},\"comment\":{}}],[\"segment\",{\"_index\":228,\"name\":{\"291\":{}},\"comment\":{}}],[\"sell\",{\"_index\":273,\"name\":{\"354\":{}},\"comment\":{}}],[\"sellprice1\",{\"_index\":362,\"name\":{\"537\":{}},\"comment\":{}}],[\"sellqty\",{\"_index\":350,\"name\":{\"510\":{}},\"comment\":{}}],[\"sellquantity1\",{\"_index\":363,\"name\":{\"538\":{}},\"comment\":{}}],[\"series\",{\"_index\":106,\"name\":{\"112\":{},\"295\":{},\"407\":{}},\"comment\":{}}],[\"seriesdata\",{\"_index\":110,\"name\":{\"116\":{}},\"comment\":{}}],[\"seriesremarks\",{\"_index\":101,\"name\":{\"106\":{}},\"comment\":{}}],[\"sessionno\",{\"_index\":240,\"name\":{\"310\":{}},\"comment\":{}}],[\"shareholdings_patterns\",{\"_index\":154,\"name\":{\"182\":{}},\"comment\":{}}],[\"signal\",{\"_index\":192,\"name\":{\"251\":{}},\"comment\":{}}],[\"slb\",{\"_index\":241,\"name\":{\"311\":{}},\"comment\":{}}],[\"slb_isin\",{\"_index\":224,\"name\":{\"287\":{}},\"comment\":{}}],[\"slickclass\",{\"_index\":329,\"name\":{\"468\":{}},\"comment\":{}}],[\"sma\",{\"_index\":188,\"name\":{\"243\":{}},\"comment\":{}}],[\"sr_no\",{\"_index\":326,\"name\":{\"454\":{}},\"comment\":{}}],[\"start\",{\"_index\":48,\"name\":{\"48\":{}},\"comment\":{}}],[\"status\",{\"_index\":231,\"name\":{\"298\":{},\"488\":{}},\"comment\":{}}],[\"stn\",{\"_index\":177,\"name\":{\"218\":{}},\"comment\":{}}],[\"stochastic\",{\"_index\":198,\"name\":{\"258\":{}},\"comment\":{}}],[\"stockindcloseprice\",{\"_index\":253,\"name\":{\"328\":{},\"416\":{}},\"comment\":{}}],[\"strikeprice\",{\"_index\":150,\"name\":{\"174\":{},\"386\":{},\"494\":{},\"502\":{},\"516\":{}},\"comment\":{}}],[\"strikeprices\",{\"_index\":316,\"name\":{\"433\":{},\"439\":{}},\"comment\":{}}],[\"surv\",{\"_index\":245,\"name\":{\"316\":{}},\"comment\":{}}],[\"surveillance\",{\"_index\":244,\"name\":{\"314\":{}},\"comment\":{}}],[\"symbol\",{\"_index\":212,\"name\":{\"273\":{},\"296\":{},\"405\":{},\"491\":{}},\"comment\":{}}],[\"symbols\",{\"_index\":109,\"name\":{\"115\":{}},\"comment\":{}}],[\"technicalindicators\",{\"_index\":187,\"name\":{\"242\":{}},\"comment\":{}}],[\"tempsuspendedseries\",{\"_index\":215,\"name\":{\"278\":{}},\"comment\":{}}],[\"ticksize\",{\"_index\":267,\"name\":{\"347\":{},\"401\":{}},\"comment\":{}}],[\"timestamp\",{\"_index\":116,\"name\":{\"125\":{},\"165\":{},\"229\":{},\"436\":{},\"442\":{},\"470\":{}},\"comment\":{}}],[\"timestmp\",{\"_index\":345,\"name\":{\"499\":{}},\"comment\":{}}],[\"timeval\",{\"_index\":124,\"name\":{\"137\":{}},\"comment\":{}}],[\"title\",{\"_index\":158,\"name\":{\"195\":{}},\"comment\":{}}],[\"todate\",{\"_index\":108,\"name\":{\"114\":{},\"223\":{}},\"comment\":{}}],[\"totalbuyquantity\",{\"_index\":75,\"name\":{\"77\":{},\"360\":{},\"529\":{}},\"comment\":{}}],[\"totalmarketcap\",{\"_index\":83,\"name\":{\"86\":{},\"234\":{}},\"comment\":{}}],[\"totalsellquantity\",{\"_index\":76,\"name\":{\"78\":{},\"361\":{},\"530\":{}},\"comment\":{}}],[\"totaltradedvalue\",{\"_index\":82,\"name\":{\"85\":{},\"149\":{},\"211\":{},\"233\":{},\"417\":{}},\"comment\":{}}],[\"totaltradedvolume\",{\"_index\":81,\"name\":{\"84\":{},\"148\":{},\"212\":{},\"235\":{},\"356\":{},\"394\":{},\"415\":{},\"523\":{}},\"comment\":{}}],[\"totaltrades\",{\"_index\":173,\"name\":{\"213\":{}},\"comment\":{}}],[\"totalturnover\",{\"_index\":303,\"name\":{\"395\":{}},\"comment\":{}}],[\"totoi\",{\"_index\":352,\"name\":{\"513\":{}},\"comment\":{}}],[\"totvol\",{\"_index\":353,\"name\":{\"514\":{}},\"comment\":{}}],[\"tradedate\",{\"_index\":138,\"name\":{\"155\":{},\"458\":{}},\"comment\":{}}],[\"tradedateformatted\",{\"_index\":328,\"name\":{\"467\":{}},\"comment\":{}}],[\"tradeinfo\",{\"_index\":80,\"name\":{\"82\":{}},\"comment\":{}}],[\"tradingdate\",{\"_index\":321,\"name\":{\"449\":{}},\"comment\":{}}],[\"tradingsegment\",{\"_index\":239,\"name\":{\"309\":{}},\"comment\":{}}],[\"tradingstatus\",{\"_index\":238,\"name\":{\"308\":{}},\"comment\":{}}],[\"type\",{\"_index\":165,\"name\":{\"202\":{},\"238\":{}},\"comment\":{}}],[\"unchanged\",{\"_index\":115,\"name\":{\"124\":{},\"232\":{}},\"comment\":{}}],[\"underlying\",{\"_index\":296,\"name\":{\"383\":{},\"465\":{},\"476\":{},\"518\":{}},\"comment\":{}}],[\"underlyingvalue\",{\"_index\":307,\"name\":{\"399\":{},\"437\":{},\"443\":{},\"539\":{}},\"comment\":{}}],[\"updated_time\",{\"_index\":327,\"name\":{\"466\":{}},\"comment\":{}}],[\"upper\",{\"_index\":195,\"name\":{\"255\":{}},\"comment\":{}}],[\"uppercp\",{\"_index\":255,\"name\":{\"330\":{}},\"comment\":{}}],[\"value\",{\"_index\":261,\"name\":{\"337\":{},\"344\":{}},\"comment\":{}}],[\"valueatrisk\",{\"_index\":90,\"name\":{\"93\":{}},\"comment\":{}}],[\"variation\",{\"_index\":140,\"name\":{\"158\":{},\"461\":{}},\"comment\":{}}],[\"varmargin\",{\"_index\":93,\"name\":{\"97\":{}},\"comment\":{}}],[\"volumefreezequantity\",{\"_index\":308,\"name\":{\"400\":{}},\"comment\":{}}],[\"vwap\",{\"_index\":210,\"name\":{\"271\":{},\"327\":{},\"373\":{}},\"comment\":{}}],[\"weekday\",{\"_index\":322,\"name\":{\"450\":{}},\"comment\":{}}],[\"weekhighlow\",{\"_index\":262,\"name\":{\"338\":{}},\"comment\":{}}],[\"williamsr\",{\"_index\":201,\"name\":{\"262\":{}},\"comment\":{}}],[\"yearhigh\",{\"_index\":125,\"name\":{\"138\":{},\"419\":{}},\"comment\":{}}],[\"yearlow\",{\"_index\":126,\"name\":{\"139\":{},\"421\":{}},\"comment\":{}}]],\"pipeline\":[]}}"); ================================================ FILE: docs/assets/style.css ================================================ :root { /* Light */ --light-color-background: #f2f4f8; --light-color-background-secondary: #eff0f1; --light-color-warning-text: #222; --light-color-background-warning: #e6e600; --light-color-icon-background: var(--light-color-background); --light-color-accent: #c5c7c9; --light-color-active-menu-item: var(--light-color-accent); --light-color-text: #222; --light-color-text-aside: #6e6e6e; --light-color-link: #1f70c2; --light-color-ts-project: #b111c9; --light-color-ts-module: var(--light-color-ts-project); --light-color-ts-namespace: var(--light-color-ts-project); --light-color-ts-enum: #7e6f15; --light-color-ts-enum-member: var(--light-color-ts-enum); --light-color-ts-variable: #4760ec; --light-color-ts-function: #572be7; --light-color-ts-class: #1f70c2; --light-color-ts-interface: #108024; --light-color-ts-constructor: var(--light-color-ts-class); --light-color-ts-property: var(--light-color-ts-variable); --light-color-ts-method: var(--light-color-ts-function); --light-color-ts-call-signature: var(--light-color-ts-method); --light-color-ts-index-signature: var(--light-color-ts-property); --light-color-ts-constructor-signature: var(--light-color-ts-constructor); --light-color-ts-parameter: var(--light-color-ts-variable); /* type literal not included as links will never be generated to it */ --light-color-ts-type-parameter: var(--light-color-ts-type-alias); --light-color-ts-accessor: var(--light-color-ts-property); --light-color-ts-get-signature: var(--light-color-ts-accessor); --light-color-ts-set-signature: var(--light-color-ts-accessor); /* object literal not included as it is not used and will be removed in 0.25 */ --light-color-ts-type-alias: #d51270; /* reference not included as links will be colored with the kind that it points to */ --light-external-icon: url("data:image/svg+xml;utf8,"); --light-color-scheme: light; /* Dark */ --dark-color-background: #2b2e33; --dark-color-background-secondary: #1e2024; --dark-color-background-warning: #bebe00; --dark-color-warning-text: #222; --dark-color-icon-background: var(--dark-color-background-secondary); --dark-color-accent: #9096a2; --dark-color-active-menu-item: #5d5d6a; --dark-color-text: #f5f5f5; --dark-color-text-aside: #dddddd; --dark-color-link: #00aff4; --dark-color-ts-project: #e358ff; --dark-color-ts-module: var(--dark-color-ts-project); --dark-color-ts-namespace: var(--dark-color-ts-project); --dark-color-ts-enum: #f4d93e; --dark-color-ts-enum-member: var(--dark-color-ts-enum); --dark-color-ts-variable: #798dff; --dark-color-ts-function: #a280ff; --dark-color-ts-class: #8ac4ff; --dark-color-ts-interface: #6cff87; --dark-color-ts-constructor: var(--dark-color-ts-class); --dark-color-ts-property: var(--dark-color-ts-variable); --dark-color-ts-method: var(--dark-color-ts-function); --dark-color-ts-call-signature: var(--dark-color-ts-method); --dark-color-ts-index-signature: var(--dark-color-ts-property); --dark-color-ts-constructor-signature: var(--dark-color-ts-constructor); --dark-color-ts-parameter: var(--dark-color-ts-variable); /* type literal not included as links will never be generated to it */ --dark-color-ts-type-parameter: var(--dark-color-ts-type-alias); --dark-color-ts-accessor: var(--dark-color-ts-property); --dark-color-ts-get-signature: var(--dark-color-ts-accessor); --dark-color-ts-set-signature: var(--dark-color-ts-accessor); /* object literal not included as it is not used and will be removed in 0.25 */ --dark-color-ts-type-alias: #ff6492; /* reference not included as links will be colored with the kind that it points to */ --dark-external-icon: url("data:image/svg+xml;utf8,"); --dark-color-scheme: dark; } @media (prefers-color-scheme: light) { :root { --color-background: var(--light-color-background); --color-background-secondary: var(--light-color-background-secondary); --color-background-warning: var(--light-color-background-warning); --color-warning-text: var(--light-color-warning-text); --color-icon-background: var(--light-color-icon-background); --color-accent: var(--light-color-accent); --color-active-menu-item: var(--light-color-active-menu-item); --color-text: var(--light-color-text); --color-text-aside: var(--light-color-text-aside); --color-link: var(--light-color-link); --color-ts-module: var(--light-color-ts-module); --color-ts-namespace: var(--light-color-ts-namespace); --color-ts-enum: var(--light-color-ts-enum); --color-ts-enum-member: var(--light-color-ts-enum-member); --color-ts-variable: var(--light-color-ts-variable); --color-ts-function: var(--light-color-ts-function); --color-ts-class: var(--light-color-ts-class); --color-ts-interface: var(--light-color-ts-interface); --color-ts-constructor: var(--light-color-ts-constructor); --color-ts-property: var(--light-color-ts-property); --color-ts-method: var(--light-color-ts-method); --color-ts-call-signature: var(--light-color-ts-call-signature); --color-ts-index-signature: var(--light-color-ts-index-signature); --color-ts-constructor-signature: var( --light-color-ts-constructor-signature ); --color-ts-parameter: var(--light-color-ts-parameter); --color-ts-type-parameter: var(--light-color-ts-type-parameter); --color-ts-accessor: var(--light-color-ts-accessor); --color-ts-get-signature: var(--light-color-ts-get-signature); --color-ts-set-signature: var(--light-color-ts-set-signature); --color-ts-type-alias: var(--light-color-ts-type-alias); --external-icon: var(--light-external-icon); --color-scheme: var(--light-color-scheme); } } @media (prefers-color-scheme: dark) { :root { --color-background: var(--dark-color-background); --color-background-secondary: var(--dark-color-background-secondary); --color-background-warning: var(--dark-color-background-warning); --color-warning-text: var(--dark-color-warning-text); --color-icon-background: var(--dark-color-icon-background); --color-accent: var(--dark-color-accent); --color-active-menu-item: var(--dark-color-active-menu-item); --color-text: var(--dark-color-text); --color-text-aside: var(--dark-color-text-aside); --color-link: var(--dark-color-link); --color-ts-module: var(--dark-color-ts-module); --color-ts-namespace: var(--dark-color-ts-namespace); --color-ts-enum: var(--dark-color-ts-enum); --color-ts-enum-member: var(--dark-color-ts-enum-member); --color-ts-variable: var(--dark-color-ts-variable); --color-ts-function: var(--dark-color-ts-function); --color-ts-class: var(--dark-color-ts-class); --color-ts-interface: var(--dark-color-ts-interface); --color-ts-constructor: var(--dark-color-ts-constructor); --color-ts-property: var(--dark-color-ts-property); --color-ts-method: var(--dark-color-ts-method); --color-ts-call-signature: var(--dark-color-ts-call-signature); --color-ts-index-signature: var(--dark-color-ts-index-signature); --color-ts-constructor-signature: var( --dark-color-ts-constructor-signature ); --color-ts-parameter: var(--dark-color-ts-parameter); --color-ts-type-parameter: var(--dark-color-ts-type-parameter); --color-ts-accessor: var(--dark-color-ts-accessor); --color-ts-get-signature: var(--dark-color-ts-get-signature); --color-ts-set-signature: var(--dark-color-ts-set-signature); --color-ts-type-alias: var(--dark-color-ts-type-alias); --external-icon: var(--dark-external-icon); --color-scheme: var(--dark-color-scheme); } } html { color-scheme: var(--color-scheme); } body { margin: 0; } :root[data-theme="light"] { --color-background: var(--light-color-background); --color-background-secondary: var(--light-color-background-secondary); --color-background-warning: var(--light-color-background-warning); --color-warning-text: var(--light-color-warning-text); --color-icon-background: var(--light-color-icon-background); --color-accent: var(--light-color-accent); --color-active-menu-item: var(--light-color-active-menu-item); --color-text: var(--light-color-text); --color-text-aside: var(--light-color-text-aside); --color-link: var(--light-color-link); --color-ts-module: var(--light-color-ts-module); --color-ts-namespace: var(--light-color-ts-namespace); --color-ts-enum: var(--light-color-ts-enum); --color-ts-enum-member: var(--light-color-ts-enum-member); --color-ts-variable: var(--light-color-ts-variable); --color-ts-function: var(--light-color-ts-function); --color-ts-class: var(--light-color-ts-class); --color-ts-interface: var(--light-color-ts-interface); --color-ts-constructor: var(--light-color-ts-constructor); --color-ts-property: var(--light-color-ts-property); --color-ts-method: var(--light-color-ts-method); --color-ts-call-signature: var(--light-color-ts-call-signature); --color-ts-index-signature: var(--light-color-ts-index-signature); --color-ts-constructor-signature: var( --light-color-ts-constructor-signature ); --color-ts-parameter: var(--light-color-ts-parameter); --color-ts-type-parameter: var(--light-color-ts-type-parameter); --color-ts-accessor: var(--light-color-ts-accessor); --color-ts-get-signature: var(--light-color-ts-get-signature); --color-ts-set-signature: var(--light-color-ts-set-signature); --color-ts-type-alias: var(--light-color-ts-type-alias); --external-icon: var(--light-external-icon); --color-scheme: var(--light-color-scheme); } :root[data-theme="dark"] { --color-background: var(--dark-color-background); --color-background-secondary: var(--dark-color-background-secondary); --color-background-warning: var(--dark-color-background-warning); --color-warning-text: var(--dark-color-warning-text); --color-icon-background: var(--dark-color-icon-background); --color-accent: var(--dark-color-accent); --color-active-menu-item: var(--dark-color-active-menu-item); --color-text: var(--dark-color-text); --color-text-aside: var(--dark-color-text-aside); --color-link: var(--dark-color-link); --color-ts-module: var(--dark-color-ts-module); --color-ts-namespace: var(--dark-color-ts-namespace); --color-ts-enum: var(--dark-color-ts-enum); --color-ts-enum-member: var(--dark-color-ts-enum-member); --color-ts-variable: var(--dark-color-ts-variable); --color-ts-function: var(--dark-color-ts-function); --color-ts-class: var(--dark-color-ts-class); --color-ts-interface: var(--dark-color-ts-interface); --color-ts-constructor: var(--dark-color-ts-constructor); --color-ts-property: var(--dark-color-ts-property); --color-ts-method: var(--dark-color-ts-method); --color-ts-call-signature: var(--dark-color-ts-call-signature); --color-ts-index-signature: var(--dark-color-ts-index-signature); --color-ts-constructor-signature: var( --dark-color-ts-constructor-signature ); --color-ts-parameter: var(--dark-color-ts-parameter); --color-ts-type-parameter: var(--dark-color-ts-type-parameter); --color-ts-accessor: var(--dark-color-ts-accessor); --color-ts-get-signature: var(--dark-color-ts-get-signature); --color-ts-set-signature: var(--dark-color-ts-set-signature); --color-ts-type-alias: var(--dark-color-ts-type-alias); --external-icon: var(--dark-external-icon); --color-scheme: var(--dark-color-scheme); } .always-visible, .always-visible .tsd-signatures { display: inherit !important; } h1, h2, h3, h4, h5, h6 { line-height: 1.2; } h1 > a, h2 > a, h3 > a, h4 > a, h5 > a, h6 > a { text-decoration: none; color: var(--color-text); } h1 { font-size: 1.875rem; margin: 0.67rem 0; } h2 { font-size: 1.5rem; margin: 0.83rem 0; } h3 { font-size: 1.25rem; margin: 1rem 0; } h4 { font-size: 1.05rem; margin: 1.33rem 0; } h5 { font-size: 1rem; margin: 1.5rem 0; } h6 { font-size: 0.875rem; margin: 2.33rem 0; } .uppercase { text-transform: uppercase; } dl, menu, ol, ul { margin: 1em 0; } dd { margin: 0 0 0 40px; } .container { max-width: 1700px; padding: 0 2rem; } /* Footer */ .tsd-generator { border-top: 1px solid var(--color-accent); padding-top: 1rem; padding-bottom: 1rem; max-height: 3.5rem; } .tsd-generator > p { margin-top: 0; margin-bottom: 0; padding: 0 1rem; } .container-main { margin: 0 auto; /* toolbar, footer, margin */ min-height: calc(100vh - 41px - 56px - 4rem); } @keyframes fade-in { from { opacity: 0; } to { opacity: 1; } } @keyframes fade-out { from { opacity: 1; visibility: visible; } to { opacity: 0; } } @keyframes fade-in-delayed { 0% { opacity: 0; } 33% { opacity: 0; } 100% { opacity: 1; } } @keyframes fade-out-delayed { 0% { opacity: 1; visibility: visible; } 66% { opacity: 0; } 100% { opacity: 0; } } @keyframes pop-in-from-right { from { transform: translate(100%, 0); } to { transform: translate(0, 0); } } @keyframes pop-out-to-right { from { transform: translate(0, 0); visibility: visible; } to { transform: translate(100%, 0); } } body { background: var(--color-background); font-family: "Segoe UI", sans-serif; font-size: 16px; color: var(--color-text); } a { color: var(--color-link); text-decoration: none; } a:hover { text-decoration: underline; } a.external[target="_blank"] { background-image: var(--external-icon); background-position: top 3px right; background-repeat: no-repeat; padding-right: 13px; } code, pre { font-family: Menlo, Monaco, Consolas, "Courier New", monospace; padding: 0.2em; margin: 0; font-size: 0.875rem; border-radius: 0.8em; } pre { position: relative; white-space: pre; white-space: pre-wrap; word-wrap: break-word; padding: 10px; border: 1px solid var(--color-accent); } pre code { padding: 0; font-size: 100%; } pre > button { position: absolute; top: 10px; right: 10px; opacity: 0; transition: opacity 0.1s; box-sizing: border-box; } pre:hover > button, pre > button.visible { opacity: 1; } blockquote { margin: 1em 0; padding-left: 1em; border-left: 4px solid gray; } .tsd-typography { line-height: 1.333em; } .tsd-typography ul { list-style: square; padding: 0 0 0 20px; margin: 0; } .tsd-typography h4, .tsd-typography .tsd-index-panel h3, .tsd-index-panel .tsd-typography h3, .tsd-typography h5, .tsd-typography h6 { font-size: 1em; margin: 0; } .tsd-typography h5, .tsd-typography h6 { font-weight: normal; } .tsd-typography p, .tsd-typography ul, .tsd-typography ol { margin: 1em 0; } .tsd-breadcrumb { margin: 0; padding: 0; color: var(--color-text-aside); } .tsd-breadcrumb a { color: var(--color-text-aside); text-decoration: none; } .tsd-breadcrumb a:hover { text-decoration: underline; } .tsd-breadcrumb li { display: inline; } .tsd-breadcrumb li:after { content: " / "; } .tsd-comment-tags { display: flex; flex-direction: column; } dl.tsd-comment-tag-group { display: flex; align-items: center; overflow: hidden; margin: 0.5em 0; } dl.tsd-comment-tag-group dt { display: flex; margin-right: 0.5em; font-size: 0.875em; font-weight: normal; } dl.tsd-comment-tag-group dd { margin: 0; } code.tsd-tag { padding: 0.25em 0.4em; border: 0.1em solid var(--color-accent); margin-right: 0.25em; font-size: 70%; } h1 code.tsd-tag:first-of-type { margin-left: 0.25em; } dl.tsd-comment-tag-group dd:before, dl.tsd-comment-tag-group dd:after { content: " "; } dl.tsd-comment-tag-group dd pre, dl.tsd-comment-tag-group dd:after { clear: both; } dl.tsd-comment-tag-group p { margin: 0; } .tsd-panel.tsd-comment .lead { font-size: 1.1em; line-height: 1.333em; margin-bottom: 2em; } .tsd-panel.tsd-comment .lead:last-child { margin-bottom: 0; } .tsd-filter-visibility h4 { font-size: 1rem; padding-top: 0.75rem; padding-bottom: 0.5rem; margin: 0; } .tsd-filter-item:not(:last-child) { margin-bottom: 0.5rem; } .tsd-filter-input { display: flex; width: fit-content; width: -moz-fit-content; align-items: center; user-select: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; cursor: pointer; } .tsd-filter-input input[type="checkbox"] { cursor: pointer; position: absolute; width: 1.5em; height: 1.5em; opacity: 0; } .tsd-filter-input input[type="checkbox"]:disabled { pointer-events: none; } .tsd-filter-input svg { cursor: pointer; width: 1.5em; height: 1.5em; margin-right: 0.5em; border-radius: 0.33em; /* Leaving this at full opacity breaks event listeners on Firefox. Don't remove unless you know what you're doing. */ opacity: 0.99; } .tsd-filter-input input[type="checkbox"]:focus + svg { transform: scale(0.95); } .tsd-filter-input input[type="checkbox"]:focus:not(:focus-visible) + svg { transform: scale(1); } .tsd-checkbox-background { fill: var(--color-accent); } input[type="checkbox"]:checked ~ svg .tsd-checkbox-checkmark { stroke: var(--color-text); } .tsd-filter-input input:disabled ~ svg > .tsd-checkbox-background { fill: var(--color-background); stroke: var(--color-accent); stroke-width: 0.25rem; } .tsd-filter-input input:disabled ~ svg > .tsd-checkbox-checkmark { stroke: var(--color-accent); } .tsd-theme-toggle { padding-top: 0.75rem; } .tsd-theme-toggle > h4 { display: inline; vertical-align: middle; margin-right: 0.75rem; } .tsd-hierarchy { list-style: square; margin: 0; } .tsd-hierarchy .target { font-weight: bold; } .tsd-panel-group.tsd-index-group { margin-bottom: 0; } .tsd-index-panel .tsd-index-list { list-style: none; line-height: 1.333em; margin: 0; padding: 0.25rem 0 0 0; overflow: hidden; display: grid; grid-template-columns: repeat(3, 1fr); column-gap: 1rem; grid-template-rows: auto; } @media (max-width: 1024px) { .tsd-index-panel .tsd-index-list { grid-template-columns: repeat(2, 1fr); } } @media (max-width: 768px) { .tsd-index-panel .tsd-index-list { grid-template-columns: repeat(1, 1fr); } } .tsd-index-panel .tsd-index-list li { -webkit-page-break-inside: avoid; -moz-page-break-inside: avoid; -ms-page-break-inside: avoid; -o-page-break-inside: avoid; page-break-inside: avoid; } .tsd-flag { display: inline-block; padding: 0.25em 0.4em; border-radius: 4px; color: var(--color-comment-tag-text); background-color: var(--color-comment-tag); text-indent: 0; font-size: 75%; line-height: 1; font-weight: normal; } .tsd-anchor { position: relative; top: -100px; } .tsd-member { position: relative; } .tsd-member .tsd-anchor + h3 { display: flex; align-items: center; margin-top: 0; margin-bottom: 0; border-bottom: none; } .tsd-navigation.settings { margin: 1rem 0; } .tsd-navigation > a, .tsd-navigation .tsd-accordion-summary { width: calc(100% - 0.5rem); } .tsd-navigation a, .tsd-navigation summary > span, .tsd-page-navigation a { display: inline-flex; align-items: center; padding: 0.25rem; color: var(--color-text); text-decoration: none; box-sizing: border-box; } .tsd-navigation a.current, .tsd-page-navigation a.current { background: var(--color-active-menu-item); } .tsd-navigation a:hover, .tsd-page-navigation a:hover { text-decoration: underline; } .tsd-navigation ul, .tsd-page-navigation ul { margin-top: 0; margin-bottom: 0; padding: 0; list-style: none; } .tsd-navigation li, .tsd-page-navigation li { padding: 0; max-width: 100%; } .tsd-nested-navigation { margin-left: 3rem; } .tsd-nested-navigation > li > details { margin-left: -1.5rem; } .tsd-small-nested-navigation { margin-left: 1.5rem; } .tsd-small-nested-navigation > li > details { margin-left: -1.5rem; } .tsd-nested-navigation > li > a, .tsd-nested-navigation > li > span { width: calc(100% - 1.75rem - 0.5rem); } .tsd-page-navigation ul { padding-left: 1.75rem; } #tsd-sidebar-links a { margin-top: 0; margin-bottom: 0.5rem; line-height: 1.25rem; } #tsd-sidebar-links a:last-of-type { margin-bottom: 0; } a.tsd-index-link { padding: 0.25rem 0 !important; font-size: 1rem; line-height: 1.25rem; display: inline-flex; align-items: center; color: var(--color-text); } .tsd-accordion-summary { list-style-type: none; /* hide marker on non-safari */ outline: none; /* broken on safari, so just hide it */ } .tsd-accordion-summary::-webkit-details-marker { display: none; /* hide marker on safari */ } .tsd-accordion-summary, .tsd-accordion-summary a { user-select: none; -moz-user-select: none; -webkit-user-select: none; -ms-user-select: none; cursor: pointer; } .tsd-accordion-summary a { width: calc(100% - 1.5rem); } .tsd-accordion-summary > * { margin-top: 0; margin-bottom: 0; padding-top: 0; padding-bottom: 0; } .tsd-index-accordion .tsd-accordion-summary > svg { margin-left: 0.25rem; } .tsd-index-content > :not(:first-child) { margin-top: 0.75rem; } .tsd-index-heading { margin-top: 1.5rem; margin-bottom: 0.75rem; } .tsd-kind-icon { margin-right: 0.5rem; width: 1.25rem; height: 1.25rem; min-width: 1.25rem; min-height: 1.25rem; } .tsd-kind-icon path { transform-origin: center; transform: scale(1.1); } .tsd-signature > .tsd-kind-icon { margin-right: 0.8rem; } .tsd-panel { margin-bottom: 2.5rem; } .tsd-panel.tsd-member { margin-bottom: 4rem; } .tsd-panel:empty { display: none; } .tsd-panel > h1, .tsd-panel > h2, .tsd-panel > h3 { margin: 1.5rem -1.5rem 0.75rem -1.5rem; padding: 0 1.5rem 0.75rem 1.5rem; } .tsd-panel > h1.tsd-before-signature, .tsd-panel > h2.tsd-before-signature, .tsd-panel > h3.tsd-before-signature { margin-bottom: 0; border-bottom: none; } .tsd-panel-group { margin: 4rem 0; } .tsd-panel-group.tsd-index-group { margin: 2rem 0; } .tsd-panel-group.tsd-index-group details { margin: 2rem 0; } #tsd-search { transition: background-color 0.2s; } #tsd-search .title { position: relative; z-index: 2; } #tsd-search .field { position: absolute; left: 0; top: 0; right: 2.5rem; height: 100%; } #tsd-search .field input { box-sizing: border-box; position: relative; top: -50px; z-index: 1; width: 100%; padding: 0 10px; opacity: 0; outline: 0; border: 0; background: transparent; color: var(--color-text); } #tsd-search .field label { position: absolute; overflow: hidden; right: -40px; } #tsd-search .field input, #tsd-search .title, #tsd-toolbar-links a { transition: opacity 0.2s; } #tsd-search .results { position: absolute; visibility: hidden; top: 40px; width: 100%; margin: 0; padding: 0; list-style: none; box-shadow: 0 0 4px rgba(0, 0, 0, 0.25); } #tsd-search .results li { padding: 0 10px; background-color: var(--color-background); } #tsd-search .results li:nth-child(even) { background-color: var(--color-background-secondary); } #tsd-search .results li.state { display: none; } #tsd-search .results li.current, #tsd-search .results li:hover { background-color: var(--color-accent); } #tsd-search .results a { display: block; } #tsd-search .results a:before { top: 10px; } #tsd-search .results span.parent { color: var(--color-text-aside); font-weight: normal; } #tsd-search.has-focus { background-color: var(--color-accent); } #tsd-search.has-focus .field input { top: 0; opacity: 1; } #tsd-search.has-focus .title, #tsd-search.has-focus #tsd-toolbar-links a { z-index: 0; opacity: 0; } #tsd-search.has-focus .results { visibility: visible; } #tsd-search.loading .results li.state.loading { display: block; } #tsd-search.failure .results li.state.failure { display: block; } #tsd-toolbar-links { position: absolute; top: 0; right: 2rem; height: 100%; display: flex; align-items: center; justify-content: flex-end; } #tsd-toolbar-links a { margin-left: 1.5rem; } #tsd-toolbar-links a:hover { text-decoration: underline; } .tsd-signature { margin: 0 0 1rem 0; padding: 1rem 0.5rem; border: 1px solid var(--color-accent); font-family: Menlo, Monaco, Consolas, "Courier New", monospace; font-size: 14px; overflow-x: auto; } .tsd-signature-symbol { color: var(--color-text-aside); font-weight: normal; } .tsd-signature-type { font-style: italic; font-weight: normal; } .tsd-signatures { padding: 0; margin: 0 0 1em 0; list-style-type: none; } .tsd-signatures .tsd-signature { margin: 0; border-color: var(--color-accent); border-width: 1px 0; transition: background-color 0.1s; } .tsd-description .tsd-signatures .tsd-signature { border-width: 1px; } ul.tsd-parameter-list, ul.tsd-type-parameter-list { list-style: square; margin: 0; padding-left: 20px; } ul.tsd-parameter-list > li.tsd-parameter-signature, ul.tsd-type-parameter-list > li.tsd-parameter-signature { list-style: none; margin-left: -20px; } ul.tsd-parameter-list h5, ul.tsd-type-parameter-list h5 { font-size: 16px; margin: 1em 0 0.5em 0; } .tsd-sources { margin-top: 1rem; font-size: 0.875em; } .tsd-sources a { color: var(--color-text-aside); text-decoration: underline; } .tsd-sources ul { list-style: none; padding: 0; } .tsd-page-toolbar { position: sticky; z-index: 1; top: 0; left: 0; width: 100%; color: var(--color-text); background: var(--color-background-secondary); border-bottom: 1px var(--color-accent) solid; transition: transform 0.3s ease-in-out; } .tsd-page-toolbar a { color: var(--color-text); text-decoration: none; } .tsd-page-toolbar a.title { font-weight: bold; } .tsd-page-toolbar a.title:hover { text-decoration: underline; } .tsd-page-toolbar .tsd-toolbar-contents { display: flex; justify-content: space-between; height: 2.5rem; margin: 0 auto; } .tsd-page-toolbar .table-cell { position: relative; white-space: nowrap; line-height: 40px; } .tsd-page-toolbar .table-cell:first-child { width: 100%; } .tsd-page-toolbar .tsd-toolbar-icon { box-sizing: border-box; line-height: 0; padding: 12px 0; } .tsd-widget { display: inline-block; overflow: hidden; opacity: 0.8; height: 40px; transition: opacity 0.1s, background-color 0.2s; vertical-align: bottom; cursor: pointer; } .tsd-widget:hover { opacity: 0.9; } .tsd-widget.active { opacity: 1; background-color: var(--color-accent); } .tsd-widget.no-caption { width: 40px; } .tsd-widget.no-caption:before { margin: 0; } .tsd-widget.options, .tsd-widget.menu { display: none; } input[type="checkbox"] + .tsd-widget:before { background-position: -120px 0; } input[type="checkbox"]:checked + .tsd-widget:before { background-position: -160px 0; } img { max-width: 100%; } .tsd-anchor-icon { display: inline-flex; align-items: center; margin-left: 0.5rem; vertical-align: middle; color: var(--color-text); } .tsd-anchor-icon svg { width: 1em; height: 1em; visibility: hidden; } .tsd-anchor-link:hover > .tsd-anchor-icon svg { visibility: visible; } .deprecated { text-decoration: line-through; } .warning { padding: 1rem; color: var(--color-warning-text); background: var(--color-background-warning); } .tsd-kind-project { color: var(--color-ts-project); } .tsd-kind-module { color: var(--color-ts-module); } .tsd-kind-namespace { color: var(--color-ts-namespace); } .tsd-kind-enum { color: var(--color-ts-enum); } .tsd-kind-enum-member { color: var(--color-ts-enum-member); } .tsd-kind-variable { color: var(--color-ts-variable); } .tsd-kind-function { color: var(--color-ts-function); } .tsd-kind-class { color: var(--color-ts-class); } .tsd-kind-interface { color: var(--color-ts-interface); } .tsd-kind-constructor { color: var(--color-ts-constructor); } .tsd-kind-property { color: var(--color-ts-property); } .tsd-kind-method { color: var(--color-ts-method); } .tsd-kind-call-signature { color: var(--color-ts-call-signature); } .tsd-kind-index-signature { color: var(--color-ts-index-signature); } .tsd-kind-constructor-signature { color: var(--color-ts-constructor-signature); } .tsd-kind-parameter { color: var(--color-ts-parameter); } .tsd-kind-type-literal { color: var(--color-ts-type-literal); } .tsd-kind-type-parameter { color: var(--color-ts-type-parameter); } .tsd-kind-accessor { color: var(--color-ts-accessor); } .tsd-kind-get-signature { color: var(--color-ts-get-signature); } .tsd-kind-set-signature { color: var(--color-ts-set-signature); } .tsd-kind-type-alias { color: var(--color-ts-type-alias); } /* if we have a kind icon, don't color the text by kind */ .tsd-kind-icon ~ span { color: var(--color-text); } * { scrollbar-width: thin; scrollbar-color: var(--color-accent) var(--color-icon-background); } *::-webkit-scrollbar { width: 0.75rem; } *::-webkit-scrollbar-track { background: var(--color-icon-background); } *::-webkit-scrollbar-thumb { background-color: var(--color-accent); border-radius: 999rem; border: 0.25rem solid var(--color-icon-background); } /* mobile */ @media (max-width: 769px) { .tsd-widget.options, .tsd-widget.menu { display: inline-block; } .container-main { display: flex; } html .col-content { float: none; max-width: 100%; width: 100%; } html .col-sidebar { position: fixed !important; overflow-y: auto; -webkit-overflow-scrolling: touch; z-index: 1024; top: 0 !important; bottom: 0 !important; left: auto !important; right: 0 !important; padding: 1.5rem 1.5rem 0 0; width: 75vw; visibility: hidden; background-color: var(--color-background); transform: translate(100%, 0); } html .col-sidebar > *:last-child { padding-bottom: 20px; } html .overlay { content: ""; display: block; position: fixed; z-index: 1023; top: 0; left: 0; right: 0; bottom: 0; background-color: rgba(0, 0, 0, 0.75); visibility: hidden; } .to-has-menu .overlay { animation: fade-in 0.4s; } .to-has-menu .col-sidebar { animation: pop-in-from-right 0.4s; } .from-has-menu .overlay { animation: fade-out 0.4s; } .from-has-menu .col-sidebar { animation: pop-out-to-right 0.4s; } .has-menu body { overflow: hidden; } .has-menu .overlay { visibility: visible; } .has-menu .col-sidebar { visibility: visible; transform: translate(0, 0); display: flex; flex-direction: column; gap: 1.5rem; max-height: 100vh; padding: 1rem 2rem; } .has-menu .tsd-navigation { max-height: 100%; } } /* one sidebar */ @media (min-width: 770px) { .container-main { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 2fr); grid-template-areas: "sidebar content"; margin: 2rem auto; } .col-sidebar { grid-area: sidebar; } .col-content { grid-area: content; padding: 0 1rem; } } @media (min-width: 770px) and (max-width: 1399px) { .col-sidebar { max-height: calc(100vh - 2rem - 42px); overflow: auto; position: sticky; top: 42px; padding-top: 1rem; } .site-menu { margin-top: 1rem; } } /* two sidebars */ @media (min-width: 1200px) { .container-main { grid-template-columns: minmax(0, 1fr) minmax(0, 2.5fr) minmax(0, 20rem); grid-template-areas: "sidebar content toc"; } .col-sidebar { display: contents; } .page-menu { grid-area: toc; padding-left: 1rem; } .site-menu { grid-area: sidebar; } .site-menu { margin-top: 1rem 0; } .page-menu, .site-menu { max-height: calc(100vh - 2rem - 42px); overflow: auto; position: sticky; top: 42px; } } ================================================ FILE: docs/classes/NseIndia.html ================================================ NseIndia | stock-nse-india - v1.3.0

Class NseIndia

Hierarchy

  • NseIndia

Constructors

Methods

  • Returns Promise<string[]>

    List of NSE equity symbols

  • Parameters

    • url: string

      NSE API's URL

    Returns Promise<any>

    JSON data from NSE India

  • Parameters

    • apiEndpoint: string

    Returns Promise<any>

  • Parameters

    • indexSymbol: string
    • Optional expiry: string

      Optional expiry date in DD-MMM-YYYY format (e.g., "23-Dec-2025"). If not provided, will fetch nearest upcoming expiry

    Returns Promise<IndexOptionChainData>

  • Get technical indicators for a specific equity symbol

    Parameters

    • symbol: string

      The equity symbol (e.g., 'RELIANCE', 'TCS')

    • period: number = 200

      Number of days for historical data (default: 200)

    • options: {
          adxPeriod?: number;
          atrPeriod?: number;
          bbPeriod?: number;
          bbStdDev?: number;
          cciPeriod?: number;
          emaPeriods?: number[];
          macdFast?: number;
          macdSignal?: number;
          macdSlow?: number;
          mfiPeriod?: number;
          momentumPeriod?: number;
          rocPeriod?: number;
          rsiPeriod?: number;
          smaPeriods?: number[];
          stochD?: number;
          stochK?: number;
          williamsRPeriod?: number;
      } = {}

      Optional configuration for indicators

      • Optional adxPeriod?: number
      • Optional atrPeriod?: number
      • Optional bbPeriod?: number
      • Optional bbStdDev?: number
      • Optional cciPeriod?: number
      • Optional emaPeriods?: number[]
      • Optional macdFast?: number
      • Optional macdSignal?: number
      • Optional macdSlow?: number
      • Optional mfiPeriod?: number
      • Optional momentumPeriod?: number
      • Optional rocPeriod?: number
      • Optional rsiPeriod?: number
      • Optional smaPeriods?: number[]
      • Optional stochD?: number
      • Optional stochK?: number
      • Optional williamsRPeriod?: number

    Returns Promise<TechnicalIndicators>

    Promise

Generated using TypeDoc

================================================ FILE: docs/enums/ApiList.html ================================================ ApiList | stock-nse-india - v1.3.0

Enumeration ApiList

Enumeration Members

ALL_INDICES: "/api/allIndices"
CIRCULARS: "/api/circulars"
EQUITY_MASTER: "/api/equity-master"
GLOSSARY: "/api/cmsContent?url=/glossary"
HOLIDAY_CLEARING: "/api/holiday-master?type=clearing"
HOLIDAY_TRADING: "/api/holiday-master?type=trading"
INDEX_NAMES: "/api/index-names"
LATEST_CIRCULARS: "/api/latest-circular"
MARKET_DATA_PRE_OPEN: "/api/market-data-pre-open?key=ALL"
MARKET_STATUS: "/api/marketStatus"
MARKET_TURNOVER: "/api/market-turnover"
MERGED_DAILY_REPORTS_CAPITAL: "/api/merged-daily-reports?key=favCapital"
MERGED_DAILY_REPORTS_DEBT: "/api/merged-daily-reports?key=favDebt"
MERGED_DAILY_REPORTS_DERIVATIVES: "/api/merged-daily-reports?key=favDerivatives"

Generated using TypeDoc

================================================ FILE: docs/index.html ================================================ stock-nse-india - v1.3.0

stock-nse-india - v1.3.0

NPM

National Stock Exchange - India (Unofficial)

npm NPM GitHub Release Date - Published_At GitHub top language

A comprehensive package and API server for accessing equity/index details and historical data from the National Stock Exchange of India. This project provides both an NPM package for direct integration and a full-featured GraphQL/REST API server.

📚 Documentation | 🚀 Examples

✨ Features

  • 📦 NPM Package - Direct integration into your Node.js projects
  • 🔌 GraphQL API - Modern GraphQL interface with Apollo Server
  • 🌐 REST API - Comprehensive REST endpoints with Swagger documentation
  • 🤖 MCP Server - Model Context Protocol server for AI assistants
  • 💻 CLI Tool - Command-line interface for quick data access
  • 🐳 Docker Support - Containerized deployment
  • 🔒 CORS Configuration - Configurable cross-origin resource sharing
  • 📊 Real-time Data - Live market data and historical information
  • 📈 Multiple Data Types - Equity, Index, Commodity, and Options data

🚀 Quick Start

⚠️ Prerequisites: Node.js 18+ required

As an NPM Package

npm install stock-nse-india
import { NseIndia } from "stock-nse-india";

const nseIndia = new NseIndia();

// Get all stock symbols
const symbols = await nseIndia.getAllStockSymbols();
console.log(symbols);

// Get equity details
const details = await nseIndia.getEquityDetails('IRCTC');
console.log(details);

// Get historical data
const range = {
start: new Date("2020-01-01"),
end: new Date("2023-12-31")
};
const historicalData = await nseIndia.getEquityHistoricalData('IRCTC', range);
console.log(historicalData);

As an API Server

# Clone and setup
git clone https://github.com/hi-imcodeman/stock-nse-india.git
cd stock-nse-india
npm install

# Start the server
npm start

🌐 Server URLs:

📦 Installation

Prerequisites

  • Node.js: Version 18 or higher
  • npm: Version 8 or higher (comes with Node.js 18+)

NPM Package

npm install stock-nse-india
# or
yarn add stock-nse-india

CLI Tool

npm install -g stock-nse-india

Server Setup

git clone https://github.com/hi-imcodeman/stock-nse-india.git
cd stock-nse-india
npm install
npm start

🔌 GraphQL API

The project now includes a powerful GraphQL API for flexible data querying:

Example Queries

# Get equity information
query GetEquity {
equities(symbolFilter: { symbols: ["IRCTC", "RELIANCE"] }) {
symbol
details {
info {
companyName
industry
isFNOSec
}
metadata {
listingDate
status
}
}
}
}

# Get indices data
query GetIndices {
indices(filter: { filterBy: "NIFTY" }) {
key
index
last
variation
percentChange
}
}

GraphQL Schema

The API includes schemas for:

  • Equity - Stock information, metadata, and details
  • Indices - Market index data and performance
  • Filters - Flexible query filtering options

🤖 MCP Server

The project includes a Model Context Protocol (MCP) server that allows AI assistants to access NSE India stock market data:

What is MCP?

Model Context Protocol (MCP) is a standard for AI assistants to communicate with external data sources and tools. This MCP server exposes all NSE India functions as tools that AI models can use.

Architecture

The MCP implementation is built with a modular architecture for maintainability and consistency:

  • src/mcp/mcp-tools.ts: Common tools configuration and handler functions shared across all implementations
  • src/mcp/server/mcp-server.ts: Stdio-based MCP server for local AI assistant integration
  • src/mcp/client/mcp-client.ts: OpenAI Functions-based MCP client for natural language queries

All components share the same tool definitions and business logic, ensuring consistency and making maintenance easier.

Benefits of Common Tools Configuration

  • 🔄 Consistency: All server implementations use identical tool definitions and behavior
  • 🛠️ Maintainability: Single source of truth for tool configurations and business logic
  • 📝 Easy Updates: Add new tools or modify existing ones in one place
  • 🧪 Testing: Unified testing approach across all server implementations
  • 📚 Documentation: Centralized tool documentation and examples

Available Tools

The MCP server provides 30 tools covering:

  • Equity Data - Stock details, trade info, corporate info, intraday data, historical data, technical indicators
  • Index Data - Market indices, intraday data, option chains, contract information
  • Market Data - Market status, turnover, pre-open data, all indices
  • Reports - Circulars, daily reports for capital/derivatives/debt markets
  • Commodity Data - Option chain data for commodities
  • Analysis Tools - Top gainers/losers, most active equities

OpenAI Functions MCP Client

The project includes an advanced MCP client that uses OpenAI's native function calling feature for intelligent query processing:

Features

  • 🤖 Natural Language Processing: Query data using plain English
  • 🔧 Automatic Tool Selection: AI intelligently chooses the right NSE API tools
  • 📊 Real-time Data: Access live market data, historical information, and more
  • 🎯 Smart Parameter Extraction: Automatically extracts symbols, dates, and other parameters
  • 📈 Comprehensive Coverage: Access to all 30 NSE India API endpoints
  • 🔄 Multiple Query Types: Support for both simple and complex multi-step queries

Query Methods

  • processQuery(): Single-round query processing for straightforward requests
  • processQueryWithMultipleFunctions(): Multi-step query processing for complex analysis

Example Usage

import { mcpClient } from './mcp/client/mcp-client'

// Simple query
const response = await mcpClient.processQuery({
query: "What is the current price of TCS stock?",
model: "gpt-4o-mini"
})

// Complex multi-step query
const complexResponse = await mcpClient.processQueryWithMemory({
query: "Compare the performance of Reliance and TCS over the last month and analyze their trends"
})

Usage

Standard I/O (stdio) Server

# Start the stdio MCP server
npm run start:mcp

# Test the stdio MCP server
npm run test:mcp

Configuration

Option 1: Using npx (Recommended for users who have installed the package)

Installation Steps:

  1. Prerequisites: Ensure Node.js 18+ is installed on your system

    node --version  # Should be v18.0.0 or higher
    
  2. Install the package (optional but recommended for faster startup):

    npm install -g stock-nse-india
    

    Note: If you don't install globally, npx will automatically download and cache the package on first use, which may take a few moments.

Configuration:

{
"mcpServers": {
"npx-stock-nse-india": {
"command": "npx",
"args": ["stock-nse-india", "mcp"],
"env": {
"NODE_ENV": "production"
}
}
}
}

Option 2: Using local build (For developers with source code)

{
"mcpServers": {
"nse-india-stdio": {
"command": "node",
"args": ["build/mcp/server/mcp-server-stdio.js"],
"env": {
"NODE_ENV": "production"
}
}
}
}

Configuring in Cursor IDE

  1. Open Cursor Settings: Press Cmd+, (Mac) or Ctrl+, (Windows/Linux) to open settings
  2. Navigate to MCP Settings: Go to Settings → Features → Model Context Protocol
  3. Add Server Configuration: Add either of the configurations above to your MCP settings
  4. Restart Cursor: Restart Cursor IDE to load the MCP server

Alternatively, you can directly edit the Cursor configuration file:

  • Mac/Linux: ~/.cursor/mcp.json or in your workspace settings
  • Windows: %APPDATA%\Cursor\mcp.json

After configuration, the MCP server will be available in Cursor's AI assistant, allowing you to query NSE India stock market data directly from the chat interface.

For detailed MCP documentation, see MCP_README.md.

🌐 REST API

Comprehensive REST endpoints with automatic Swagger documentation:

Core Endpoints

  • GET / - Market status
  • GET /api/marketStatus - Market status information
  • GET /api/glossary - NSE glossary
  • GET /api/equity/:symbol - Equity details
  • GET /api/equity/:symbol/historical - Historical data
  • GET /api/indices - Market indices
  • GET /api-docs - Interactive API documentation

MCP Client Endpoints

  • POST /api/mcp/query - Natural language query using OpenAI Functions
  • POST /api/mcp/query-multiple - Multi-step natural language queries

API Documentation

Visit http://localhost:3000/api-docs for complete interactive API documentation powered by Swagger UI.

💻 CLI Usage

Basic Commands

# Get help
nseindia --help

# Get market status
nseindia

# Get equity details
nseindia equity IRCTC

# Get historical data
nseindia historical IRCTC

# Get indices information
nseindia index

# Get specific index details
nseindia index "NIFTY AUTO"

CLI Features

  • Real-time data - Live market information
  • Historical analysis - Historical price data
  • Index tracking - Market index performance
  • Interactive charts - ASCII-based data visualization

🐳 Docker

Quick Start

# Pull and run from Docker Hub
docker run --rm -d -p 3001:3001 imcodeman/nseindia

# Or build locally
docker build -t nseindia . && docker run --rm -d -p 3001:3001 nseindia:latest

Docker Hub

Image: imcodeman/nseindia
Registry: Docker Hub

Container URLs

⚙️ Configuration

Environment Variables

# Server Configuration
PORT=3000
HOST_URL=http://localhost:3000
NODE_ENV=development

# CORS Configuration
CORS_ORIGINS=https://myapp.com,https://admin.myapp.com
CORS_METHODS=GET,POST,OPTIONS
CORS_HEADERS=Content-Type,Authorization,X-Requested-With
CORS_CREDENTIALS=true

CORS Settings

  • Origins: Comma-separated list of allowed domains
  • Methods: HTTP methods (default: GET,POST,PUT,DELETE,OPTIONS)
  • Headers: Allowed request headers
  • Credentials: Enable/disable credentials (default: true)
  • Localhost: Always allowed for development

📊 API Methods

Core Methods

  • getAllStockSymbols() - Get all NSE stock symbols
  • getData() - Generic data retrieval
  • getDataByEndpoint() - Get data by specific NSE API endpoints

Equity Methods

  • getEquityDetails(symbol) - Get equity information
  • getEquityHistoricalData(symbol, range) - Historical price data
  • getEquityIntradayData(symbol) - Intraday trading data
  • getEquityOptionChain(symbol) - Options chain data
  • getEquityCorporateInfo(symbol) - Corporate information
  • getEquityTradeInfo(symbol) - Trading statistics

Index Methods

  • getEquityStockIndices() - Get all market indices
  • getIndexIntradayData(index) - Index intraday data
  • getIndexOptionChain(index) - Index options data
  • getIndexOptionChainContractInfo(indexSymbol) - Get option chain contract information (expiry dates and strike prices)

Commodity Methods

  • getCommodityOptionChain(symbol) - Commodity options data

Helper Methods

  • getGainersAndLosersByIndex(index) - Top gainers and losers
  • getMostActiveEquities() - Most actively traded stocks

🏃‍♂️ Development

⚠️ Prerequisites: Node.js 18+ required

Local Development

# Clone repository
git clone https://github.com/hi-imcodeman/stock-nse-india.git
cd stock-nse-india

# Install dependencies
npm install

# Development mode with auto-reload
npm run start:dev

# Build project
npm run build

# Run tests
npm test

# Generate documentation
npm run docs

Development Scripts

  • npm start - Start production server
  • npm run start:dev - Development mode with auto-reload
  • npm run build - Build TypeScript to JavaScript
  • npm test - Run test suite with coverage
  • npm run docs - Generate TypeDoc documentation
  • npm run lint - Run ESLint

MCP Scripts

  • npm run start:mcp - Start stdio MCP server
  • npm run test:mcp - Test stdio MCP server

🧪 Testing

# Run all tests
npm test

# Run tests with coverage
npm test -- --coverage

# Run specific test file
npm test -- utils.spec.ts

📚 Documentation

🤝 Contributing

We welcome contributions! Please see our contributing guidelines and feel free to submit issues and pull requests.

Development Setup

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes
  4. Add tests for new functionality
  5. Ensure all tests pass
  6. Submit a pull request

📄 License

This project is licensed under the MIT License - see the LICENSE file for details.

👥 Contributors

🔗 Links


⭐ Star this repository if you find it helpful!

Generated using TypeDoc

================================================ FILE: docs/interfaces/AllIndicesData.html ================================================ AllIndicesData | stock-nse-india - v1.3.0

Interface AllIndicesData

All indices data

Hierarchy

  • AllIndicesData

Properties

Properties

data: {
    change: number;
    ffmc_sum: number;
    high: number;
    indexName: string;
    last: number;
    low: number;
    open: number;
    percChange: number;
    previousClose: number;
    timeVal: string;
    totalTradedValue: number;
    totalTradedVolume: number;
    yearHigh: number;
    yearLow: number;
}[]

Type declaration

  • change: number
  • ffmc_sum: number
  • high: number
  • indexName: string
  • last: number
  • low: number
  • open: number
  • percChange: number
  • previousClose: number
  • timeVal: string
  • totalTradedValue: number
  • totalTradedVolume: number
  • yearHigh: number
  • yearLow: number

Generated using TypeDoc

================================================ FILE: docs/interfaces/CircularsData.html ================================================ CircularsData | stock-nse-india - v1.3.0

Interface CircularsData

Circulars data from NSE

Hierarchy

  • CircularsData

Properties

Properties

data: {
    cirDate: string;
    cirDisplayDate: string;
    circCompany: string;
    circDisplayNo: string;
    circFilelink: string;
    circFilename: string;
    circNumber: string;
    fileDept: string;
    fileExt: string;
    sub: string;
}[]

Type declaration

  • cirDate: string
  • cirDisplayDate: string
  • circCompany: string
  • circDisplayNo: string
  • circFilelink: string
  • circFilename: string
  • circNumber: string
  • fileDept: string
  • fileExt: string
  • sub: string
fromDate: string
toDate: string

Generated using TypeDoc

================================================ FILE: docs/interfaces/CommodityOptionChainData.html ================================================ CommodityOptionChainData | stock-nse-india - v1.3.0

Generated using TypeDoc

================================================ FILE: docs/interfaces/CommodityRecords.html ================================================ CommodityRecords | stock-nse-india - v1.3.0

Interface CommodityRecords

Commodity option chain records with numeric strike prices

Hierarchy

  • Records
    • CommodityRecords

Properties

data: Datum[]
expiryDates: string[]
strikePrices: number[]
timestamp: string
underlyingValue: number

Generated using TypeDoc

================================================ FILE: docs/interfaces/DateRange.html ================================================ DateRange | stock-nse-india - v1.3.0

Generated using TypeDoc

================================================ FILE: docs/interfaces/Datum.html ================================================ Datum | stock-nse-india - v1.3.0

Generated using TypeDoc

================================================ FILE: docs/interfaces/EquityCorporateInfo.html ================================================ EquityCorporateInfo | stock-nse-india - v1.3.0

Interface EquityCorporateInfo

Corporate information including announcements, actions, and financial results

Hierarchy

  • EquityCorporateInfo

Properties

borad_meeting: {
    data: {
        meetingdate: string;
        purpose: string;
        symbol: string;
    }[];
}

Type declaration

  • data: {
        meetingdate: string;
        purpose: string;
        symbol: string;
    }[]
corporate_actions: {
    data: {
        exdate: string;
        purpose: string;
        symbol: string;
    }[];
}

Type declaration

  • data: {
        exdate: string;
        purpose: string;
        symbol: string;
    }[]
financial_results: {
    data: {
        audited: string;
        consolidated: string;
        cumulative: null | string;
        expenditure: null | string;
        from_date: null | string;
        income: string;
        na_attachment: null | string;
        proLossAftTax: string;
        reDilEPS: string;
        reProLossBefTax: string;
        re_broadcast_timestamp: string;
        to_date: string;
        xbrl_attachment: string;
    }[];
}

Type declaration

  • data: {
        audited: string;
        consolidated: string;
        cumulative: null | string;
        expenditure: null | string;
        from_date: null | string;
        income: string;
        na_attachment: null | string;
        proLossAftTax: string;
        reDilEPS: string;
        reProLossBefTax: string;
        re_broadcast_timestamp: string;
        to_date: string;
        xbrl_attachment: string;
    }[]
latest_announcements: {
    data: {
        broadcastdate: string;
        subject: string;
        symbol: string;
    }[];
}

Type declaration

  • data: {
        broadcastdate: string;
        subject: string;
        symbol: string;
    }[]
shareholdings_patterns: {
    data: {
        [date: string]: {
            [key: string]: string;
        }[];
    };
}

Type declaration

  • data: {
        [date: string]: {
            [key: string]: string;
        }[];
    }
    • [date: string]: {
          [key: string]: string;
      }[]

Generated using TypeDoc

================================================ FILE: docs/interfaces/EquityDetails.html ================================================ EquityDetails | stock-nse-india - v1.3.0

Interface EquityDetails

Detailed equity information including price, metadata, and market data

Hierarchy

  • EquityDetails

Properties

currentMarketType: string
industryInfo: {
    basicIndustry: string;
    industry: string;
    macro: string;
    sector: string;
}

Type declaration

  • basicIndustry: string
  • industry: string
  • macro: string
  • sector: string
metadata: EquityMetadata
preOpenMarket: EquityPreOpenMarket
priceInfo: EquityPriceInfo
sddDetails: {
    SDDAuditor: string;
    SDDStatus: string;
}

Type declaration

  • SDDAuditor: string
  • SDDStatus: string
securityInfo: EquitySecurityInfo

Generated using TypeDoc

================================================ FILE: docs/interfaces/EquityHistoricalData.html ================================================ EquityHistoricalData | stock-nse-india - v1.3.0

Interface EquityHistoricalData

Historical equity data with price and volume information

Hierarchy

  • EquityHistoricalData

Properties

Properties

meta: {
    fromDate: string;
    series: string[];
    symbols: string[];
    toDate: string;
}

Type declaration

  • fromDate: string
  • series: string[]
  • symbols: string[]
  • toDate: string

Generated using TypeDoc

================================================ FILE: docs/interfaces/EquityHistoricalInfo.html ================================================ EquityHistoricalInfo | stock-nse-india - v1.3.0

Interface EquityHistoricalInfo

Historical equity price and volume information for a single day

Hierarchy

  • EquityHistoricalInfo

Properties

ch52WeekHighPrice: number
ch52WeekLowPrice: number
chClosingPrice: number
chLastTradedPrice: number
chOpeningPrice: number
chPreviousClsPrice: number
chSeries: string
chSymbol: string
chTotTradedQty: number
chTotTradedVal: number
chTotalTrades: number
chTradeHighPrice: number
chTradeLowPrice: number
mtimestamp: string
vwap: number

Generated using TypeDoc

================================================ FILE: docs/interfaces/EquityInfo.html ================================================ EquityInfo | stock-nse-india - v1.3.0

Interface EquityInfo

Equity information including company details and security metadata

Hierarchy

  • EquityInfo

Properties

activeSeries: string[]
companyName: string
debtSeries: string[]
identifier: string
industry: string
isCASec: boolean
isDebtSec: boolean
isDelisted: boolean
isETFSec: boolean
isFNOSec: boolean
isHybridSymbol: boolean
isMunicipalBond: boolean
isSLBSec: boolean
isSuspended: boolean
isTop10: boolean
isin: string
listingDate: string
segment: string
slb_isin: string
symbol: string
tempSuspendedSeries: string[]

Generated using TypeDoc

================================================ FILE: docs/interfaces/EquityMaster.html ================================================ EquityMaster | stock-nse-india - v1.3.0

Generated using TypeDoc

================================================ FILE: docs/interfaces/EquityMetadata.html ================================================ EquityMetadata | stock-nse-india - v1.3.0

Interface EquityMetadata

Equity metadata including series, ISIN, status, and listing information

Hierarchy

  • EquityMetadata

Properties

industry: string
isin: string
lastUpdateTime: string
listingDate: string
pdSectorInd: string
pdSectorIndAll: string[]
pdSectorPe: number
pdSymbolPe: number
series: string
status: string
symbol: string

Generated using TypeDoc

================================================ FILE: docs/interfaces/EquityOptionChainData.html ================================================ EquityOptionChainData | stock-nse-india - v1.3.0

Generated using TypeDoc

================================================ FILE: docs/interfaces/EquityOptionChainItem.html ================================================ EquityOptionChainItem | stock-nse-india - v1.3.0

Interface EquityOptionChainItem

Individual equity option chain item with strike price and option details

Hierarchy

  • EquityOptionChainItem

Properties

change: number
changeinOpenInterest: number
closePrice: number
expiryDate: string
highPrice: number
identifier: string
instrumentType: string
lastPrice: number
lowPrice: number
openInterest: number
openPrice: number
optionType: string
pchange: number
pchangeinOpenInterest: number
prevClose: number
strikePrice: string
ticksize: number
totalTradedVolume: number
totalTurnover: number
underlying: string
underlyingValue: number
volumeFreezeQuantity: number

Generated using TypeDoc

================================================ FILE: docs/interfaces/EquityPreOpenMarket.html ================================================ EquityPreOpenMarket | stock-nse-india - v1.3.0

Interface EquityPreOpenMarket

Pre-open market data for equity including indicative equilibrium price

Hierarchy

  • EquityPreOpenMarket

Properties

IEP: number
ato: {
    buy: number;
    sell: number;
}

Type declaration

  • buy: number
  • sell: number
atoBuyQty: number
atoSellQty: number
finalPrice: number
finalQuantity: number
lastUpdateTime: string
preopen: PreOpenDetails[]
totalBuyQuantity: number
totalSellQuantity: number
totalTradedVolume: number

Generated using TypeDoc

================================================ FILE: docs/interfaces/EquityPriceInfo.html ================================================ EquityPriceInfo | stock-nse-india - v1.3.0

Interface EquityPriceInfo

Equity price information including current price, change, and trading bands

Hierarchy

  • EquityPriceInfo

Properties

basePrice: number
change: number
checkINAV: boolean
close: number
iNavValue: null | number
ieq: string
intraDayHighLow: {
    max: number;
    min: number;
    value: number;
}

Type declaration

  • max: number
  • min: number
  • value: number
lastPrice: number
lowerCP: string
open: number
pChange: number
pPriceBand: string
previousClose: number
stockIndClosePrice: number
tickSize: number
upperCP: string
vwap: number
weekHighLow: {
    max: number;
    maxDate: string;
    min: number;
    minDate: string;
    value: number;
}

Type declaration

  • max: number
  • maxDate: string
  • min: number
  • minDate: string
  • value: number

Generated using TypeDoc

================================================ FILE: docs/interfaces/EquitySecurityInfo.html ================================================ EquitySecurityInfo | stock-nse-india - v1.3.0

Interface EquitySecurityInfo

Equity security information including trading status and surveillance details

Hierarchy

  • EquitySecurityInfo

Properties

boardStatus: string
classOfShare: string
derivatives: string
faceValue: number
issuedSize: number
sessionNo: string
slb: string
surveillance: {
    desc: null | string;
    surv: null | string;
}

Type declaration

  • desc: null | string
  • surv: null | string
tradingSegment: string
tradingStatus: string

Generated using TypeDoc

================================================ FILE: docs/interfaces/EquityTradeInfo.html ================================================ EquityTradeInfo | stock-nse-india - v1.3.0

Interface EquityTradeInfo

Equity trade information including order book and trade statistics

Hierarchy

  • EquityTradeInfo

Properties

bulkBlockDeals: {
    name: string;
}[]

Type declaration

  • name: string
marketDeptOrderBook: {
    ask: {
        price: number;
        quantity: number;
    }[];
    bid: {
        price: number;
        quantity: number;
    }[];
    open: number;
    totalBuyQuantity: number;
    totalSellQuantity: number;
    tradeInfo: {
        activeSeries: string;
        cmAnnualVolatility: string;
        cmDailyVolatility: string;
        ffmc: number;
        impactCost: number;
        marketLot: string;
        totalMarketCap: number;
        totalTradedValue: number;
        totalTradedVolume: number;
    };
    valueAtRisk: {
        adhocMargin: number;
        applicableMargin: number;
        extremeLossMargin: number;
        indexVar: number;
        securityVar: number;
        varMargin: number;
    };
}

Type declaration

  • ask: {
        price: number;
        quantity: number;
    }[]
  • bid: {
        price: number;
        quantity: number;
    }[]
  • open: number
  • totalBuyQuantity: number
  • totalSellQuantity: number
  • tradeInfo: {
        activeSeries: string;
        cmAnnualVolatility: string;
        cmDailyVolatility: string;
        ffmc: number;
        impactCost: number;
        marketLot: string;
        totalMarketCap: number;
        totalTradedValue: number;
        totalTradedVolume: number;
    }
    • activeSeries: string
    • cmAnnualVolatility: string
    • cmDailyVolatility: string
    • ffmc: number
    • impactCost: number
    • marketLot: string
    • totalMarketCap: number
    • totalTradedValue: number
    • totalTradedVolume: number
  • valueAtRisk: {
        adhocMargin: number;
        applicableMargin: number;
        extremeLossMargin: number;
        indexVar: number;
        securityVar: number;
        varMargin: number;
    }
    • adhocMargin: number
    • applicableMargin: number
    • extremeLossMargin: number
    • indexVar: number
    • securityVar: number
    • varMargin: number
noBlockDeals: boolean
securityWiseDP: {
    deliveryQuantity: number;
    deliveryToTradedQuantity: number;
    quantityTraded: number;
    secWiseDelPosDate: string;
    seriesRemarks: null | string;
}

Type declaration

  • deliveryQuantity: number
  • deliveryToTradedQuantity: number
  • quantityTraded: number
  • secWiseDelPosDate: string
  • seriesRemarks: null | string

Generated using TypeDoc

================================================ FILE: docs/interfaces/Filtered.html ================================================ Filtered | stock-nse-india - v1.3.0

Generated using TypeDoc

================================================ FILE: docs/interfaces/GiftNifty.html ================================================ GiftNifty | stock-nse-india - v1.3.0

Interface GiftNifty

Gift Nifty (formerly SGX Nifty) futures data

Hierarchy

  • GiftNifty

Properties

CONTRACTSTRADED: number
DAYCHANGE: string
EXPIRYDATE: string
INSTRUMENTTYPE: string
LASTPRICE: number
OPTIONTYPE: string
PERCHANGE: string
STRIKEPRICE: string
SYMBOL: string
TIMESTMP: string
id: string

Generated using TypeDoc

================================================ FILE: docs/interfaces/Glossary.html ================================================ Glossary | stock-nse-india - v1.3.0

Interface Glossary

NSE glossary content

Hierarchy

  • Glossary

Properties

Properties

changed?: string
content: {
    body?: string;
    field_glossary_items?: any;
    field_labels?: any;
    field_reference?: any;
    field_unique_url?: string;
    title?: string;
    [key: string]: any;
}

Type declaration

  • [key: string]: any
  • Optional body?: string
  • Optional field_glossary_items?: any
  • Optional field_labels?: any
  • Optional field_reference?: any
  • Optional field_unique_url?: string
  • Optional title?: string
id: string
type: string

Generated using TypeDoc

================================================ FILE: docs/interfaces/Holiday.html ================================================ Holiday | stock-nse-india - v1.3.0

Generated using TypeDoc

================================================ FILE: docs/interfaces/HolidaysBySegment.html ================================================ HolidaysBySegment | stock-nse-india - v1.3.0

Generated using TypeDoc

================================================ FILE: docs/interfaces/IndexDetails.html ================================================ IndexDetails | stock-nse-india - v1.3.0

Interface IndexDetails

Detailed index information including constituent stocks and metadata

Hierarchy

  • IndexDetails

Properties

advance: {
    advances: string;
    declines: string;
    unchanged: string;
}

Type declaration

  • advances: string
  • declines: string
  • unchanged: string
date30dAgo: string
date365dAgo: string
marketStatus: {
    index: string;
    last: number;
    market: string;
    marketStatus: string;
    marketStatusMessage: string;
    percentChange: number;
    tradeDate: string;
    variation: number;
}

Type declaration

  • index: string
  • last: number
  • market: string
  • marketStatus: string
  • marketStatusMessage: string
  • percentChange: number
  • tradeDate: string
  • variation: number
metadata: {
    change: number;
    chart30dPath: string;
    chart365dPath: string;
    chartTodayPath: string;
    date30dAgo: string;
    date365dAgo: string;
    ffmc_sum: number;
    high: number;
    indexName: string;
    indicativeClose: number;
    last: number;
    low: number;
    open: number;
    perChange30d: number;
    perChange365d: number;
    percChange: number;
    previousClose: number;
    timeVal: string;
    totalTradedValue: number;
    totalTradedVolume: number;
    yearHigh: number;
    yearLow: number;
}

Type declaration

  • change: number
  • chart30dPath: string
  • chart365dPath: string
  • chartTodayPath: string
  • date30dAgo: string
  • date365dAgo: string
  • ffmc_sum: number
  • high: number
  • indexName: string
  • indicativeClose: number
  • last: number
  • low: number
  • open: number
  • perChange30d: number
  • perChange365d: number
  • percChange: number
  • previousClose: number
  • timeVal: string
  • totalTradedValue: number
  • totalTradedVolume: number
  • yearHigh: number
  • yearLow: number
name: string
timestamp: string

Generated using TypeDoc

================================================ FILE: docs/interfaces/IndexEquityInfo.html ================================================ IndexEquityInfo | stock-nse-india - v1.3.0

Interface IndexEquityInfo

Index constituent equity information

Hierarchy

  • IndexEquityInfo

Properties

change: number
chart30dPath: string
chart365dPath: string
chartTodayPath: string
date30dAgo: string
date365dAgo: string
dayHigh: number
dayLow: number
ffmc: number
identifier: string
lastPrice: number
lastUpdateTime: string
meta?: EquityInfo
nearWKH: number
nearWKL: number
open: number
pChange: number
perChange30d: number
perChange365d: number
previousClose: number
priority: number
series: string
stockIndClosePrice: number
symbol: string
totalTradedValue: number
totalTradedVolume: number
yearHigh: number
yearLow: number

Generated using TypeDoc

================================================ FILE: docs/interfaces/IndexNamesData.html ================================================ IndexNamesData | stock-nse-india - v1.3.0

Generated using TypeDoc

================================================ FILE: docs/interfaces/IndexOptionChainData.html ================================================ IndexOptionChainData | stock-nse-india - v1.3.0

Generated using TypeDoc

================================================ FILE: docs/interfaces/IndexRecords.html ================================================ IndexRecords | stock-nse-india - v1.3.0

Interface IndexRecords

Index option chain records with string strike prices

Hierarchy

  • Records
    • IndexRecords

Properties

data: Datum[]
expiryDates: string[]
strikePrices: string[]
timestamp: string
underlyingValue: number

Generated using TypeDoc

================================================ FILE: docs/interfaces/IndicativeNifty50.html ================================================ IndicativeNifty50 | stock-nse-india - v1.3.0

Interface IndicativeNifty50

Indicative Nifty 50 index information

Hierarchy

  • IndicativeNifty50

Properties

change: number
closingValue: number
dateTime: string
finalClosingValue: number
indexLast: null | number
indexName: string
indexPercChange: null | number
indexTimeVal: null | string
indicativeTime: null | string
perChange: number
status: string

Generated using TypeDoc

================================================ FILE: docs/interfaces/IntradayData.html ================================================ IntradayData | stock-nse-india - v1.3.0

Generated using TypeDoc

================================================ FILE: docs/interfaces/LatestCircularData.html ================================================ LatestCircularData | stock-nse-india - v1.3.0

Interface LatestCircularData

Latest circular data from NSE

Hierarchy

  • LatestCircularData

Properties

Properties

data: {
    cirDate: string;
    cirDisplayDate: string;
    circCompany: string;
    circDisplayNo: string;
    circFilelink: string;
    circFilename: string;
    circNumber: string;
    fileDept: string;
    fileExt: string;
    sub: string;
}[]

Type declaration

  • cirDate: string
  • cirDisplayDate: string
  • circCompany: string
  • circDisplayNo: string
  • circFilelink: string
  • circFilename: string
  • circNumber: string
  • fileDept: string
  • fileExt: string
  • sub: string

Generated using TypeDoc

================================================ FILE: docs/interfaces/MarketCap.html ================================================ MarketCap | stock-nse-india - v1.3.0

Interface MarketCap

Market capitalization information

Hierarchy

  • MarketCap

Properties

marketCapinCRRupees: number
marketCapinCRRupeesFormatted: string
marketCapinLACCRRupees: number
marketCapinLACCRRupeesFormatted: string
marketCapinTRDollars: number
timeStamp: string
underlying: string

Generated using TypeDoc

================================================ FILE: docs/interfaces/MarketState.html ================================================ MarketState | stock-nse-india - v1.3.0

Interface MarketState

Market state information including status and trading details

Hierarchy

  • MarketState

Properties

expiryDate?: string
index: string
last: string | number
market: string
marketStatus: string
marketStatusMessage: string
percentChange: string | number
slickclass?: string
tradeDate: string
tradeDateFormatted?: string
underlying?: string
updated_time?: string
variation: string | number

Generated using TypeDoc

================================================ FILE: docs/interfaces/MarketStatus.html ================================================ MarketStatus | stock-nse-india - v1.3.0

Generated using TypeDoc

================================================ FILE: docs/interfaces/MarketTurnover.html ================================================ MarketTurnover | stock-nse-india - v1.3.0

Generated using TypeDoc

================================================ FILE: docs/interfaces/MergedDailyReportsData.html ================================================ MergedDailyReportsData | stock-nse-india - v1.3.0

Generated using TypeDoc

================================================ FILE: docs/interfaces/OptionChainContractInfo.html ================================================ OptionChainContractInfo | stock-nse-india - v1.3.0

Generated using TypeDoc

================================================ FILE: docs/interfaces/OptionsData.html ================================================ OptionsData | stock-nse-india - v1.3.0

Generated using TypeDoc

================================================ FILE: docs/interfaces/OptionsDetails.html ================================================ OptionsDetails | stock-nse-india - v1.3.0

Interface OptionsDetails

Detailed options information including open interest, volume, and pricing

Hierarchy

  • OptionsDetails

Properties

askPrice?: number
askQty?: number
bidQty?: number
bidprice?: number
buyPrice1?: number
buyQuantity1?: number
change: number
changeinOpenInterest: number
expiryDate: null | string
identifier: null | string
impliedVolatility: number
lastPrice: number
openInterest: number
optionType: null | string
pChange?: number
pchange?: number
pchangeinOpenInterest: number
sellPrice1?: number
sellQuantity1?: number
strikePrice: number
totalBuyQuantity: number
totalSellQuantity: number
totalTradedVolume: number
underlying: null | string
underlyingValue: number

Generated using TypeDoc

================================================ FILE: docs/interfaces/PreOpenDetails.html ================================================ PreOpenDetails | stock-nse-india - v1.3.0

Generated using TypeDoc

================================================ FILE: docs/interfaces/PreOpenMarketData.html ================================================ PreOpenMarketData | stock-nse-india - v1.3.0

Interface PreOpenMarketData

Pre-open market data

Hierarchy

  • PreOpenMarketData

Properties

advances: number
data: {
    detail?: any;
    metadata: {
        companyName: string;
        industry: string;
        isinCode: string;
        lastUpdateTime?: string;
        listingDate?: string;
        series?: string;
        status?: string;
        symbol: string;
    };
    priceInfo?: {
        change: number;
        close: number;
        high: number;
        lastPrice: number;
        low: number;
        open: number;
        pChange: number;
        prevClose: number;
        totalTradedValue: number;
        totalTradedVolume: number;
    };
}[]

Type declaration

  • Optional detail?: any
  • metadata: {
        companyName: string;
        industry: string;
        isinCode: string;
        lastUpdateTime?: string;
        listingDate?: string;
        series?: string;
        status?: string;
        symbol: string;
    }
    • companyName: string
    • industry: string
    • isinCode: string
    • Optional lastUpdateTime?: string
    • Optional listingDate?: string
    • Optional series?: string
    • Optional status?: string
    • symbol: string
  • Optional priceInfo?: {
        change: number;
        close: number;
        high: number;
        lastPrice: number;
        low: number;
        open: number;
        pChange: number;
        prevClose: number;
        totalTradedValue: number;
        totalTradedVolume: number;
    }
    • change: number
    • close: number
    • high: number
    • lastPrice: number
    • low: number
    • open: number
    • pChange: number
    • prevClose: number
    • totalTradedValue: number
    • totalTradedVolume: number
declines: number
timestamp: string
totalTradedValue: number
totalTradedVolume: number
totalmarketcap: number
unchanged: number

Generated using TypeDoc

================================================ FILE: docs/interfaces/SeriesData.html ================================================ SeriesData | stock-nse-india - v1.3.0

Generated using TypeDoc

================================================ FILE: docs/interfaces/TechnicalIndicators.html ================================================ TechnicalIndicators | stock-nse-india - v1.3.0

Interface TechnicalIndicators

Technical indicators including SMA, EMA, RSI, MACD, Bollinger Bands, etc.

Hierarchy

  • TechnicalIndicators

Properties

ad: number[]
adx: number[]
atr: number[]
bollingerBands: {
    lower: number[];
    middle: number[];
    upper: number[];
}

Type declaration

  • lower: number[]
  • middle: number[]
  • upper: number[]
cci: number[]
ema: {
    [key: string]: number[];
}

Type declaration

  • [key: string]: number[]
macd: {
    histogram: number[];
    macd: number[];
    signal: number[];
}

Type declaration

  • histogram: number[]
  • macd: number[]
  • signal: number[]
mfi: number[]
momentum: number[]
obv: number[]
roc: number[]
rsi: number[]
sma: {
    [key: string]: number[];
}

Type declaration

  • [key: string]: number[]
stochastic: {
    d: number[];
    k: number[];
}

Type declaration

  • d: number[]
  • k: number[]
vwap: number[]
williamsR: number[]

Generated using TypeDoc

================================================ FILE: docs/modules.html ================================================ stock-nse-india - v1.3.0

Generated using TypeDoc

================================================ FILE: examples/basic.js ================================================ // import { NseIndia } from 'stock-nse-india' const { NseIndia } = require('../build/index') const nse = new NseIndia() nse.getAllStockSymbols().then(symbols => { console.log(symbols); }) ================================================ FILE: jest.config.js ================================================ module.exports = { preset: 'ts-jest', testEnvironment: 'node', roots: ['/src'], transform: { '^.+\\.tsx?$': 'ts-jest', }, coverageThreshold: { global: { branches: 97.73, functions: 100, lines: 100, statements: 100 } }, coverageReporters: ['json', 'lcov', 'text', 'clover'] } ================================================ FILE: mcp-config.json ================================================ { "mcpServers": { "nse-india-stdio": { "command": "node", "args": ["build/mcp/server/mcp-server-stdio.js"], "env": { "NODE_ENV": "production" } }, "npx-stock-nse-india": { "command": "npx", "args": ["stock-nse-india","mcp"], "env": { "NODE_ENV": "production" } } } } ================================================ FILE: package.json ================================================ { "name": "stock-nse-india", "version": "1.3.0", "description": "This package will help us to get equity/index details and historical data from National Stock Exchange of India.", "main": "build/index.js", "browser": false, "repository": "https://github.com/hi-imcodeman/stock-nse-india.git", "author": "Asraf Ali ", "license": "MIT", "bin": { "nseindia": "build/cli/index.js" }, "engines": { "node": ">=18" }, "scripts": { "remove-build": "rimraf ./build", "copy-graphql": "copyfiles -f ./src/**/*.graphql build/graphql-schema", "prebuild": "yarn remove-build", "build": "tsc", "postbuild": "yarn copy-graphql", "prestart": "yarn build", "start": "node build/server.js", "prestart:dev": "yarn remove-build", "start:dev": "NODE_ENV=development tsc-watch --onCompilationComplete 'yarn copy-graphql' --onSuccess 'node build/server.js'", "start:mcp": "node build/mcp/server/mcp-server.js", "demo:mcp-client": "node demo/mcp-client-demo.js", "demo:memory": "node demo/memory-example.js", "docs": "typedoc", "test": "jest --coverage --testTimeout=600000", "lint": "eslint ./src/**/*.ts", "gpr-setup": "node ./scripts/setup-gpr.js", "prepare": "husky install" }, "lint-staged": { "src/**/*.{ts,tsx,js,jsx}": [ "yarn lint --fix", "git add" ] }, "prepare": "husky install", "devDependencies": { "@types/express": "^4.17.17", "@types/jest": "^29.5.0", "@types/node": "^18.15.0", "@types/swagger-jsdoc": "^6.0.1", "@types/swagger-ui-express": "^4.1.6", "@types/user-agents": "^1.0.4", "@typescript-eslint/eslint-plugin": "^5.57.0", "@typescript-eslint/parser": "^5.57.0", "copyfiles": "^2.4.1", "eslint": "^8.38.0", "husky": "^8.0.3", "jest": "^29.5.0", "lint-staged": "^13.2.0", "rimraf": "^5.0.0", "ts-jest": "^29.1.0", "tsc-watch": "^6.0.4", "typedoc": "^0.24.8", "typescript": "^4.9.5" }, "dependencies": { "@graphql-tools/graphql-file-loader": "^7.5.13", "@graphql-tools/load": "^7.8.8", "@graphql-tools/load-files": "^6.6.1", "@graphql-tools/merge": "^8.3.14", "@modelcontextprotocol/sdk": "^1.17.5", "@types/cors": "^2.8.17", "apollo-server-core": "^3.10.0", "apollo-server-express": "^3.10.0", "asciichart": "^1.5.25", "axios": "^1.4.0", "chalk": "^4.1.2", "cheerio": "1.0.0-rc.10", "cors": "^2.8.5", "express": "^4.18.2", "graphql": "^16.6.0", "indicatorts": "^2.2.2", "mcp-remote": "^0.1.27", "moment": "^2.29.4", "moment-range": "^4.0.2", "ohlc": "^2.0.4", "openai": "^4.20.1", "ora": "^5.4.1", "swagger-jsdoc": "^6.2.8", "swagger-ui-express": "^4.6.3", "user-agents": "^1.0.104", "yargs": "^17.7.2" }, "keywords": [ "nse", "nseindia", "nse-india", "national-stock-exchange", "stock-market", "stock-exchange", "indian-stock-market", "equity", "shares", "stocks", "indices", "nifty", "sensex", "stock-data", "market-data", "historical-data", "intraday-data", "option-chain", "technical-indicators", "api", "rest-api", "graphql", "graphql-api", "mcp", "model-context-protocol", "mcp-server", "mcp-client", "openai", "ai-assistant", "cli", "command-line", "typescript", "nodejs", "express", "apollo-server", "swagger", "india", "bse", "nse-api", "stock-market-api", "financial-data", "trading", "investment" ], "bugs": { "url": "https://github.com/hi-imcodeman/stock-nse-india/issues" }, "homepage": "https://hi-imcodeman.github.io/stock-nse-india" } ================================================ FILE: scripts/setup-gpr.js ================================================ const fs = require('fs') const { join } = require('path') const pkg = require('../package.json') pkg.name = `@hi-imcodeman/${pkg.name}` fs.writeFileSync(join(__dirname, '../package.json'), JSON.stringify(pkg)) ================================================ FILE: src/__snapshots__/utils.spec.ts.snap ================================================ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`Utils getDataSchema for date value having typeStrict:false 1`] = ` [ "a: any", "b: any", { "c": "any", }, { "d": [ "a: any", { "b": "any", }, { "c": [ "d: any", ], }, { "e": "any", }, ], }, "e: any", { "f": "any", }, ] `; exports[`Utils getDataSchema for date value having typeStrict:false: array_validation 1`] = `"any"`; exports[`Utils getDataSchema with type strict 1`] = ` [ "a: number", "b: string | null", { "c": "number", }, { "d": [ "a: number", { "b": "number", }, { "c": [ "d: number", ], }, { "e": [], }, ], }, "e: Date", { "f": "number[]", }, ] `; exports[`Utils getDataSchema with type strict: array_validation 1`] = `"string[]"`; ================================================ FILE: src/cli/@types/asciichart.d.ts ================================================ declare module 'asciichart' ================================================ FILE: src/cli/@types/ohlc.d.ts ================================================ declare module 'ohlc' ================================================ FILE: src/cli/api.ts ================================================ /* eslint-disable @typescript-eslint/explicit-module-boundary-types */ /* eslint-disable no-console */ import { NseIndia, ApiList } from '../index' import ora from 'ora' import chalk from 'chalk' import ohlc from 'ohlc' import moment from 'moment' import asciichart from 'asciichart' const rupee = '₹' const nse = new NseIndia() export async function showIndexOverview(): Promise { const spinner = ora() spinner.text = 'Loading Indices deatils' spinner.start() const { data: allIndexData } = await nse.getDataByEndpoint(ApiList.ALL_INDICES) spinner.text = '' spinner.stop() const indexTypes = [ 'BROAD MARKET INDICES', 'SECTORAL INDICES', // 'STRATEGY INDICES', // 'THEMATIC INDICES', // 'FIXED INCOME INDICES' ] indexTypes.forEach(indexType => { const allIndexTableData = allIndexData .filter((item: any) => item.key === indexType) .map((item: any) => { return { // 'Index Name': item.index, 'Index Symbol': item.indexSymbol, 'Last Price': item.last, 'Previous Close': item.previousClose, 'Change': item.variation, 'Change Percent': item.percentChange, 'Open': item.open, 'High': item.high, 'Low': item.low, } }) console.log(`${indexType} Details`); console.table(allIndexTableData) }) } export async function showIndexDetails(argv: any): Promise { const { indexSymbol: index } = argv const spinner = ora() spinner.text = `Loading ${index} Details` spinner.start() const { data } = await nse.getEquityStockIndices(index) spinner.text = '' spinner.stop() if (data) { const indexTableData = data.map((item: any) => { return { 'Symbol': item.symbol, 'Open': item.open, 'High': item.dayHigh, 'Low': item.dayLow, 'Last Price': item.lastPrice, 'Previous Close': item.previousClose, 'Change': Number(item.change.toFixed(2)), 'Change Percent': item.pChange } }) console.log(`${index} deatils`); console.table(indexTableData); } else { console.log(chalk.red(`${index} index symbol is invalid. Try to enclose the index symbols with quotes.`)); } } export async function showMarketStatus(): Promise { const spinner = ora() spinner.text = 'Loading Market status' spinner.start() const { marketState } = await nse.getDataByEndpoint(ApiList.MARKET_STATUS) spinner.text = '' spinner.stop() console.table(marketState); } export async function showEquityDetails(argv: any): Promise { const { symbol } = argv const spinner = ora() spinner.text = 'Loading Equity details' spinner.start() try { const { info, priceInfo, metadata, securityInfo } = await nse.getEquityDetails(symbol) spinner.text = 'Loading Trading details' const { marketDeptOrderBook } = await nse.getEquityTradeInfo(symbol) spinner.text = '' spinner.stop() if (info && marketDeptOrderBook) { const { tradeInfo } = marketDeptOrderBook const changePrice = Number(priceInfo.change.toFixed(2)) const changePercent = Number(priceInfo.pChange.toFixed(2)) const tableData = { 'Last Updated Time': metadata.lastUpdateTime, 'Symbol': symbol, 'Company Name': info.companyName, 'Industry': metadata.industry, 'Sectoral Index': metadata.pdSectorInd.trim(), 'Sectoral PE': metadata.pdSectorPe, 'Symbol PE': metadata.pdSymbolPe, 'Listing Status': metadata.status, 'Listing Since': metadata.listingDate, [`Price Change (in ${rupee})`]: changePrice, 'Change Percentage (in %)': changePercent, 'Open': priceInfo.open, 'High': priceInfo.intraDayHighLow.max, 'Low': priceInfo.intraDayHighLow.min, 'Close': priceInfo.close, 'Previous Close': priceInfo.previousClose, 'Last Traded Price': priceInfo.lastPrice, 'Volume Weighted Average Price (VWAP)': priceInfo.vwap, 'Total Traded Volume': tradeInfo.totalTradedVolume, [`Total Traded Value (${rupee} Lakhs)`]: tradeInfo.totalTradedValue, [`Total Market Capital (${rupee} Lakhs)`]: tradeInfo.totalMarketCap } const changeStatus = changePrice <= 0 ? `${rupee}${changePrice} (${changePercent}%)${chalk.red('▼')}` : `${rupee}${changePrice} (${changePercent}%)${chalk.green('▲')}` const derivativeStatus = securityInfo.derivatives === 'Yes' ? chalk.black.bgGreen(' Derivatives ') : chalk.black.bgRed(' Derivatives ') const slbStatus = securityInfo.slb === 'Yes' ? chalk.black.bgGreen(' SLB ') : chalk.black.bgRed(' SLB ') const ltpStatus = changePrice <= 0 ? chalk.black.bgRed(` LTP: ${priceInfo.lastPrice} `) : chalk.black.bgGreen(` LTP: ${priceInfo.lastPrice} `) console.table(tableData) console.log(`Change: ${changeStatus}`) console.log(`${ltpStatus} ${derivativeStatus} ${slbStatus}`); } else { console.log(chalk.red('Please provide valid NSE symbol.')); } } catch (error:any) { spinner.text = '' spinner.stop() console.log(chalk.red(error.message)) } } export async function showHistorical(argv: any): Promise { console.time('Done In') const { symbol } = argv const spinner = ora() spinner.text = 'Loading Historical Data' spinner.start() const startDate = moment().subtract(3, 'months').format('YYYY-MM-DD') const results = await nse.getEquityHistoricalData(symbol, { start: new Date(startDate), end: new Date() }) spinner.text = '' spinner.stop() const ohlcData: any[] = [] results.forEach(({ data: historicalData }) => { historicalData.forEach(info => { ohlcData.push([ info.mtimestamp, info.chOpeningPrice, info.chTradeHighPrice, info.chTradeLowPrice, info.chClosingPrice, info.chTotTradedVal ]) }) }) const fullOhlcData = ohlc(ohlcData) console.log(); const ohlcDataFromStartDate = fullOhlcData.start(startDate).sma(5).toDaily() const CloseData = ohlcDataFromStartDate.map((obj: any) => obj.Close) const Volume = ohlcDataFromStartDate.map((obj: any) => obj.Volume / 100000) const chartConfig = { height: 10 } console.log(chalk.black.bgCyan(' Price Chart - SMA5 (Last 3 months) ')); console.log(); console.log(asciichart.plot(CloseData, { ...chartConfig, colors: [asciichart.cyan] })); console.log(); console.log(chalk.black.bgYellow(' Volume Chart - In Lakhs (Last 3 months) ')); console.log(); console.log(asciichart.plot(Volume, { ...chartConfig, colors: [asciichart.yellow] })); console.log(); console.timeEnd('Done In') } ================================================ FILE: src/cli/index.ts ================================================ #!/usr/bin/env node /* eslint-disable no-console */ import { showEquityDetails, showHistorical, showMarketStatus, showIndexDetails, showIndexOverview } from './api' import yargs from 'yargs' import { MCPServer } from '../mcp/server/mcp-server.js' // MCP Server handler function function startMCPServer() { console.log('🚀 Starting MCP stdio server...') try { // Create and start the MCP server directly const server = new MCPServer() console.log('📡 MCP stdio server is running. Connect your MCP client to this process.') console.log('💡 Use Ctrl+C to stop the server.') // Handle graceful shutdown process.on('SIGINT', () => { console.log('\n🛑 Shutting down MCP server...') process.exit(0) }) process.on('SIGTERM', () => { console.log('\n🛑 Shutting down MCP server...') process.exit(0) }) } catch (error) { console.error(`❌ Failed to start MCP server: ${error instanceof Error ? error.message : String(error)}`) process.exit(1) } } const _argv = yargs .command('$0', 'the default command', {}, showMarketStatus) .command('equity ', 'Get details of the symbol', (yargsBuilder: any) => { yargsBuilder.positional('symbol', { type: 'string', demandOption: true, describe: 'Symbol of NSE equities.' }) }, showEquityDetails) .command('historical ', 'Get historical chart of the symbol', (yargsBuilder: any) => { yargsBuilder.positional('symbol', { type: 'string', demandOption: true, describe: 'Symbol of NSE equities.' }) }, showHistorical) .command('index [indexSymbol]', 'Get details of the index.', (yargsBuilder: any) => { yargsBuilder.positional('indexSymbol', { type: 'string', demandOption: true, describe: 'Symbol of NSE Indices.' }) }, (argv: any) => { const { indexSymbol: index } = argv if (index) showIndexDetails(argv) else showIndexOverview() }) .command('mcp', 'Start MCP stdio server', (yargsBuilder: any) => { yargsBuilder .example('$0 mcp', 'Start MCP stdio server') .example('npx . mcp', 'Start MCP stdio server via npx') }, startMCPServer) .argv ================================================ FILE: src/constants.ts ================================================ export const API_RESPONSE_VALIDATION='API Response Validation' export const IS_TYPE_STRICT=false ================================================ FILE: src/equity.graphql ================================================ type Equity { symbol: String! details: EqutiyDetail } type EqutiyDetail { info: EquityInfo metadata: EquityMetadata } "It will return equity's information." type EquityInfo { symbol: String "Name of the company." companyName: String industry: String activeSeries: [String] debtSeries: [String] tempSuspendedSeries: [String] "Is it available for FNO option?" isFNOSec: Boolean isCASec: Boolean isSLBSec: Boolean isDebtSec: Boolean isSuspended: Boolean isETFSec: Boolean isDelisted: Boolean isin: String isTop10: Boolean identifier: String } "It will return metadata of the equity." type EquityMetadata { symbol: String series: String status: String listingDate: String industry: String pdSectorInd: String pdSectorPe: String pdSymbolPe: String lastUpdateTime: String } ================================================ FILE: src/helpers.spec.ts ================================================ import { getGainersAndLosersByIndex, getMostActiveEquities } from './helpers' describe('Helpers', () => { test('getGainersAndLosersByIndex', async () => { const data = await getGainersAndLosersByIndex("NIFTY 50") // expect(getDataSchema(data, IS_TYPE_STRICT)).toMatchSnapshot(API_RESPONSE_VALIDATION) const isLosers = data.losers.every((equityDetails) => equityDetails.pChange <= 0) const isGainers = data.gainers.every((equityDetails) => equityDetails.pChange > 0) expect(isLosers).toBeTruthy() expect(isGainers).toBeTruthy() }) test('getMostActiveEquities', async () => { const data = await getMostActiveEquities("NIFTY 50") // expect(getDataSchema(data, IS_TYPE_STRICT)).toMatchSnapshot(API_RESPONSE_VALIDATION) expect(data.byVolume[0] >= data.byVolume[1]).toBeTruthy() expect(data.byValue[0] >= data.byValue[1]).toBeTruthy() }) }) ================================================ FILE: src/helpers.ts ================================================ import { NseIndia } from './index' import { IndexEquityInfo, TechnicalIndicators, EquityHistoricalInfo } from './interface' import * as indicators from 'indicatorts' const nseIndia = new NseIndia() /** * * @param indexSymbol * @returns */ export const getGainersAndLosersByIndex = async (indexSymbol: string): Promise<{ gainers: IndexEquityInfo[], losers: IndexEquityInfo[] }> => { const indexData = await nseIndia.getEquityStockIndices(indexSymbol) const gainers: IndexEquityInfo[] = [] const losers: IndexEquityInfo[] = [] indexData.data.forEach((equityInfo: IndexEquityInfo) => { if (equityInfo.pChange > 0) gainers.push(equityInfo) else losers.push(equityInfo) }) return { gainers: [...gainers].sort((a, b) => b.pChange - a.pChange), losers: [...losers].sort((a, b) => a.pChange - b.pChange) } } /** * * @param indexSymbol * @returns */ export const getMostActiveEquities = async (indexSymbol: string): Promise<{ byVolume: IndexEquityInfo[], byValue: IndexEquityInfo[] }> => { const indexData = await nseIndia.getEquityStockIndices(indexSymbol) return { byVolume: [...indexData.data].sort((a, b) => b.totalTradedVolume - a.totalTradedVolume), byValue: [...indexData.data].sort((a, b) => b.totalTradedValue - a.totalTradedValue) } } /** * Get technical indicators for a specific equity symbol * @param symbol - The equity symbol (e.g., 'RELIANCE', 'TCS') * @param period - Number of days for historical data (default: 200) * @param options - Optional configuration for indicators * @returns Promise */ export const getTechnicalIndicators = async ( symbol: string, /* istanbul ignore next */ period = 200, /* istanbul ignore next */ options: { smaPeriods?: number[] // Array of periods for SMA (e.g., [5, 10, 20, 50]) emaPeriods?: number[] // Array of periods for EMA (e.g., [5, 10, 20, 50]) rsiPeriod?: number macdFast?: number macdSlow?: number macdSignal?: number bbPeriod?: number bbStdDev?: number stochK?: number stochD?: number williamsRPeriod?: number atrPeriod?: number adxPeriod?: number cciPeriod?: number mfiPeriod?: number rocPeriod?: number momentumPeriod?: number } = {} ): Promise => { try { // Get historical data for the symbol /* istanbul ignore next */ const endDate = new Date() /* istanbul ignore next */ const startDate = new Date() /* istanbul ignore next */ startDate.setDate(endDate.getDate() - period) /* istanbul ignore next */ const historicalDataArray = await nseIndia.getEquityHistoricalData( symbol, { start: startDate, end: endDate } ) // Flatten the array of historical data /* istanbul ignore next */ const historicalData = historicalDataArray.flatMap(data => data.data) /* istanbul ignore next */ if (!historicalData || historicalData.length === 0) { /* istanbul ignore next */ throw new Error(`No historical data found for symbol: ${symbol}`) } // Sort data by date (oldest first) const sortedData = historicalData.sort((a: EquityHistoricalInfo, b: EquityHistoricalInfo) => new Date(a.mtimestamp).getTime() - new Date(b.mtimestamp).getTime() ) // Extract OHLCV data const closes = sortedData.map((d: EquityHistoricalInfo) => d.chClosingPrice) const highs = sortedData.map((d: EquityHistoricalInfo) => d.chTradeHighPrice) const lows = sortedData.map((d: EquityHistoricalInfo) => d.chTradeLowPrice) const volumes = sortedData.map((d: EquityHistoricalInfo) => d.chTotTradedQty) // Set default periods const smaPeriods = options.smaPeriods || [5, 10, 20, 50, 100, 200] const emaPeriods = options.emaPeriods || [5, 10, 20, 50, 100, 200] const config = { rsiPeriod: options.rsiPeriod || 14, macdFast: options.macdFast || 12, macdSlow: options.macdSlow || 26, macdSignal: options.macdSignal || 9, bbPeriod: options.bbPeriod || 20, bbStdDev: options.bbStdDev || 2, stochK: options.stochK || 14, stochD: options.stochD || 3, williamsRPeriod: options.williamsRPeriod || 14, atrPeriod: options.atrPeriod || 14, adxPeriod: options.adxPeriod || 14, cciPeriod: options.cciPeriod || 20, mfiPeriod: options.mfiPeriod || 14, rocPeriod: options.rocPeriod || 10, momentumPeriod: options.momentumPeriod || 10 } // Calculate technical indicators // Dynamic SMAs const sma: { [key: string]: number[] } = {} smaPeriods.forEach(period => { sma[`sma${period}`] = indicators.sma(closes, { period }) }) // Dynamic EMAs const ema: { [key: string]: number[] } = {} emaPeriods.forEach(period => { ema[`ema${period}`] = indicators.ema(closes, { period }) }) const rsi = indicators.rsi(closes, { period: config.rsiPeriod }) const macdResult = indicators.macd(closes, { fast: config.macdFast, slow: config.macdSlow, signal: config.macdSignal }) const macd = { macd: macdResult.macdLine, signal: macdResult.signalLine, histogram: macdResult.macdLine.map((val: number, i: number) => val - macdResult.signalLine[i]) } const bbResult = indicators.bb(closes, { period: config.bbPeriod }) const bollingerBands = { upper: bbResult.upper, middle: bbResult.middle, lower: bbResult.lower } const stochResult = indicators.stoch(highs, lows, closes) const stochastic = { k: stochResult.k, d: stochResult.d } const williamsR = indicators.williamsR(highs, lows, closes) const atrResult = indicators.atr(highs, lows, closes, { period: config.atrPeriod }) const atr = atrResult.atrLine const adx = new Array(closes.length).fill(0) // ADX not available, using placeholder const obv = indicators.obv(closes, volumes) const cci = indicators.cci(highs, lows, closes) const mfi = indicators.mfi(highs, lows, closes, volumes) const roc = indicators.roc(closes, { period: config.rocPeriod }) const momentum = indicators.roc(closes, { period: config.momentumPeriod }) // Using ROC as momentum const ad = indicators.ad(highs, lows, closes, volumes) const vwap = indicators.vwap(closes, volumes) return { sma, ema, rsi, macd, bollingerBands, stochastic, williamsR, atr, adx, obv, cci, mfi, roc, momentum, ad, vwap } } catch (error) { /* istanbul ignore next */ const errorMessage = error instanceof Error ? error.message : 'Unknown error' /* istanbul ignore next */ throw new Error(`Failed to calculate technical indicators for ${symbol}: ${errorMessage}`) } } ================================================ FILE: src/index.charting.spec.ts ================================================ import axios from 'axios' import { NseIndia } from './index' jest.mock('axios') describe('NseIndia charting API tests', () => { const mockedAxios = axios as jest.Mocked beforeEach(() => { mockedAxios.get.mockReset() }) test('getChartingCookies refreshes and then reuses cached cookies', async () => { const nseIndia = new NseIndia() as any mockedAxios.get.mockResolvedValueOnce({ headers: { 'set-cookie': ['nsit=abc; Path=/', 'ak_bmsc=xyz; Path=/'] } } as any) const first = await nseIndia.getChartingCookies() expect(first).toBe('nsit=abc; ak_bmsc=xyz') expect(mockedAxios.get).toHaveBeenCalledTimes(1) const second = await nseIndia.getChartingCookies() expect(second).toBe('nsit=abc; ak_bmsc=xyz') expect(mockedAxios.get).toHaveBeenCalledTimes(1) }) test('getData falls back to charting cookies when NSE cookies fail', async () => { const nseIndia = new NseIndia() as any jest.spyOn(nseIndia, 'getNseCookies').mockResolvedValue('nse_cookie=primary') jest.spyOn(nseIndia, 'getChartingCookies').mockResolvedValue('chart_cookie=fallback') mockedAxios.get .mockRejectedValueOnce(new Error('primary cookie failed')) .mockResolvedValueOnce({ data: { status: true, data: [] } } as any) const result = await nseIndia.getData('https://charting.nseindia.com/v1/test', 'charting') expect(result).toEqual({ status: true, data: [] }) expect(mockedAxios.get).toHaveBeenCalledTimes(2) expect(mockedAxios.get.mock.calls[1][1]?.headers?.Cookie).toBe('chart_cookie=fallback') }) test('getEquitySymbolInfo throws when charting API returns empty list', async () => { const nseIndia = new NseIndia() as any jest.spyOn(nseIndia, 'getData').mockResolvedValue([]) await expect(nseIndia.getEquitySymbolInfo('ONGC')).rejects.toThrow( 'No symbol info found for: ONGC' ) }) test('getEquityChartHistoricalData uses default date range when range is omitted', async () => { const nseIndia = new NseIndia() as any jest.spyOn(nseIndia, 'getData').mockResolvedValue({ status: true, data: [] }) const response = await nseIndia.getEquityChartHistoricalData('ONGC', undefined, '2475') expect(response).toEqual({ status: true, data: [] }) expect(nseIndia.getData).toHaveBeenCalledWith( expect.stringContaining('symbolHistoricalData?fromDate='), 'charting' ) }) test('getEquitySymbolInfo falls back to first item when exact symbol is missing', async () => { const nseIndia = new NseIndia() as any jest.spyOn(nseIndia, 'getData').mockResolvedValue([ { symbol: 'ONGC', scripcode: '2475', companyName: 'Oil & Natural Gas Corporation', isin: 'INE213A01029', segment: 'CM', series: 'EQ' } ]) const info = await nseIndia.getEquitySymbolInfo('UNKNOWN') expect(info.symbol).toBe('ONGC') expect(info.scripcode).toBe('2475') }) }) ================================================ FILE: src/index.spec.ts ================================================ import { NseIndia, ApiList } from "./index"; jest.setTimeout(999999) describe('Class: NseIndia', () => { const symbol = 'ITC' const nseIndia = new NseIndia() test('getAllStockSymbols', async () => { const symbols = await nseIndia.getAllStockSymbols() expect(symbols.length).toBeGreaterThan(1000) }) test('getEquityDetails', async () => { const details = await nseIndia.getEquityDetails(symbol.toLowerCase()) // expect(getDataSchema(details,IS_TYPE_STRICT)).toMatchSnapshot(API_RESPONSE_VALIDATION) expect(details.info.symbol).toBe(symbol) }) test('getIndexOptionChain', async () => { const optionChain = await nseIndia.getIndexOptionChain('NIFTY') // expect(getDataSchema(details,IS_TYPE_STRICT)).toMatchSnapshot(API_RESPONSE_VALIDATION) expect(optionChain).toBeDefined() expect(optionChain).toHaveProperty('records') expect(optionChain).toHaveProperty('filtered') // Handle case where filtered or records might be null if (optionChain.filtered && optionChain.filtered.data && optionChain.filtered.data.length > 0) { const firstItem = optionChain.filtered.data[0] expect(firstItem.PE?.underlying || firstItem.CE?.underlying).toBe('NIFTY') } else if (optionChain.records && optionChain.records.data && optionChain.records.data.length > 0) { const firstItem = optionChain.records.data[0] expect(firstItem.PE?.underlying || firstItem.CE?.underlying).toBe('NIFTY') } // At least one of records or filtered should exist (even if null) expect(optionChain.records !== undefined && optionChain.filtered !== undefined).toBe(true) }) test('getIndexOptionChain with expiry', async () => { const expiry = '23-Dec-2025' const optionChain = await nseIndia.getIndexOptionChain('NIFTY', expiry) expect(optionChain).toBeDefined() expect(optionChain).toHaveProperty('records') expect(optionChain).toHaveProperty('filtered') // Handle case where filtered or records might be null if (optionChain.filtered && optionChain.filtered.data && optionChain.filtered.data.length > 0) { const firstItem = optionChain.filtered.data[0] expect(firstItem.PE?.underlying || firstItem.CE?.underlying).toBe('NIFTY') } else if (optionChain.records && optionChain.records.data && optionChain.records.data.length > 0) { const firstItem = optionChain.records.data[0] expect(firstItem.PE?.underlying || firstItem.CE?.underlying).toBe('NIFTY') } // At least one of records or filtered should exist (even if null) expect(optionChain.records !== undefined && optionChain.filtered !== undefined).toBe(true) }) test('getIndexOptionChainContractInfo', async () => { const contractInfo = await nseIndia.getIndexOptionChainContractInfo('NIFTY') expect(contractInfo).toBeDefined() expect(contractInfo.expiryDates).toBeDefined() expect(Array.isArray(contractInfo.expiryDates)).toBe(true) expect(contractInfo.expiryDates.length).toBeGreaterThan(0) expect(contractInfo.strikePrice).toBeDefined() expect(Array.isArray(contractInfo.strikePrice)).toBe(true) expect(contractInfo.strikePrice.length).toBeGreaterThan(0) }) test('getCommodityOptionChain', async () => { const optionChain = await nseIndia.getCommodityOptionChain('CRUDEOIL') // expect(getDataSchema(details,IS_TYPE_STRICT)).toMatchSnapshot(API_RESPONSE_VALIDATION) expect(optionChain).toBeDefined() expect(optionChain).toHaveProperty('records') expect(optionChain).toHaveProperty('filtered') // Handle case where filtered or records might be null if (optionChain.filtered && optionChain.filtered.data && optionChain.filtered.data.length > 0) { const firstItem = optionChain.filtered.data[0] expect(firstItem.PE?.underlying || firstItem.CE?.underlying).toBe('CRUDEOIL') } else if (optionChain.records && optionChain.records.data && optionChain.records.data.length > 0) { const firstItem = optionChain.records.data[0] expect(firstItem.PE?.underlying || firstItem.CE?.underlying).toBe('CRUDEOIL') } // At least one of records or filtered should exist (even if null) expect(optionChain.records !== undefined && optionChain.filtered !== undefined).toBe(true) }) test('getEquityOptionChain', async () => { const optionChain = await nseIndia.getEquityOptionChain('TCS') // expect(getDataSchema(details,IS_TYPE_STRICT)).toMatchSnapshot(API_RESPONSE_VALIDATION) expect(optionChain).toBeDefined() expect(optionChain).toHaveProperty('data') expect(optionChain).toHaveProperty('timestamp') expect(Array.isArray(optionChain.data)).toBe(true) expect(optionChain.data.length).toBeGreaterThan(0) const firstItem = optionChain.data[0] expect(firstItem).toHaveProperty('underlying') expect(firstItem.underlying).toBe('TCS') }) test('getEquityTradeInfo', async () => { const tradeInfo = await nseIndia.getEquityTradeInfo(symbol) // expect(getDataSchema(tradeInfo,IS_TYPE_STRICT)).toMatchSnapshot(API_RESPONSE_VALIDATION) expect(Object.keys(tradeInfo).length).toBeGreaterThan(3) }) test('getEquityCorporateInfo', async () => { const data = await nseIndia.getEquityCorporateInfo(symbol) // expect(getDataSchema(data,IS_TYPE_STRICT)).toMatchSnapshot(API_RESPONSE_VALIDATION) expect(data.latest_announcements.data[0].symbol).toBe(symbol) }) test('getEquityIntradayData', async () => { const intradayData = await nseIndia.getEquityIntradayData(symbol) // expect(getDataSchema(intradayData,IS_TYPE_STRICT)).toMatchSnapshot(API_RESPONSE_VALIDATION) expect(intradayData.name).toBe(symbol) expect(intradayData.grapthData).toBeDefined() expect(Array.isArray(intradayData.grapthData)).toBe(true) }) test('getEquityHistoricalData', async () => { const historicalData = await nseIndia.getEquityHistoricalData(symbol) // expect(getDataSchema(historicalData,IS_TYPE_STRICT)).toMatchSnapshot(API_RESPONSE_VALIDATION) expect(historicalData.length).toBeGreaterThan(1) expect(historicalData[historicalData.length - 1].data[0].chSymbol).toBe(symbol) }) test('getEquityHistoricalData with Date range', async () => { const range = { start: new Date("2021-03-10"), end: new Date("2021-03-20") } const historicalData = await nseIndia.getEquityHistoricalData(symbol, range) // expect(getDataSchema(historicalData,IS_TYPE_STRICT)).toMatchSnapshot(API_RESPONSE_VALIDATION) expect(historicalData[0].data[0].chSymbol).toBe(symbol) expect(historicalData[0].meta.fromDate).toBe('10-03-2021') expect(historicalData[0].meta.toDate).toBe('20-03-2021') }) test('getEquitySeries', async () => { const seriesData = await nseIndia.getEquitySeries(symbol) // expect(getDataSchema(seriesData,IS_TYPE_STRICT)).toMatchSnapshot(API_RESPONSE_VALIDATION) expect(seriesData.data.length).toBeGreaterThanOrEqual(1) }) test('getIndexIntradayData', async () => { const index = 'NIFTY 50' const intradayData = await nseIndia.getIndexIntradayData(index) // expect(getDataSchema(intradayData,IS_TYPE_STRICT)).toMatchSnapshot(API_RESPONSE_VALIDATION) expect(intradayData).toBeDefined() expect(intradayData.name).toBe(index) expect(intradayData.grapthData).toBeDefined() expect(Array.isArray(intradayData.grapthData)).toBe(true) }) test('getEquityStockIndices', async () => { const index = 'NIFTY AUTO' const indexData = await nseIndia.getEquityStockIndices(index) // expect(getDataSchema(indexData,IS_TYPE_STRICT)).toMatchSnapshot(API_RESPONSE_VALIDATION) expect(indexData.metadata.indexName).toBe(index) }) test('Multiple request to getaData', async () => { const limit = 15 const symbols = await nseIndia.getAllStockSymbols() const selectedSymbols = symbols.filter((_symbol, index) => index < limit) const promises = selectedSymbols.map(async (symbol) => { const data = await nseIndia.getEquityDetails(symbol) return { symbol, data } }) const allData = await Promise.all(promises) expect(allData.length).toBe(limit) }) test('Invalid API call', async () => { try { await nseIndia.getDataByEndpoint('/api/invalidapi') } catch (error) { expect((error as Error).message).toBe('Request failed with status code 404') } }) // Test convenience methods for better coverage test('getGlossary', async () => { const glossary = await nseIndia.getGlossary() expect(glossary).toBeDefined() expect(JSON.stringify(glossary).length).toBeGreaterThan(0) }) test('getTradingHolidays', async () => { const holidays = await nseIndia.getTradingHolidays() expect(holidays).toBeDefined() expect(JSON.stringify(holidays).length).toBeGreaterThan(0) }) test('getClearingHolidays', async () => { const holidays = await nseIndia.getClearingHolidays() expect(holidays).toBeDefined() expect(JSON.stringify(holidays).length).toBeGreaterThan(0) }) test('getMarketStatus', async () => { const status = await nseIndia.getMarketStatus() expect(status).toBeDefined() expect(JSON.stringify(status).length).toBeGreaterThan(0) }) test('getMarketTurnover', async () => { const turnover = await nseIndia.getMarketTurnover() expect(turnover).toBeDefined() expect(JSON.stringify(turnover).length).toBeGreaterThan(0) }) test('getAllIndices', async () => { const indices = await nseIndia.getAllIndices() expect(indices).toBeDefined() expect(JSON.stringify(indices).length).toBeGreaterThan(0) }) test('getIndexNames', async () => { const names = await nseIndia.getIndexNames() expect(names).toBeDefined() expect(JSON.stringify(names).length).toBeGreaterThan(0) }) test('getCirculars', async () => { const circulars = await nseIndia.getCirculars() expect(circulars).toBeDefined() expect(JSON.stringify(circulars).length).toBeGreaterThan(0) }) test('getLatestCirculars', async () => { const circulars = await nseIndia.getLatestCirculars() expect(circulars).toBeDefined() expect(JSON.stringify(circulars).length).toBeGreaterThan(0) }) test('getEquityMaster', async () => { const master = await nseIndia.getEquityMaster() expect(master).toBeDefined() expect(JSON.stringify(master).length).toBeGreaterThan(0) }) test('getPreOpenMarketData', async () => { const data = await nseIndia.getPreOpenMarketData() expect(data).toBeDefined() expect(JSON.stringify(data).length).toBeGreaterThan(0) }) test('getMergedDailyReportsCapital', async () => { const reports = await nseIndia.getMergedDailyReportsCapital() expect(reports).toBeDefined() expect(JSON.stringify(reports).length).toBeGreaterThan(0) }) test('getMergedDailyReportsDerivatives', async () => { const reports = await nseIndia.getMergedDailyReportsDerivatives() expect(reports).toBeDefined() expect(JSON.stringify(reports).length).toBeGreaterThan(0) }) test('getMergedDailyReportsDebt', async () => { const reports = await nseIndia.getMergedDailyReportsDebt() expect(reports).toBeDefined() expect(JSON.stringify(reports).length).toBeGreaterThan(0) }) test('getTechnicalIndicators', async () => { const indicators = await nseIndia.getTechnicalIndicators(symbol) // expect(getDataSchema(indicators,IS_TYPE_STRICT)).toMatchSnapshot(API_RESPONSE_VALIDATION) expect(indicators).toBeDefined() expect(indicators).toHaveProperty('sma') expect(indicators).toHaveProperty('ema') expect(indicators).toHaveProperty('rsi') expect(indicators).toHaveProperty('macd') expect(indicators).toHaveProperty('bollingerBands') expect(indicators).toHaveProperty('stochastic') expect(indicators).toHaveProperty('williamsR') expect(indicators).toHaveProperty('atr') expect(indicators).toHaveProperty('adx') expect(indicators).toHaveProperty('obv') expect(indicators).toHaveProperty('cci') expect(indicators).toHaveProperty('mfi') expect(indicators).toHaveProperty('roc') expect(indicators).toHaveProperty('momentum') expect(indicators).toHaveProperty('ad') expect(indicators).toHaveProperty('vwap') // Verify structure of key indicators expect(Array.isArray(indicators.rsi)).toBe(true) expect(indicators.rsi.length).toBeGreaterThan(0) expect(indicators.macd).toHaveProperty('macd') expect(indicators.macd).toHaveProperty('signal') expect(indicators.macd).toHaveProperty('histogram') expect(Array.isArray(indicators.macd.macd)).toBe(true) expect(indicators.bollingerBands).toHaveProperty('upper') expect(indicators.bollingerBands).toHaveProperty('middle') expect(indicators.bollingerBands).toHaveProperty('lower') expect(Array.isArray(indicators.bollingerBands.upper)).toBe(true) }) test('getTechnicalIndicators with custom options', async () => { const indicators = await nseIndia.getTechnicalIndicators(symbol, 100, { smaPeriods: [5, 10, 20], emaPeriods: [5, 10], rsiPeriod: 14, bbPeriod: 20, bbStdDev: 2 }) expect(indicators).toBeDefined() expect(indicators).toHaveProperty('sma') expect(indicators).toHaveProperty('ema') expect(indicators).toHaveProperty('rsi') // Verify custom SMA periods exist expect(indicators.sma).toHaveProperty('sma5') expect(indicators.sma).toHaveProperty('sma10') expect(indicators.sma).toHaveProperty('sma20') // Verify custom EMA periods exist expect(indicators.ema).toHaveProperty('ema5') expect(indicators.ema).toHaveProperty('ema10') }) test('getEquityChartHistoricalData', async () => { // Test charting API with real parameters const chartData = await nseIndia.getEquityChartHistoricalData( 'ONGC', { start: new Date(1775834999 * 1000), end: new Date(1775999513 * 1000) }, '2475', 'Equity', 'I', '5' ) // Verify response structure expect(chartData).toBeDefined() expect(chartData).toHaveProperty('status') expect(chartData).toHaveProperty('data') expect(Array.isArray(chartData.data)).toBe(true) if (chartData.data.length > 0) { // Verify each candle has necessary fields const candle = chartData.data[0] expect(candle).toBeDefined() } }) test('getEquitySymbolInfo', async () => { const info = await nseIndia.getEquitySymbolInfo('ONGC') expect(info).toBeDefined() expect(info).toHaveProperty('symbol') expect(info).toHaveProperty('scripcode') // scripcode is the token required by the chart API — must be a non-empty string expect(typeof info.scripcode).toBe('string') expect(info.scripcode.length).toBeGreaterThan(0) }) test('getEquityChartHistoricalData without token (auto-lookup)', async () => { // Token omitted — the method should call getEquitySymbolInfo internally const chartData = await nseIndia.getEquityChartHistoricalData( 'ONGC', { start: new Date(1775834999 * 1000), end: new Date(1775999513 * 1000) } // no token — should auto-fetch via symbolsDynamic ) expect(chartData).toBeDefined() expect(chartData).toHaveProperty('status') expect(chartData).toHaveProperty('data') expect(Array.isArray(chartData.data)).toBe(true) }) describe('ApiList', () => { Object.entries(ApiList).forEach(entry => { test(`should return content for ${entry[0]}`, async () => { const data = await nseIndia.getDataByEndpoint(entry[1]) // expect(getDataSchema(data,IS_TYPE_STRICT)).toMatchSnapshot(API_RESPONSE_VALIDATION) const contentLength = JSON.stringify(data).length expect(contentLength).not.toBe(0) }) }) }) }) ================================================ FILE: src/index.ts ================================================ import axios from 'axios' import UserAgent from 'user-agents' import { getDateRangeChunks, sleep } from './utils' import { DateRange, IntradayData, EquityDetails, EquityTradeInfo, EquityHistoricalData, SeriesData, IndexDetails, EquityOptionChainData, IndexOptionChainData, CommodityOptionChainData, OptionChainContractInfo, EquityCorporateInfo, Glossary, HolidaysBySegment, MarketStatus, MarketTurnover, AllIndicesData, IndexNamesData, CircularsData, LatestCircularData, EquityMaster, PreOpenMarketData, MergedDailyReportsData, TechnicalIndicators, ChartingSymbolInfo, ChartingOHLCItem, ChartingOHLCResponse, // Nested interfaces EquityInfo, EquityMetadata, EquitySecurityInfo, EquityPriceInfo, EquityPreOpenMarket, EquityHistoricalInfo, EquityOptionChainItem, IndexEquityInfo, IndexRecords, CommodityRecords, Filtered, Holiday, MarketState, MarketCap, IndicativeNifty50, GiftNifty, Datum, PreOpenDetails, OptionsData, OptionsDetails } from './interface' export enum ApiList { GLOSSARY = '/api/cmsContent?url=/glossary', HOLIDAY_TRADING = '/api/holiday-master?type=trading', HOLIDAY_CLEARING = '/api/holiday-master?type=clearing', MARKET_STATUS = '/api/marketStatus', MARKET_TURNOVER = '/api/market-turnover', ALL_INDICES = '/api/allIndices', INDEX_NAMES = '/api/index-names', CIRCULARS = '/api/circulars', LATEST_CIRCULARS = '/api/latest-circular', EQUITY_MASTER = '/api/equity-master', MARKET_DATA_PRE_OPEN = '/api/market-data-pre-open?key=ALL', MERGED_DAILY_REPORTS_CAPITAL = '/api/merged-daily-reports?key=favCapital', MERGED_DAILY_REPORTS_DERIVATIVES = '/api/merged-daily-reports?key=favDerivatives', MERGED_DAILY_REPORTS_DEBT = '/api/merged-daily-reports?key=favDebt' } export class NseIndia { private readonly baseUrl = 'https://www.nseindia.com' private readonly cookieMaxAge = 60 // should be in seconds private readonly baseHeaders = { 'Authority': 'www.nseindia.com', 'Referer': 'https://www.nseindia.com/', 'Accept': '*/*', 'Origin': this.baseUrl, 'Accept-Language': 'en-US,en;q=0.9', 'Accept-Encoding': 'application/json, text/plain, */*', 'Connection': 'keep-alive' } private userAgent = '' private cookies = '' private cookieUsedCount = 0 private cookieExpiry = new Date().getTime() + (this.cookieMaxAge * 1000) private noOfConnections = 0 private readonly chartingBaseUrl = 'https://charting.nseindia.com' private chartingCookies = '' private chartingCookieUsedCount = 0 private chartingCookieExpiry = new Date().getTime() + (this.cookieMaxAge * 1000) private async getNseCookies() { if (this.cookies === '' || this.cookieUsedCount > 10 || this.cookieExpiry <= new Date().getTime()) { this.userAgent = new UserAgent().toString() const response = await axios.get(`${this.baseUrl}/get-quotes/equity?symbol=TCS`, { headers: { ...this.baseHeaders, 'User-Agent': this.userAgent } }) const setCookies: string[] | undefined = response.headers['set-cookie'] const cookies: string[] = [] if (setCookies) { setCookies.forEach((cookie: string) => { const cookieKeyValue = cookie.split(';')[0] cookies.push(cookieKeyValue) }) this.cookies = cookies.join('; ') this.cookieUsedCount = 0 this.cookieExpiry = new Date().getTime() + (this.cookieMaxAge * 1000) } this.cookieUsedCount++ return this.cookies } this.cookieUsedCount++ return this.cookies } /** * Get cookies for charting.nseindia.com domain * Used as fallback when charting API fails with NSE cookies * @returns Charting domain cookies */ private async getChartingCookies() { if ( this.chartingCookies === '' || this.chartingCookieUsedCount > 10 || this.chartingCookieExpiry <= new Date().getTime() ) { const userAgent = new UserAgent().toString() const response = await axios.get(`${this.chartingBaseUrl}/`, { headers: { 'Authority': 'charting.nseindia.com', 'Referer': `${this.chartingBaseUrl}/`, 'Accept': '*/*', 'Accept-Language': 'en-US,en;q=0.9', 'Accept-Encoding': 'application/json, text/plain, */*', 'Connection': 'keep-alive', 'User-Agent': userAgent } }) const setCookies: string[] | undefined = response.headers['set-cookie'] const cookies: string[] = [] if (setCookies) { setCookies.forEach((cookie: string) => { const cookieKeyValue = cookie.split(';')[0] cookies.push(cookieKeyValue) }) this.chartingCookies = cookies.join('; ') this.chartingCookieUsedCount = 0 this.chartingCookieExpiry = new Date().getTime() + (this.cookieMaxAge * 1000) } this.chartingCookieUsedCount++ return this.chartingCookies } this.chartingCookieUsedCount++ return this.chartingCookies } /** * * @param url NSE API's URL or charting API URL * @param domain Domain type: 'nse' for www.nseindia.com, 'charting' for charting.nseindia.com * @returns JSON data from NSE India or charting service */ async getData(url: string, domain: 'nse' | 'charting' = 'nse'): Promise { let retries = 0 let hasError = false let lastError: any = null do { while (this.noOfConnections >= 5) { await sleep(500) } this.noOfConnections++ try { if (domain === 'charting') { // For charting domain: try NSE cookies first, then fallback to charting cookies const chartingHeaders = { 'Authority': 'charting.nseindia.com', 'Referer': `${this.chartingBaseUrl}/`, 'Accept': 'application/json, text/plain, */*', 'Accept-Language': 'en-GB,en;q=0.5', 'Accept-Encoding': 'application/json, text/plain, */*', 'Connection': 'keep-alive' } let cookies = await this.getNseCookies() // Try NSE cookies first (PRIMARY) let response: any try { response = await axios.get(url, { headers: { ...chartingHeaders, 'Cookie': cookies, 'User-Agent': this.userAgent } }) } catch (primaryError) { // NSE cookies failed, try charting cookies (FALLBACK) lastError = primaryError cookies = await this.getChartingCookies() response = await axios.get(url, { headers: { ...chartingHeaders, 'Cookie': cookies, 'User-Agent': this.userAgent } }) } this.noOfConnections-- return response.data } else { // For NSE domain: use standard NSE headers const response = await axios.get(url, { headers: { ...this.baseHeaders, 'Cookie': await this.getNseCookies(), 'User-Agent': this.userAgent } }) this.noOfConnections-- return response.data } } catch (error) { hasError = true lastError = error retries++ this.noOfConnections-- if (retries >= 10) throw error } } while (hasError); } /** * * @param apiEndpoint * @returns */ async getDataByEndpoint(apiEndpoint: string): Promise { return this.getData(`${this.baseUrl}${apiEndpoint}`) } /** * Get historical chart data from charting.nseindia.com * @param symbol Equity symbol with series (e.g., 'ONGC') * @param range Optional date range for chart data query * @param token NSE script code (token) for the symbol. If not provided, it is * automatically fetched via {@link getEquitySymbolInfo}. * @param symbolType Type of symbol (e.g., 'Equity', 'Index') * @param chartType Chart type (e.g., 'I' for intraday, 'D' for daily) * @param timeInterval Time interval in minutes (e.g., '5', '15', '60') * @returns Chart data from charting service */ async getEquityChartHistoricalData( symbol: string, range?: DateRange, token?: string | number, symbolType = 'Equity', chartType = 'I', timeInterval: string | number = '5' ): Promise { const endDate = range?.end ?? new Date() const startDate = range?.start ?? new Date(endDate.getTime() - 24 * 60 * 60 * 1000) const fromDate = Math.floor(startDate.getTime() / 1000) const toDate = Math.floor(endDate.getTime() / 1000) // Auto-fetch token (scripCode) when not supplied by the caller let resolvedToken = token if (!resolvedToken) { const symbolInfo = await this.getEquitySymbolInfo(symbol) resolvedToken = symbolInfo.scripcode } const url = `${this.chartingBaseUrl}/v1/charts/symbolHistoricalData?` + `fromDate=${fromDate}&` + `toDate=${toDate}&` + `symbol=${encodeURIComponent(symbol)}&` + `token=${resolvedToken}&` + `symbolType=${encodeURIComponent(symbolType)}&` + `chartType=${encodeURIComponent(chartType)}&` + `timeInterval=${timeInterval}` return this.getData(url, 'charting') } /** * Look up the NSE script code (token) for an equity symbol using the charting domain. * The `scripCode` in the returned object is the value that must be passed as `token` * to {@link getEquityChartHistoricalData}. * @param symbol Equity symbol with series code (e.g., 'ONGC') OR plain symbol (e.g., 'ONGC') * @param segment Optional market segment filter (default: empty string, returns all segments) * @returns Symbol information including scripCode / token */ async getEquitySymbolInfo( symbol: string, segment = '' ): Promise { const url = `${this.chartingBaseUrl}/v1/exchanges/symbolsDynamic` + `?symbol=${encodeURIComponent(symbol)}&segment=${encodeURIComponent(segment)}` const response = await this.getData(url, 'charting') let symbolList = response if (!Array.isArray(response) && response && typeof response === 'object' && Array.isArray(response.data)) { symbolList = response.data } // The API returns an array; pick the best match: prefer exact symbol match if (!Array.isArray(symbolList) || symbolList.length === 0) { throw new Error(`No symbol info found for: ${symbol}`) } // Try exact match first (symbol === input), fall back to first result const upperSymbol = symbol.toUpperCase() const exact = symbolList.find((s: any) => s.symbol?.toUpperCase() === upperSymbol ) return exact ?? symbolList[0] } /** * * @returns List of NSE equity symbols */ async getAllStockSymbols(): Promise { const { data } = await this.getDataByEndpoint(ApiList.MARKET_DATA_PRE_OPEN) return data.map((obj: { metadata: { symbol: string } }) => obj.metadata.symbol).sort() } /** * * @param symbol * @returns */ getEquityDetails(symbol: string): Promise { return this.getDataByEndpoint(`/api/quote-equity?symbol=${encodeURIComponent(symbol.toUpperCase())}`) } /** * * @param symbol * @returns */ getEquityTradeInfo(symbol: string): Promise { return this.getDataByEndpoint(`/api/quote-equity?symbol=${encodeURIComponent(symbol .toUpperCase())}§ion=trade_info`) } /** * * @param symbol * @returns */ getEquityCorporateInfo(symbol: string): Promise { return this.getDataByEndpoint(`/api/top-corp-info?symbol=${encodeURIComponent(symbol .toUpperCase())}&market=equities`) } /** * * @param symbol * @returns */ async getEquityIntradayData(symbol: string): Promise { const details = await this.getEquityDetails(symbol.toUpperCase()) const identifier = details.info.identifier const url = `/api/NextApi/apiClient/GetQuoteApi?functionName=getSymbolChartData` + `&symbol=${encodeURIComponent(identifier)}&days=1D` return this.getDataByEndpoint(url) } /** * * @param symbol * @param range * @returns */ async getEquityHistoricalData(symbol: string, range?: DateRange): Promise { const data = await this.getEquityDetails(symbol.toUpperCase()) const activeSeries = data.info.activeSeries.length ? data.info.activeSeries[0] : /* istanbul ignore next */ 'EQ' if (!range) { range = { start: new Date(data.metadata.listingDate), end: new Date() } } const dateRanges = getDateRangeChunks(range.start, range.end, 66) const promises = dateRanges.map(async (dateRange) => { const url = `/api/NextApi/apiClient/GetQuoteApi?functionName=getHistoricalTradeData` + `&symbol=${encodeURIComponent(symbol.toUpperCase())}` + `&series=${encodeURIComponent(activeSeries)}` + `&fromDate=${dateRange.start}&toDate=${dateRange.end}` const response = await this.getDataByEndpoint(url) // New API returns a direct array, wrap it in EquityHistoricalData structure for backward compatibility /* istanbul ignore next */ return { data: Array.isArray(response) ? response : [], meta: { series: [activeSeries], fromDate: dateRange.start, toDate: dateRange.end, symbols: [symbol.toUpperCase()] } } }) return Promise.all(promises) } /** * * @param symbol * @returns */ async getEquitySeries(symbol: string): Promise { const response = await this.getDataByEndpoint( `/api/NextApi/apiClient/GetQuoteApi?functionName=histTradeDataSeries` + `&symbol=${encodeURIComponent(symbol.toUpperCase())}` ) // New API returns a direct array, wrap it in SeriesData structure for backward compatibility /* istanbul ignore next */ return { data: Array.isArray(response) ? response : [] } } /** * * @param index * @returns */ getEquityStockIndices(index: string): Promise { return this.getDataByEndpoint(`/api/equity-stockIndices?index=${encodeURIComponent(index.toUpperCase())}`) } /** * * @param index * @returns */ async getIndexIntradayData(index: string): Promise { const response = await this.getDataByEndpoint( `/api/NextApi/apiClient?functionName=getGraphChart` + `&type=${encodeURIComponent(index.toUpperCase())}&flag=1D` ) // The API response is wrapped in a 'data' object /* istanbul ignore next */ return response.data || response } /** * Get option chain contract information (expiry dates and strike prices) for an index * * @param indexSymbol * @returns */ getIndexOptionChainContractInfo(indexSymbol: string): Promise { return this.getDataByEndpoint( `/api/option-chain-contract-info?symbol=${encodeURIComponent(indexSymbol.toUpperCase())}` ) as Promise } /** * * @param indexSymbol * @param expiry Optional expiry date in DD-MMM-YYYY format (e.g., "23-Dec-2025"). * If not provided, will fetch nearest upcoming expiry * @returns */ async getIndexOptionChain(indexSymbol: string, expiry?: string): Promise { // If expiry not provided, fetch the nearest upcoming expiry date from the API if (!expiry) { /* istanbul ignore next */ const contractInfo = await this.getIndexOptionChainContractInfo(indexSymbol) /* istanbul ignore next */ if (contractInfo && contractInfo.expiryDates && Array.isArray(contractInfo.expiryDates)) { /* istanbul ignore next */ const today = new Date() /* istanbul ignore next */ today.setHours(0, 0, 0, 0) // Reset time to start of day for comparison // Find the nearest upcoming expiry date /* istanbul ignore next */ let nearestExpiry: string | null = null /* istanbul ignore next */ let nearestDate: Date | null = null /* istanbul ignore next */ for (const expiryDateStr of contractInfo.expiryDates) { // Parse date in DD-MMM-YYYY format /* istanbul ignore next */ const dateParts = expiryDateStr.split('-') /* istanbul ignore next */ if (dateParts.length === 3) { /* istanbul ignore next */ const day = parseInt(dateParts[0], 10) /* istanbul ignore next */ const monthNames = [ 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec' ] /* istanbul ignore next */ const month = monthNames.indexOf(dateParts[1]) /* istanbul ignore next */ const year = parseInt(dateParts[2], 10) /* istanbul ignore next */ if (month !== -1) { /* istanbul ignore next */ const expiryDate = new Date(year, month, day) /* istanbul ignore next */ expiryDate.setHours(0, 0, 0, 0) // Check if this expiry is in the future or today /* istanbul ignore next */ if (expiryDate >= today) { /* istanbul ignore next */ if (!nearestDate || expiryDate < nearestDate) { /* istanbul ignore next */ nearestDate = expiryDate /* istanbul ignore next */ nearestExpiry = expiryDateStr } } } } } /* istanbul ignore next */ if (nearestExpiry) { /* istanbul ignore next */ expiry = nearestExpiry } else { // Fallback: use the last expiry date if no upcoming date found /* istanbul ignore next */ expiry = contractInfo.expiryDates[contractInfo.expiryDates.length - 1] } } else { // Fallback: use current date if API fails /* istanbul ignore next */ const today = new Date() /* istanbul ignore next */ const day = today.getDate().toString().padStart(2, '0') /* istanbul ignore next */ const months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'] /* istanbul ignore next */ const month = months[today.getMonth()] /* istanbul ignore next */ const year = today.getFullYear() /* istanbul ignore next */ expiry = `${day}-${month}-${year}` } } // Ensure expiry is defined (should always be set by this point) /* istanbul ignore next */ if (!expiry) { /* istanbul ignore next */ throw new Error('Failed to determine expiry date') } return this.getDataByEndpoint( `/api/option-chain-v3?type=Indices` + `&symbol=${encodeURIComponent(indexSymbol.toUpperCase())}` + `&expiry=${encodeURIComponent(expiry)}` ) } /** * * @param symbol * @returns */ getEquityOptionChain(symbol: string): Promise { return this.getDataByEndpoint( `/api/NextApi/apiClient/GetQuoteApi?functionName=getSymbolDerivativesData` + `&symbol=${encodeURIComponent(symbol.toUpperCase())}` ) } /** * * @param symbol * @returns */ getCommodityOptionChain(symbol: string): Promise { return this.getDataByEndpoint(`/api/option-chain-com?symbol=${encodeURIComponent(symbol .toUpperCase())}`) } /** * Get NSE glossary content * @returns Glossary content */ getGlossary(): Promise { return this.getDataByEndpoint(ApiList.GLOSSARY) } /** * Get trading holidays * @returns List of trading holidays */ getTradingHolidays(): Promise { return this.getDataByEndpoint(ApiList.HOLIDAY_TRADING) } /** * Get clearing holidays * @returns List of clearing holidays */ getClearingHolidays(): Promise { return this.getDataByEndpoint(ApiList.HOLIDAY_CLEARING) } /** * Get market status * @returns Current market status */ getMarketStatus(): Promise { return this.getDataByEndpoint(ApiList.MARKET_STATUS) } /** * Get market turnover * @returns Market turnover data */ getMarketTurnover(): Promise { return this.getDataByEndpoint(ApiList.MARKET_TURNOVER) } /** * Get all indices * @returns List of all indices */ getAllIndices(): Promise { return this.getDataByEndpoint(ApiList.ALL_INDICES) } /** * Get index names * @returns List of index names */ getIndexNames(): Promise { return this.getDataByEndpoint(ApiList.INDEX_NAMES) } /** * Get circulars * @returns List of circulars */ getCirculars(): Promise { return this.getDataByEndpoint(ApiList.CIRCULARS) } /** * Get latest circulars * @returns List of latest circulars */ getLatestCirculars(): Promise { return this.getDataByEndpoint(ApiList.LATEST_CIRCULARS) } /** * Get equity master * @returns Equity master data with categorized indices */ getEquityMaster(): Promise { return this.getDataByEndpoint(ApiList.EQUITY_MASTER) } /** * Get pre-open market data * @returns Pre-open market data */ getPreOpenMarketData(): Promise { return this.getDataByEndpoint(ApiList.MARKET_DATA_PRE_OPEN) } /** * Get merged daily reports for capital market * @returns Daily reports for capital market */ getMergedDailyReportsCapital(): Promise { return this.getDataByEndpoint(ApiList.MERGED_DAILY_REPORTS_CAPITAL) } /** * Get merged daily reports for derivatives * @returns Daily reports for derivatives */ getMergedDailyReportsDerivatives(): Promise { return this.getDataByEndpoint(ApiList.MERGED_DAILY_REPORTS_DERIVATIVES) } /** * Get merged daily reports for debt market * @returns Daily reports for debt market */ getMergedDailyReportsDebt(): Promise { return this.getDataByEndpoint(ApiList.MERGED_DAILY_REPORTS_DEBT) } /** * Get technical indicators for a specific equity symbol * @param symbol - The equity symbol (e.g., 'RELIANCE', 'TCS') * @param period - Number of days for historical data (default: 200) * @param options - Optional configuration for indicators * @returns Promise */ async getTechnicalIndicators( symbol: string, period = 200, options: { smaPeriods?: number[] // Array of periods for SMA (e.g., [5, 10, 20, 50]) emaPeriods?: number[] // Array of periods for EMA (e.g., [5, 10, 20, 50]) rsiPeriod?: number macdFast?: number macdSlow?: number macdSignal?: number bbPeriod?: number bbStdDev?: number stochK?: number stochD?: number williamsRPeriod?: number atrPeriod?: number adxPeriod?: number cciPeriod?: number mfiPeriod?: number rocPeriod?: number momentumPeriod?: number } = {} ): Promise { const { getTechnicalIndicators } = await import('./helpers') return getTechnicalIndicators(symbol, period, options) } } // Export all interfaces for TypeDoc documentation export type { DateRange, IntradayData, EquityDetails, EquityTradeInfo, EquityHistoricalData, SeriesData, IndexDetails, EquityOptionChainData, IndexOptionChainData, CommodityOptionChainData, OptionChainContractInfo, EquityCorporateInfo, Glossary, HolidaysBySegment, MarketStatus, MarketTurnover, AllIndicesData, IndexNamesData, CircularsData, LatestCircularData, EquityMaster, PreOpenMarketData, MergedDailyReportsData, TechnicalIndicators, ChartingSymbolInfo, ChartingOHLCItem, ChartingOHLCResponse, // Nested interfaces EquityInfo, EquityMetadata, EquitySecurityInfo, EquityPriceInfo, EquityPreOpenMarket, EquityHistoricalInfo, EquityOptionChainItem, IndexEquityInfo, IndexRecords, CommodityRecords, Filtered, Holiday, MarketState, MarketCap, IndicativeNifty50, GiftNifty, Datum, PreOpenDetails, OptionsData, OptionsDetails } ================================================ FILE: src/inputs.graphql ================================================ input StringArrayFilter { startsWith: String regex: String in: [String] nin: [String] eq: String, neq: String offset: Int limit: Int } input ObjectFilter { regex: String } ================================================ FILE: src/interface.ts ================================================ /** * Intraday data for equity or index */ export interface IntradayData { identifier: string name: string // Array of [timestamp, price, status] where status is "PO" (pre-open) or "NM" (normal market) grapthData: [number, number, string][] closePrice: number } /** * Symbol information returned by the charting.nseindia.com symbolsDynamic API. * The `scripCode` field is what the historical chart API refers to as `token`. */ export interface ChartingSymbolInfo { symbol: string scripcode: string // This is the "token" required by the historical chart API companyName: string isin: string segment: string series: string status: string } /** * Individual candle data point from charting API */ export interface ChartingOHLCItem { volume: number high: number low: number time: number // Unix timestamp in milliseconds close: number open: number } /** * Response structure for historical chart OHLC data */ export interface ChartingOHLCResponse { status: boolean data: ChartingOHLCItem[] } /** * Date range for historical data queries */ export interface DateRange { start: Date end: Date } /** * Equity information including company details and security metadata */ export interface EquityInfo { symbol: string companyName: string industry: string activeSeries: string[] debtSeries: string[] tempSuspendedSeries: string[] isFNOSec: boolean isCASec: boolean isSLBSec: boolean isDebtSec: boolean isSuspended: boolean isETFSec: boolean isDelisted: boolean isin: string slb_isin: string listingDate: string isMunicipalBond: boolean isHybridSymbol: boolean segment: string isTop10: boolean identifier: string } /** * Option chain contract information with expiry dates and strike prices */ export interface OptionChainContractInfo { expiryDates: string[] strikePrice: string[] } /** * Equity option chain data structure */ export interface EquityOptionChainData { data: EquityOptionChainItem[]; timestamp: string; } /** * Index option chain data structure */ export interface IndexOptionChainData { records: IndexRecords | null; filtered: Filtered | null; } /** * Commodity option chain data structure */ export interface CommodityOptionChainData { records: CommodityRecords | null; filtered: Filtered | null; } // Base Records interface export interface Records { expiryDates: string[]; data: Datum[]; timestamp: string; underlyingValue: number; } /** * Index option chain records with string strike prices */ export interface IndexRecords extends Records { strikePrices: string[]; // API returns strings (e.g., "9000", "10000") } /** * Commodity option chain records with numeric strike prices */ export interface CommodityRecords extends Records { strikePrices: number[]; // API returns numbers } /** * Filtered option chain data with call and put options */ export interface Filtered { data: Datum[]; CE: OptionsData; PE: OptionsData; } /** * Options data with total open interest and volume */ export interface OptionsData { totOI: number; totVol: number; } /** * Individual equity option chain item with strike price and option details */ export interface EquityOptionChainItem { identifier: string; instrumentType: string; underlying: string; expiryDate: string; optionType: string; strikePrice: string; openPrice: number; highPrice: number; lowPrice: number; closePrice: number; prevClose: number; lastPrice: number; change: number; totalTradedVolume: number; totalTurnover: number; openInterest: number; changeinOpenInterest: number; pchangeinOpenInterest: number; underlyingValue: number; volumeFreezeQuantity: number; ticksize: number; pchange: number; } /** * Option chain datum with strike price and option details */ export interface Datum { strikePrice: number; expiryDates: string; // For index options, this is a string (e.g., "30-Dec-2025") expiryDate?: string; // Alternative field name PE?: OptionsDetails; CE?: OptionsDetails; } /** * Detailed options information including open interest, volume, and pricing */ export interface OptionsDetails { strikePrice: number; expiryDate: string | null; underlying: Underlying | string | null; identifier: string | null; openInterest: number; changeinOpenInterest: number; pchangeinOpenInterest: number; totalTradedVolume: number; impliedVolatility: number; lastPrice: number; change: number; pChange?: number; pchange?: number; // Some APIs use 'pchange' instead of 'pChange' totalBuyQuantity: number; totalSellQuantity: number; bidQty?: number; bidprice?: number; askQty?: number; askPrice?: number; buyPrice1?: number; // Index options use buyPrice1/sellPrice1 buyQuantity1?: number; sellPrice1?: number; sellQuantity1?: number; underlyingValue: number; optionType: string | null; } export enum Underlying { Nifty = "NIFTY", Gold = "GOLD" } /** * Equity metadata including series, ISIN, status, and listing information */ export interface EquityMetadata { series: string symbol: string isin: string status: string listingDate: string industry: string lastUpdateTime: string pdSectorPe: number pdSymbolPe: number pdSectorInd: string pdSectorIndAll: string[] } /** * Equity security information including trading status and surveillance details */ export interface EquitySecurityInfo { boardStatus: string tradingStatus: string tradingSegment: string sessionNo: string slb: string classOfShare: string derivatives: string surveillance: { surv: string | null desc: string | null } faceValue: number issuedSize: number } /** * Equity price information including current price, change, and trading bands */ export interface EquityPriceInfo { lastPrice: number change: number pChange: number previousClose: number open: number close: number vwap: number stockIndClosePrice: number lowerCP: string upperCP: string pPriceBand: string basePrice: number intraDayHighLow: { min: number max: number value: number } weekHighLow: { min: number minDate: string max: number maxDate: string value: number } iNavValue: number | null checkINAV: boolean tickSize: number ieq: string } /** * Pre-open market details for individual price levels */ export interface PreOpenDetails { price: number buyQty: number sellQty: number iep?: boolean } /** * Pre-open market data for equity including indicative equilibrium price */ export interface EquityPreOpenMarket { preopen: PreOpenDetails[] ato: { buy: number sell: number } IEP: number totalTradedVolume: number finalPrice: number finalQuantity: number lastUpdateTime: string totalBuyQuantity: number totalSellQuantity: number atoBuyQty: number atoSellQty: number } /** * Detailed equity information including price, metadata, and market data */ export interface EquityDetails { info: EquityInfo metadata: EquityMetadata securityInfo: EquitySecurityInfo sddDetails: { SDDAuditor: string SDDStatus: string } currentMarketType: string priceInfo: EquityPriceInfo industryInfo: { macro: string sector: string industry: string basicIndustry: string } preOpenMarket: EquityPreOpenMarket } /** * Equity trade information including order book and trade statistics */ export interface EquityTradeInfo { noBlockDeals: boolean bulkBlockDeals: { name: string }[] marketDeptOrderBook: { totalBuyQuantity: number totalSellQuantity: number open: number bid: { price: number quantity: number }[] ask: { price: number quantity: number }[] tradeInfo: { totalTradedVolume: number totalTradedValue: number totalMarketCap: number ffmc: number impactCost: number cmDailyVolatility: string cmAnnualVolatility: string marketLot: string activeSeries: string } valueAtRisk: { securityVar: number indexVar: number varMargin: number extremeLossMargin: number adhocMargin: number applicableMargin: number } } securityWiseDP: { quantityTraded: number deliveryQuantity: number deliveryToTradedQuantity: number seriesRemarks: string | null secWiseDelPosDate: string } } export interface DirectoryDetails { webAddress: string smName: string symbol: string office: string address: string city: string pincode: string telephone: string fax: string email: string } /** * Corporate information including announcements, actions, and financial results */ export interface EquityCorporateInfo { "latest_announcements": { "data": { "symbol": string "broadcastdate": string "subject": string }[] }, "corporate_actions": { "data": { "symbol": string "exdate": string "purpose": string }[] }, "shareholdings_patterns": { "data": { [date: string]: Array<{ [key: string]: string }> } }, "financial_results": { "data": { "from_date": string | null "to_date": string "expenditure": string | null "income": string "audited": string "cumulative": string | null "consolidated": string "reDilEPS": string "reProLossBefTax": string "proLossAftTax": string "re_broadcast_timestamp": string "xbrl_attachment": string "na_attachment": string | null }[] }, "borad_meeting": { "data": { "symbol": string "purpose": string "meetingdate": string }[] } } /** * Historical equity price and volume information for a single day */ export interface EquityHistoricalInfo { chSymbol: string chSeries: string chPreviousClsPrice: number chOpeningPrice: number chTradeHighPrice: number chTradeLowPrice: number chLastTradedPrice: number chClosingPrice: number vwap: number chTotTradedQty: number chTotTradedVal: number chTotalTrades: number ch52WeekHighPrice: number ch52WeekLowPrice: number mtimestamp: string } /** * Historical equity data with price and volume information */ export interface EquityHistoricalData { data: EquityHistoricalInfo[] meta: { series: string[] fromDate: string toDate: string symbols: string[] } } /** * Series data for equity symbols */ export interface SeriesData { data: string[] } // Note: The API actually returns a direct array, but we wrap it for consistency // The actual response type is: string[] /** * Index constituent equity information */ export interface IndexEquityInfo { priority: number symbol: string identifier: string series: string open: number dayHigh: number dayLow: number lastPrice: number previousClose: number change: number pChange: number totalTradedVolume: number stockIndClosePrice: number totalTradedValue: number lastUpdateTime: string yearHigh: number ffmc: number yearLow: number nearWKH: number nearWKL: number perChange365d: number perChange30d: number date365dAgo: string date30dAgo: string chartTodayPath: string chart30dPath: string chart365dPath: string meta?: EquityInfo } /** * Detailed index information including constituent stocks and metadata */ export interface IndexDetails { name: string, advance: { declines: string, advances: string, unchanged: string }, timestamp: string, data: IndexEquityInfo[], metadata: { indexName: string, open: number high: number low: number previousClose: number last: number percChange: number change: number timeVal: string, yearHigh: number yearLow: number indicativeClose: number perChange365d: number perChange30d: number date365dAgo: string date30dAgo: string chartTodayPath: string chart30dPath: string chart365dPath: string totalTradedVolume: number totalTradedValue: number ffmc_sum: number }, marketStatus: { market: string, marketStatus: string, tradeDate: string, index: string, last: number variation: number percentChange: number marketStatusMessage: string }, date30dAgo: string, date365dAgo: string } // New interfaces for additional APIs export interface GlossaryData { data: { content: string title: string url: string } } export interface HolidayData { data: { date: string description: string trading: boolean clearing: boolean }[] } /** * Market status data */ export interface MarketStatusData { marketState: string marketStatus: string tradeDate: string index: string last: number variation: number percentChange: number marketStatusMessage: string } /** * Market turnover data */ export interface MarketTurnoverData { data: { date: string totalTradedValue: number totalTradedVolume: number totalTrades: number }[] } /** * All indices data */ export interface AllIndicesData { data: { indexName: string open: number high: number low: number previousClose: number last: number percChange: number change: number timeVal: string yearHigh: number yearLow: number totalTradedVolume: number totalTradedValue: number ffmc_sum: number }[] } /** * Index names data organized by category */ export interface IndexNamesData { stn: string[][]; nts: string[][]; } /** * Circulars data from NSE */ export interface CircularsData { data: { fileDept: string; circNumber: string; fileExt: string; sub: string; cirDate: string; cirDisplayDate: string; circFilename: string; circFilelink: string; circCompany: string; circDisplayNo: string; }[]; fromDate: string; toDate: string; } /** * Latest circular data from NSE */ export interface LatestCircularData { data: { fileDept: string; circNumber: string; fileExt: string; sub: string; cirDate: string; cirDisplayDate: string; circFilename: string; circFilelink: string; circCompany: string; circDisplayNo: string; }[]; } /** * Equity master data */ export interface EquityMasterData { data: { symbol: string series: string isin: string status: string listingDate: string industry: string lastUpdateTime: string }[] } export interface MarketDataPreOpenData { data: { metadata: { symbol: string series: string isin: string status: string listingDate: string industry: string lastUpdateTime: string } priceInfo: { lastPrice: number change: number pChange: number previousClose: number open: number close: number vwap: number lowerCP: string upperCP: string pPriceBand: string basePrice: number } preOpenMarket: { preopen: PreOpenDetails[] ato: { buy: number sell: number } IEP: number totalTradedVolume: number finalPrice: number finalQuantity: number lastUpdateTime: string totalBuyQuantity: number totalSellQuantity: number atoBuyQty: number atoSellQty: number } }[] } /** * Merged daily reports data */ export interface MergedDailyReportsData { name: string; type: string; category: string; section: string; link: string; } /** * NSE glossary content */ export interface Glossary { content: { title?: string; body?: string; field_glossary_items?: any; field_labels?: any; field_reference?: any; field_unique_url?: string; [key: string]: any; // Glossary content can have various structures }; id: string; type: string; changed?: string; } /** * Trading holiday information */ export interface Holiday { tradingDate: string; weekDay: string; description: string; morning_session: string; evening_session: string; Sr_no: number; } /** * Trading and clearing holidays organized by segment */ export interface HolidaysBySegment { [segment: string]: Holiday[]; } /** * Market state information including status and trading details */ export interface MarketState { market: string; marketStatus: string; tradeDate: string; index: string; last: number | string; variation: number | string; percentChange: number | string; marketStatusMessage: string; expiryDate?: string; underlying?: string; updated_time?: string; tradeDateFormatted?: string; slickclass?: string; } /** * Market capitalization information */ export interface MarketCap { timeStamp: string; marketCapinTRDollars: number; marketCapinLACCRRupees: number; marketCapinCRRupees: number; marketCapinCRRupeesFormatted: string; marketCapinLACCRRupeesFormatted: string; underlying: string; } /** * Indicative Nifty 50 index information */ export interface IndicativeNifty50 { dateTime: string; indicativeTime: string | null; indexName: string; indexLast: number | null; indexPercChange: number | null; indexTimeVal: string | null; closingValue: number; finalClosingValue: number; change: number; perChange: number; status: string; } /** * Gift Nifty (formerly SGX Nifty) futures data */ export interface GiftNifty { INSTRUMENTTYPE: string; SYMBOL: string; EXPIRYDATE: string; OPTIONTYPE: string; STRIKEPRICE: string; LASTPRICE: number; DAYCHANGE: string; PERCHANGE: string; CONTRACTSTRADED: number; TIMESTMP: string; id: string; } /** * Market status information */ export interface MarketStatus { marketState: MarketState[]; marketcap: MarketCap; indicativenifty50?: IndicativeNifty50; giftnifty: GiftNifty; } /** * Market turnover information */ export interface MarketTurnover { totalTradedValue: number totalTradedVolume: number totalTrades: number lastUpdateTime: string } export interface IndexName { indexSymbol: string indexName: string } export interface Circular { subject: string description: string date: string attachment: string } export interface IndexCategories { [category: string]: string[]; } /** * Equity master data organized by category */ export interface EquityMaster { [categoryName: string]: string[]; } /** * Pre-open market data */ export interface PreOpenMarketData { data: Array<{ metadata: { symbol: string; companyName: string; industry: string; isinCode: string; series?: string; status?: string; listingDate?: string; lastUpdateTime?: string; }; detail?: any; priceInfo?: { lastPrice: number; change: number; pChange: number; open: number; high: number; low: number; close: number; prevClose: number; totalTradedVolume: number; totalTradedValue: number; }; }>; timestamp: string; advances: number; declines: number; unchanged: number; totalTradedValue: number; totalmarketcap: number; totalTradedVolume: number; } export interface DailyReport { symbol: string series: string openPrice: number highPrice: number lowPrice: number closePrice: number lastTradedPrice: number totalTradedQuantity: number totalTradedValue: number prevClosePrice: number change: number pChange: number totalTrades: number isin: string tradingDate: string } /** * Technical indicators including SMA, EMA, RSI, MACD, Bollinger Bands, etc. */ export interface TechnicalIndicators { sma: { [key: string]: number[] } // Dynamic SMA indicators (e.g., sma5, sma10, sma20) ema: { [key: string]: number[] } // Dynamic EMA indicators (e.g., ema5, ema10, ema20) rsi: number[] // Relative Strength Index macd: { macd: number[] signal: number[] histogram: number[] } bollingerBands: { upper: number[] middle: number[] lower: number[] } stochastic: { k: number[] d: number[] } williamsR: number[] // Williams %R atr: number[] // Average True Range adx: number[] // Average Directional Index obv: number[] // On-Balance Volume cci: number[] // Commodity Channel Index mfi: number[] // Money Flow Index roc: number[] // Rate of Change momentum: number[] // Momentum ad: number[] // Accumulation/Distribution vwap: number[] // Volume Weighted Average Price } ================================================ FILE: src/mcp/client/mcp-client.ts ================================================ import OpenAI from 'openai' import { NseIndia } from '../../index.js' import { mcpTools, handleMCPToolCall } from '../mcp-tools.js' import { MemoryManager, ConversationMessage, MemoryConfig } from '../memory-manager.js' export interface MCPClientRequest { query: string sessionId?: string userId?: string model?: string temperature?: number max_tokens?: number includeContext?: boolean updatePreferences?: boolean useMemory?: boolean maxIterations?: number enableDebugLogging?: boolean } export interface MCPClientResponse { response: string tools_used: string[] data_sources: string[] timestamp: string sessionId?: string context_used?: boolean user_preferences_updated?: boolean conversation_length?: number context_summarized?: boolean context_summary?: any token_count?: any iterations_used?: number iteration_details?: { iteration: number tools_called: string[] purpose: string tool_parameters?: { tool_name: string parameters: any }[] }[] } export interface MCPClientConfig { memoryConfig?: Partial openaiApiKey?: string enableMemory?: boolean enableContextSummarization?: boolean enableDebugLogging?: boolean } /** * Unified MCP Client with OpenAI Function Calling, Memory, and Context Summarization * * This is the single, unified MCP client that combines all features: * - OpenAI function calling for natural language queries * - Memory management for context awareness * - Context summarization for handling long conversations * - Session management for multi-user support */ export class MCPClient { private nseClient: NseIndia private openai: OpenAI private availableTools: any[] private memoryManager?: MemoryManager private config: MCPClientConfig private currentQuery?: string // Track current query for smarter iteration decisions private allToolsUsed: string[] = [] // Track all tools used across iterations constructor(config: MCPClientConfig = {}) { this.config = { enableMemory: true, enableContextSummarization: true, enableDebugLogging: false, ...config } // Initialize NSE India client this.nseClient = new NseIndia() // Initialize OpenAI client this.openai = new OpenAI({ apiKey: config.openaiApiKey || process.env.OPENAI_API_KEY, }) // Initialize available tools this.availableTools = mcpTools // Initialize memory manager if enabled if (this.config.enableMemory) { this.memoryManager = new MemoryManager(config.memoryConfig) } } /** * Debug logging method */ private debugLog(message: string, data?: any): void { if (this.config.enableDebugLogging) { // eslint-disable-next-line no-console console.log(`[MCP DEBUG] ${message}`) if (data) { // eslint-disable-next-line no-console console.log(`[MCP DEBUG] Data:`, JSON.stringify(data, null, 2)) } } } /** * Enable or disable debug logging on this client instance */ setDebugLogging(enabled: boolean): void { this.config.enableDebugLogging = enabled } /** * Get current debug logging status */ isDebugLoggingEnabled(): boolean { return this.config.enableDebugLogging === true } /** * Convert MCP tools to OpenAI function format */ private convertToolsToOpenAIFunctions(): OpenAI.Chat.Completions.ChatCompletionCreateParams.Function[] { return this.availableTools.map(tool => ({ name: tool.name, description: tool.description, parameters: tool.inputSchema })) } /** * Extract stock symbols from query for context tracking */ private extractStockSymbols(query: string): string[] { const symbolRegex = /\b[A-Z]{2,10}\b/g const matches = query.match(symbolRegex) || [] const commonWords = ['THE', 'AND', 'OR', 'FOR', 'WITH', 'FROM', 'TO', 'IN', 'ON', 'AT', 'BY'] return matches.filter(symbol => !commonWords.includes(symbol)) } /** * Get base system prompt without context */ private getBaseSystemPrompt(): string { return 'You are a helpful assistant that provides information about Indian stock market data from NSE India. ' + 'You have access to various tools to fetch real-time market data, stock information, ' + 'historical data, and more. ' + 'When a user asks a question, use the appropriate tools to gather the necessary data ' + 'and provide a comprehensive answer. ' + 'Always format your responses in a clear, professional manner with proper markdown ' + 'formatting when appropriate.' } /** * Process a natural language query with multi-iteration support (default: 5 iterations) */ async processQuery(request: MCPClientRequest): Promise { const { query, sessionId, userId, model = 'gpt-4o-mini', temperature = 0.7, max_tokens = 2000, includeContext = true, updatePreferences = true, useMemory = true, maxIterations = 5 } = request try { // Initialize query tracking for smart iteration decisions this.currentQuery = query this.allToolsUsed = [] // Determine if we should use memory features const shouldUseMemory = !!(useMemory && this.config.enableMemory && this.memoryManager && sessionId) let session: any = null let conversationContext: any = { messages: [], wasSummarized: false, tokenCount: { totalTokens: 0 } } // Initialize session and memory if enabled if (shouldUseMemory) { session = this.memoryManager!.getOrCreateSession(sessionId!, userId) // Add user message to conversation history const userMessage: ConversationMessage = { role: 'user', content: query, timestamp: new Date().toISOString() } this.memoryManager!.addMessage(sessionId!, userMessage) // Extract stock symbols for context tracking const stockSymbols = this.extractStockSymbols(query) stockSymbols.forEach(symbol => { this.memoryManager!.updateStockAccess(sessionId!, symbol) }) // Get conversation history with context summarization if (includeContext) { conversationContext = await this.memoryManager!.getConversationContext(sessionId!) } } // Get system prompt (contextual if memory is enabled) const systemPrompt = shouldUseMemory && includeContext ? this.memoryManager!.getContextualSystemPrompt(sessionId!) : this.getBaseSystemPrompt() // Initialize iteration tracking let currentIteration = 0 const uniqueToolsUsed = new Set() // Use Set for true uniqueness const iterationDetails: { iteration: number; tools_called: string[]; purpose: string; tool_parameters?: { tool_name: string; parameters: any; }[] }[] = [] // Build initial messages array const allMessages: OpenAI.Chat.Completions.ChatCompletionMessageParam[] = [ { role: 'system', content: systemPrompt } ] // Add conversation history if memory is enabled if (shouldUseMemory && includeContext) { conversationContext.messages.forEach((msg: ConversationMessage) => { if (msg.role === 'assistant' && msg.content) { allMessages.push({ role: 'assistant', content: msg.content }) } else if (msg.role === 'user' && msg.content !== query) { allMessages.push({ role: 'user', content: msg.content }) } else if (msg.role === 'system' && msg.content) { allMessages.push({ role: 'system', content: msg.content }) } }) } // Add current user query allMessages.push({ role: 'user', content: query }) // Convert MCP tools to OpenAI functions const functions = this.convertToolsToOpenAIFunctions() // Main iteration loop while (currentIteration < maxIterations) { currentIteration++ this.debugLog(`Iteration ${currentIteration}/${maxIterations}`) this.debugLog('Sending messages to OpenAI:', allMessages) const response = await this.openai.chat.completions.create({ model, messages: allMessages, tools: functions.map(fn => ({ type: 'function', function: fn })), tool_choice: 'auto', temperature, max_tokens }) this.debugLog('OpenAI Response:', { model: response.model, usage: response.usage, message: response.choices[0]?.message }) const message = response.choices[0]?.message if (!message) { throw new Error(`No response from OpenAI in iteration ${currentIteration}`) } // Add assistant message to conversation allMessages.push({ role: 'assistant', content: message.content, tool_calls: message.tool_calls }) // Check if tools were called if (message.tool_calls && message.tool_calls.length > 0) { const iterationTools = message.tool_calls.map(tc => tc.function.name) this.debugLog( `Iteration ${currentIteration}: Calling ${iterationTools.length} tools: ${iterationTools.join(', ')}` ) // Log tool parameters for debugging message.tool_calls.forEach((toolCall, index) => { this.debugLog(`Tool ${index + 1}: ${toolCall.function.name}`) try { const params = JSON.parse(toolCall.function.arguments) this.debugLog(`Parameters:`, params) } catch (e) { this.debugLog(`Invalid JSON parameters: ${toolCall.function.arguments}`) } }) // Execute all function calls in parallel const functionCallPromises = message.tool_calls.map(async (toolCall) => { this.debugLog(`Executing tool: ${toolCall.function.name}`) const functionResult = await this.executeFunctionCall(toolCall) this.debugLog(`Tool ${toolCall.function.name} result:`, functionResult) return { toolCall, result: functionResult } }) const functionCallResults = await Promise.all(functionCallPromises) this.debugLog(`Completed ${functionCallResults.length} tool executions`) // Add unique tools to Set (automatically handles duplicates) iterationTools.forEach(tool => { uniqueToolsUsed.add(tool) }) // Track all tools (including duplicates) for internal logic this.allToolsUsed.push(...iterationTools) // Capture tool parameters for iteration details const toolParameters = message.tool_calls.map(toolCall => ({ tool_name: toolCall.function.name, parameters: (() => { try { return JSON.parse(toolCall.function.arguments) } catch (e) { return { raw_arguments: toolCall.function.arguments, parse_error: e instanceof Error ? e.message : String(e) } } })() })) // Add iteration details iterationDetails.push({ iteration: currentIteration, tools_called: iterationTools, purpose: this.inferIterationPurpose(iterationTools, currentIteration), tool_parameters: toolParameters }) // Add tool results to conversation functionCallResults.forEach(({ toolCall, result }) => { allMessages.push({ role: 'tool', tool_call_id: toolCall.id, content: JSON.stringify(result) }) }) // Check if we should continue iterating if (this.shouldContinueIterating(message, currentIteration, maxIterations)) { // Add instruction for next iteration with specific guidance let nextInstruction = `You now have additional data from iteration ${currentIteration}. ` // Provide specific guidance based on the original query and current context if (query.toLowerCase().includes('technical indicators') && !this.allToolsUsed.includes('get_equity_technical_indicators')) { nextInstruction += `IMPORTANT: The user specifically asked about technical indicators ` + `for investment decisions. You MUST call get_equity_technical_indicators for several ` + `promising stocks from the data you received. Do not provide investment recommendations ` + `without actual technical analysis data.` } else if (query.toLowerCase().includes('invest') && currentIteration <= 2) { nextInstruction += `The user is asking for investment recommendations. You need to ` + `analyze the data more deeply by calling get_equity_technical_indicators or ` + `get_equity_details for specific stocks to make informed recommendations.` } else if (query.toLowerCase().includes('nifty') && query.toLowerCase().includes('invest')) { nextInstruction += `You have NIFTY stock data. Now you need to select promising ` + `stocks and get their technical indicators by calling get_equity_technical_indicators ` + `for informed investment recommendations.` } else { nextInstruction += `If you need more specific information to provide a comprehensive ` + `answer, call the appropriate tools. If you have sufficient data, provide your final analysis.` } allMessages.push({ role: 'system', content: nextInstruction }) continue } else { // Final synthesis iteration: always perform a final completion and return allMessages.push({ role: 'system', content: 'Based on all the data gathered from previous tool calls, provide your ' + 'comprehensive final analysis and recommendations.' }) const finalResponse = await this.openai.chat.completions.create({ model, messages: allMessages, temperature, max_tokens }) const finalMessage = finalResponse.choices[0]?.message?.content || 'Unable to generate final response' // Add final response to conversation history if memory is enabled if (shouldUseMemory) { const assistantMessage: ConversationMessage = { role: 'assistant', content: finalMessage, timestamp: new Date().toISOString(), tools_used: Array.from(uniqueToolsUsed), metadata: { model, temperature, max_tokens, iterations_used: currentIteration + 1 } } this.memoryManager!.addMessage(sessionId!, assistantMessage) } return this.buildFinalResponse( finalMessage, Array.from(uniqueToolsUsed), currentIteration + 1, iterationDetails, request, shouldUseMemory, session, conversationContext, updatePreferences || false ) } } else { // No tools called, this is the final response // Iteration ${currentIteration}: No more tools needed, providing final response const finalResponse = message.content || 'Unable to process query' // Add final response to conversation history if memory is enabled if (shouldUseMemory) { const assistantMessage: ConversationMessage = { role: 'assistant', content: finalResponse, timestamp: new Date().toISOString(), tools_used: Array.from(uniqueToolsUsed), metadata: { model, temperature, max_tokens, iterations_used: currentIteration } } this.memoryManager!.addMessage(sessionId!, assistantMessage) } return this.buildFinalResponse( finalResponse, Array.from(uniqueToolsUsed), currentIteration, iterationDetails, request, shouldUseMemory, session, conversationContext, updatePreferences || false ) } } throw new Error(`Query exceeded maximum iterations (${maxIterations}). ` + `Consider simplifying the query or increasing maxIterations.`) } catch (error) { throw new Error(`MCP Client Error: ${error instanceof Error ? error.message : String(error)}`) } } /** * Execute function calls using the NSE India API */ private async executeFunctionCall(toolCall: OpenAI.Chat.Completions.ChatCompletionMessageToolCall): Promise { const { function: { name, arguments: args } } = toolCall try { const parsedArgs = typeof args === 'string' ? JSON.parse(args) : args const result = await handleMCPToolCall(this.nseClient, name, parsedArgs) return result } catch (error) { return { error: error instanceof Error ? error.message : String(error) } } } /** * Determine if iterations should continue based on AI response and context */ private shouldContinueIterating(message: any, currentIteration: number, maxIterations: number): boolean { // Don't exceed max iterations (save one for final synthesis) if (currentIteration >= maxIterations - 1) return false // Always continue for specific complex query patterns that need multiple steps const originalQuery = this.currentQuery?.toLowerCase() || '' // AGGRESSIVE: For technical indicator investment queries, force continuation until we get technical data if (originalQuery.includes('technical indicators') && originalQuery.includes('invest')) { // Continue until we've called technical indicators tool OR reached iteration 4 if (!this.allToolsUsed.includes('get_equity_technical_indicators') && currentIteration <= 3) { // Forcing continuation for technical indicators query (iteration ${currentIteration}) return true } } // AGGRESSIVE: For NIFTY investment queries, ensure we go deeper than just index lookup if (originalQuery.includes('nifty') && originalQuery.includes('invest') && currentIteration <= 2) { // Forcing continuation for NIFTY investment query (iteration ${currentIteration}) return true } // Check if assistant indicates more work is needed const content = message.content?.toLowerCase() || '' const needsMoreData = content.includes('i need to') || content.includes('let me analyze') || content.includes('i should get') || content.includes('need more information') || content.includes('let me check') || content.includes('i will analyze') || content.includes('let me gather') || content.includes('additional data needed') // For investment/analysis queries, be more aggressive about continuing const isInvestmentQuery = content.includes('invest') || content.includes('recommend') || content.includes('technical') || content.includes('analysis') || content.includes('indicators') // If it's an investment query and we're early in iterations, continue if (isInvestmentQuery && currentIteration <= 2) { return true } return needsMoreData } /** * Infer the purpose of an iteration based on tools called */ private inferIterationPurpose(tools: string[], iteration: number): string { if (tools.includes('get_equity_stock_indices')) { return 'Getting index composition data' } else if (tools.includes('get_equity_technical_indicators')) { return 'Analyzing technical indicators' } else if (tools.includes('get_equity_details') || tools.includes('get_equity_trade_info')) { return 'Gathering stock details and trade information' } else if (tools.includes('get_market_status')) { return 'Checking market status' } else if (tools.includes('get_all_stock_symbols')) { return 'Getting available stock symbols' } else { return `Data collection (iteration ${iteration})` } } /** * Build the final response with all tracking information */ private buildFinalResponse( finalResponse: string, toolsUsed: string[], iterationsUsed: number, iterationDetails: { iteration: number; tools_called: string[]; purpose: string; tool_parameters?: { tool_name: string; parameters: any; }[] }[], request: MCPClientRequest, shouldUseMemory: boolean, session: any, conversationContext: any, updatePreferences: boolean ): MCPClientResponse { // Update user preferences if requested and memory is enabled let preferencesUpdated = false if (shouldUseMemory && updatePreferences && request.sessionId) { preferencesUpdated = this.updateUserPreferencesFromQuery(request.sessionId, request.query!, toolsUsed) } // Build response const clientResponse: MCPClientResponse = { response: finalResponse, tools_used: toolsUsed, data_sources: ['NSE India API via MCP'], timestamp: new Date().toISOString(), iterations_used: iterationsUsed, iteration_details: iterationDetails } // Add memory-related fields if memory is enabled if (shouldUseMemory) { clientResponse.sessionId = request.sessionId clientResponse.context_used = request.includeContext clientResponse.user_preferences_updated = preferencesUpdated clientResponse.conversation_length = session?.conversationHistory?.length || 0 clientResponse.context_summarized = conversationContext.wasSummarized clientResponse.context_summary = conversationContext.summary clientResponse.token_count = conversationContext.tokenCount } return clientResponse } /** * Update user preferences based on query patterns */ private updateUserPreferencesFromQuery(sessionId: string, query: string, toolsUsed: string[]): boolean { if (!this.memoryManager) return false const session = this.memoryManager.getOrCreateSession(sessionId) let updated = false const queryLower = query.toLowerCase() // Detect analysis style preference if (queryLower.includes('brief') || queryLower.includes('summary')) { if (session.userPreferences.analysisStyle !== 'brief') { session.userPreferences.analysisStyle = 'brief' updated = true } } else if (queryLower.includes('detailed') || queryLower.includes('comprehensive')) { if (session.userPreferences.analysisStyle !== 'detailed') { session.userPreferences.analysisStyle = 'detailed' updated = true } } else if (queryLower.includes('technical') || queryLower.includes('indicators')) { if (session.userPreferences.analysisStyle !== 'technical') { session.userPreferences.analysisStyle = 'technical' updated = true } } // Detect preferred stocks from query const stockSymbols = this.extractStockSymbols(query) stockSymbols.forEach(symbol => { if (!session.userPreferences.preferredStocks.includes(symbol)) { session.userPreferences.preferredStocks.push(symbol) if (session.userPreferences.preferredStocks.length > 10) { session.userPreferences.preferredStocks = session.userPreferences.preferredStocks.slice(-10) } updated = true } }) // Detect preferred indices const indexKeywords = ['nifty', 'banknifty', 'sensex', 'midcap', 'smallcap'] indexKeywords.forEach(keyword => { if (queryLower.includes(keyword)) { const indexName = keyword.toUpperCase() if (!session.userPreferences.preferredIndices.includes(indexName)) { session.userPreferences.preferredIndices.push(indexName) updated = true } } }) if (updated) { this.memoryManager.updatePreferences(sessionId, session.userPreferences) } return updated } // ============================================================================ // Memory Management Methods (only available if memory is enabled) // ============================================================================ /** * Get session information */ getSessionInfo(sessionId: string): any { if (!this.memoryManager) { throw new Error('Memory is not enabled for this MCP client') } return this.memoryManager.getSessionStats(sessionId) } /** * Update user preferences manually */ updateUserPreferences(sessionId: string, preferences: Record): void { if (!this.memoryManager) { throw new Error('Memory is not enabled for this MCP client') } this.memoryManager.updatePreferences(sessionId, preferences) } /** * Get conversation history */ getConversationHistory(sessionId: string, maxMessages?: number): ConversationMessage[] { if (!this.memoryManager) { throw new Error('Memory is not enabled for this MCP client') } return this.memoryManager.getConversationContextSync(sessionId, maxMessages) } /** * Get conversation history with context summarization */ async getConversationHistoryWithSummarization( sessionId: string, maxMessages?: number, systemPrompt?: string ): Promise<{ messages: ConversationMessage[] summary?: any wasSummarized: boolean tokenCount: any }> { if (!this.memoryManager) { throw new Error('Memory is not enabled for this MCP client') } return this.memoryManager.getConversationContext(sessionId, maxMessages, systemPrompt) } /** * Clear session data */ clearSession(sessionId: string): void { if (!this.memoryManager) { throw new Error('Memory is not enabled for this MCP client') } this.memoryManager.clearSession(sessionId) } /** * Export session data */ exportSessionData(sessionId: string): any { if (!this.memoryManager) { throw new Error('Memory is not enabled for this MCP client') } return this.memoryManager.exportSessionData(sessionId) } /** * Check if context needs summarization */ async needsContextSummarization(sessionId: string, systemPrompt?: string): Promise { if (!this.memoryManager) { throw new Error('Memory is not enabled for this MCP client') } return this.memoryManager.needsContextSummarization(sessionId, systemPrompt) } /** * Get context statistics */ async getContextStats(sessionId: string, systemPrompt?: string): Promise<{ messageCount: number tokenCount: any needsSummarization: boolean contextWindowUsage: number }> { if (!this.memoryManager) { throw new Error('Memory is not enabled for this MCP client') } return this.memoryManager.getContextStats(sessionId, systemPrompt) } /** * Force context summarization */ async forceContextSummarization(sessionId: string, systemPrompt?: string): Promise { if (!this.memoryManager) { throw new Error('Memory is not enabled for this MCP client') } return this.memoryManager.forceContextSummarization(sessionId, systemPrompt) } /** * Update context window configuration */ updateContextWindowConfig(config: Record): void { if (!this.memoryManager) { throw new Error('Memory is not enabled for this MCP client') } this.memoryManager.updateContextWindowConfig(config) } /** * Get context window configuration */ getContextWindowConfig(): any { if (!this.memoryManager) { throw new Error('Memory is not enabled for this MCP client') } return this.memoryManager.getContextWindowConfig() } /** * Cleanup expired sessions */ cleanupExpiredSessions(): void { if (!this.memoryManager) { throw new Error('Memory is not enabled for this MCP client') } this.memoryManager.cleanupExpiredSessions() } // ============================================================================ // Utility Methods // ============================================================================ /** * Get available tools information */ getAvailableTools(): any[] { return this.availableTools } /** * Get tools in OpenAI function format */ getOpenAIFunctions(): OpenAI.Chat.Completions.ChatCompletionCreateParams.Function[] { return this.convertToolsToOpenAIFunctions() } /** * Test the MCP client connection */ async testConnection(): Promise { try { await this.processQuery({ query: 'What is the current market status?', useMemory: false }) return true } catch (error) { console.error('MCP Client test failed:', error) return false } } /** * Test the MCP client with memory */ async testConnectionWithMemory(sessionId: string): Promise { if (!this.memoryManager) { throw new Error('Memory is not enabled for this MCP client') } try { await this.processQuery({ query: 'What is the current market status?', sessionId, useMemory: true, includeContext: false }) return true } catch (error) { console.error('MCP Client with Memory test failed:', error) return false } } /** * Get client configuration */ getConfig(): MCPClientConfig { return { ...this.config } } /** * Check if memory is enabled */ isMemoryEnabled(): boolean { return this.config.enableMemory === true && this.memoryManager !== undefined } /** * Check if context summarization is enabled */ isContextSummarizationEnabled(): boolean { return this.config.enableContextSummarization === true && this.memoryManager !== undefined } /** * Get last summarization for a session */ getLastSummarization(sessionId: string): any { if (!this.memoryManager) return null return this.memoryManager.getLastSummarization(sessionId) } /** * Get summarization history for a session */ getSummarizationHistory(sessionId: string, limit?: number): any[] { if (!this.memoryManager) return [] return this.memoryManager.getSummarizationHistory(sessionId, limit) } /** * Get summarization summary for a session */ getSummarizationSummary(sessionId: string): any { if (!this.memoryManager) return null return this.memoryManager.getSummarizationSummary(sessionId) } /** * Get OpenAI messages for a session (including system message) */ getOpenAIMessages(sessionId: string): any { if (!this.memoryManager) return null const session = this.memoryManager.getOrCreateSession(sessionId) const systemPrompt = this.memoryManager.getContextualSystemPrompt(sessionId) return { systemPrompt, conversationHistory: session.conversationHistory } } } // Export singleton instance with default configuration export const mcpClient = new MCPClient({ enableMemory: true, enableContextSummarization: true }) // Export factory function for custom configurations export function createMCPClient(config: MCPClientConfig): MCPClient { return new MCPClient(config) } ================================================ FILE: src/mcp/context-summarizer.ts ================================================ import OpenAI from 'openai' export interface ContextSummary { summary: string keyPoints: string[] importantStocks: string[] importantIndices: string[] userPreferences: Record timestamp: string originalMessageCount: number } export interface ContextWindowConfig { maxTokens: number reservedTokens: number // Tokens reserved for system prompt and response summarizationThreshold: number // When to start summarizing (as percentage of max tokens) minMessagesToSummarize: number // Minimum messages before summarization summaryCompressionRatio: number // How much to compress (0.1 = 10% of original) } export interface TokenCountResult { totalTokens: number messageTokens: number[] systemPromptTokens: number estimatedResponseTokens: number } export class ContextSummarizer { private openai: OpenAI private config: ContextWindowConfig constructor(openai: OpenAI, config: Partial = {}) { this.openai = openai this.config = { maxTokens: 8000, // Default context window reservedTokens: 2000, // Reserve tokens for system prompt and response summarizationThreshold: 0.7, // Start summarizing at 70% of available tokens minMessagesToSummarize: 10, // Don't summarize until we have at least 10 messages summaryCompressionRatio: 0.3, // Compress to 30% of original size ...config } } /** * Estimate token count for a message (rough approximation) */ private estimateTokenCount(text: string | null | undefined): number { // Rough estimation: 1 token ≈ 4 characters for English text // This is a simplified approach - in production, use tiktoken or similar if (!text || typeof text !== 'string') { return 0 } return Math.ceil(text.length / 4) } /** * Count tokens for a conversation */ countTokens(messages: any[], systemPrompt: string): TokenCountResult { const systemPromptTokens = this.estimateTokenCount(systemPrompt) const messageTokens = messages.map(msg => { if (msg && msg.content) { const tokens = this.estimateTokenCount(msg.content) // Ensure we return a valid number return isNaN(tokens) ? 0 : tokens } return 0 }) // Filter out any NaN or invalid values before reducing const validTokens = messageTokens.filter(count => typeof count === 'number' && !isNaN(count)) const totalMessageTokens = validTokens.reduce((sum, count) => sum + count, 0) const totalTokens = systemPromptTokens + totalMessageTokens + this.config.reservedTokens return { totalTokens, messageTokens, systemPromptTokens, estimatedResponseTokens: this.config.reservedTokens } } /** * Check if context needs summarization */ needsSummarization(messages: any[], systemPrompt: string): boolean { const tokenCount = this.countTokens(messages, systemPrompt) // Calculate threshold based on maxTokens (not availableTokens) // because tokenCount.totalTokens already includes reservedTokens const threshold = this.config.maxTokens * this.config.summarizationThreshold return ( messages.length >= this.config.minMessagesToSummarize && tokenCount.totalTokens > threshold ) } /** * Extract key information from messages for summarization */ private extractKeyInformation(messages: any[]): { stocks: Set indices: Set queries: string[] tools: Set preferences: Record } { const stocks = new Set() const indices = new Set() const queries: string[] = [] const tools = new Set() const preferences: Record = {} messages.forEach(msg => { if (msg.role === 'user' && msg.content) { queries.push(msg.content) // Extract stock symbols (simple regex) const stockMatches = msg.content.match(/\b[A-Z]{2,10}\b/g) || [] stockMatches.forEach((symbol: string) => { if (!['THE', 'AND', 'OR', 'FOR', 'WITH', 'FROM', 'TO', 'IN', 'ON', 'AT', 'BY'].includes(symbol)) { stocks.add(symbol) } }) // Extract indices const indexKeywords = ['nifty', 'banknifty', 'sensex', 'midcap', 'smallcap'] indexKeywords.forEach(keyword => { if (msg.content.toLowerCase().includes(keyword)) { indices.add(keyword.toUpperCase()) } }) } if (msg.tools_used) { msg.tools_used.forEach((tool: string) => tools.add(tool)) } if (msg.metadata?.preferences) { Object.assign(preferences, msg.metadata.preferences) } }) return { stocks, indices, queries, tools, preferences } } /** * Create a context summary using AI */ async createContextSummary(messages: any[]): Promise { const keyInfo = this.extractKeyInformation(messages) // Create a summary prompt const summaryPrompt = `Please create a concise summary of this conversation about Indian stock market data. Focus on: 1. Key topics discussed 2. Important stock symbols mentioned 3. Important indices mentioned 4. User preferences and analysis style 5. Tools used 6. Main queries and their outcomes Conversation to summarize: ${messages.map((msg, i) => `${i + 1}. [${msg.role}]: ${msg.content}`).join('\n')} Please provide: - A brief summary (2-3 sentences) - Key points (bullet list) - Important stocks mentioned - Important indices mentioned - User preferences detected - Tools used Format as JSON with these fields: summary, keyPoints, importantStocks, importantIndices, userPreferences, toolsUsed` try { const response = await this.openai.chat.completions.create({ model: 'gpt-4o-mini', messages: [ { role: 'system', content: 'You are a helpful assistant that creates concise summaries of conversations. ' + 'Always respond with valid JSON only, without any markdown formatting or code blocks.' }, { role: 'user', content: summaryPrompt } ], temperature: 0.3, max_tokens: 500 }) let summaryText = response.choices[0]?.message?.content || '{}' // Clean up the response - remove markdown code blocks if present summaryText = summaryText.trim() if (summaryText.startsWith('```json')) { summaryText = summaryText.replace(/^```json\s*/, '').replace(/\s*```$/, '') } else if (summaryText.startsWith('```')) { summaryText = summaryText.replace(/^```\s*/, '').replace(/\s*```$/, '') } summaryText = summaryText.trim() let summaryData: any try { summaryData = JSON.parse(summaryText) } catch (parseError) { console.error('Failed to parse OpenAI summary response:', summaryText.substring(0, 200)) throw parseError } return { summary: summaryData.summary || 'Conversation summary', keyPoints: summaryData.keyPoints || [], importantStocks: summaryData.importantStocks || Array.from(keyInfo.stocks), importantIndices: summaryData.importantIndices || Array.from(keyInfo.indices), userPreferences: summaryData.userPreferences || keyInfo.preferences, timestamp: new Date().toISOString(), originalMessageCount: messages.length } } catch (error) { // Fallback to simple extraction if AI summarization fails console.warn('AI summarization failed, using fallback method:', error instanceof Error ? error.message : String(error)) return { summary: `Conversation with ${messages.length} messages about Indian stock market data`, keyPoints: keyInfo.queries.slice(0, 5), // First 5 queries as key points importantStocks: Array.from(keyInfo.stocks), importantIndices: Array.from(keyInfo.indices), userPreferences: keyInfo.preferences, timestamp: new Date().toISOString(), originalMessageCount: messages.length } } } /** * Optimize context by selecting most relevant messages */ async optimizeContext(messages: any[], systemPrompt: string, maxTokens: number): Promise<{ selectedMessages: any[] summary?: ContextSummary wasSummarized: boolean }> { const tokenCount = this.countTokens(messages, systemPrompt) if (tokenCount.totalTokens <= maxTokens) { return { selectedMessages: messages, wasSummarized: false } } // If we need to reduce context, prioritize recent messages and important ones const availableTokens = maxTokens - this.config.reservedTokens const systemPromptTokens = tokenCount.systemPromptTokens const targetMessageTokens = availableTokens - systemPromptTokens // Sort messages by importance (recent + with tools + user queries) const scoredMessages = messages.map((msg, index) => { let score = 0 // Recent messages get higher score score += (messages.length - index) * 10 // Messages with tools get higher score if (msg.tools_used && msg.tools_used.length > 0) { score += 50 } // User queries get higher score if (msg.role === 'user') { score += 30 } // Assistant responses get medium score if (msg.role === 'assistant') { score += 20 } return { message: msg, score, index } }) // Sort by score (highest first) scoredMessages.sort((a, b) => b.score - a.score) // Select messages that fit within token limit const selectedMessages: any[] = [] let currentTokens = 0 for (const { message } of scoredMessages) { const messageTokens = this.estimateTokenCount(message.content || '') if (currentTokens + messageTokens <= targetMessageTokens) { selectedMessages.unshift(message) // Add to beginning to maintain order currentTokens += messageTokens } else { break } } // If we still have too many messages, create a summary if (selectedMessages.length < messages.length * 0.5) { return await this.createSummarizedContext(messages, systemPrompt, maxTokens) } return { selectedMessages, wasSummarized: false } } /** * Create summarized context when too much history */ private async createSummarizedContext( messages: any[], systemPrompt: string, maxTokens: number ): Promise<{ selectedMessages: any[] summary?: ContextSummary wasSummarized: boolean }> { // Calculate how many recent messages to keep // Target: keep enough to be around 40% of max tokens after summarization // This gives room for more conversation before next summarization const targetTokensAfterSummarization = maxTokens * 0.4 // Start with keeping more messages and work backwards let recentMessageCount = Math.min(10, messages.length - 1) // Keep at least 1 for summary let recentMessages = messages.slice(-recentMessageCount) // Adjust to fit target token count while (recentMessageCount > 2) { const testTokens = this.countTokens(recentMessages, systemPrompt) if (testTokens.totalTokens <= targetTokensAfterSummarization) { break } recentMessageCount -= 2 // Remove one conversation pair at a time recentMessages = messages.slice(-recentMessageCount) } // Ensure we keep at least 2 messages (1 pair) if (recentMessageCount < 2) { recentMessageCount = Math.min(2, messages.length) recentMessages = messages.slice(-recentMessageCount) } const olderMessages = messages.slice(0, -recentMessageCount) if (olderMessages.length === 0) { return { selectedMessages: recentMessages, wasSummarized: false } } // Create summary of older messages const summary = await this.createContextSummary(olderMessages) // Create a summary message const summaryMessage = { role: 'system' as const, content: `[CONTEXT SUMMARY] ${summary.summary}\n\nKey Points: ${summary.keyPoints.join(', ')}\n` + `Important Stocks: ${summary.importantStocks.join(', ')}\n` + `Important Indices: ${summary.importantIndices.join(', ')}\n` + `User Preferences: ${JSON.stringify(summary.userPreferences)}`, timestamp: summary.timestamp, metadata: { isSummary: true, originalMessageCount: summary.originalMessageCount, summaryData: summary } } return { selectedMessages: [summaryMessage, ...recentMessages], summary, wasSummarized: true } } /** * Get optimal context for a conversation */ async getOptimalContext( messages: any[], systemPrompt: string, maxTokens?: number ): Promise<{ messages: any[] summary?: ContextSummary wasSummarized: boolean tokenCount: TokenCountResult }> { const targetTokens = maxTokens || this.config.maxTokens const tokenCount = this.countTokens(messages, systemPrompt) // Check if we should trigger summarization based on threshold const thresholdTokens = targetTokens * this.config.summarizationThreshold // If we're within limits and below threshold, return as is if (tokenCount.totalTokens <= thresholdTokens) { return { messages, wasSummarized: false, tokenCount } } // Check minimum message requirement if (messages.length < this.config.minMessagesToSummarize) { return { messages, wasSummarized: false, tokenCount } } // We've exceeded the threshold, so we should summarize // Force summarization by calling createSummarizedContext directly const summarized = await this.createSummarizedContext(messages, systemPrompt, targetTokens) return { messages: summarized.selectedMessages, summary: summarized.summary, wasSummarized: summarized.wasSummarized, tokenCount: this.countTokens(summarized.selectedMessages, systemPrompt) } } /** * Update configuration */ updateConfig(newConfig: Partial): void { this.config = { ...this.config, ...newConfig } } /** * Get current configuration */ getConfig(): ContextWindowConfig { return { ...this.config } } } ================================================ FILE: src/mcp/mcp-tools.ts ================================================ import type { NseIndia } from '../index.js' import { getGainersAndLosersByIndex, getMostActiveEquities } from '../helpers.js' // Common MCP tools configuration for NSE India servers export const mcpTools = [ { name: 'get_all_stock_symbols', description: 'Get list of all NSE equity symbols', inputSchema: { type: 'object', properties: {}, required: [], }, }, { name: 'get_equity_details', description: 'Get equity details for a specific symbol', inputSchema: { type: 'object', properties: { symbol: { type: 'string', description: 'Stock symbol (e.g., TCS, RELIANCE)', }, }, required: ['symbol'], }, }, { name: 'get_equity_trade_info', description: 'Get equity trade information for a specific symbol', inputSchema: { type: 'object', properties: { symbol: { type: 'string', description: 'Stock symbol (e.g., TCS, RELIANCE)', }, }, required: ['symbol'], }, }, { name: 'get_equity_corporate_info', description: 'Get corporate information for a specific equity symbol', inputSchema: { type: 'object', properties: { symbol: { type: 'string', description: 'Stock symbol (e.g., TCS, RELIANCE)', }, }, required: ['symbol'], }, }, { name: 'get_equity_intraday_data', description: 'Get intraday data for a specific equity symbol', inputSchema: { type: 'object', properties: { symbol: { type: 'string', description: 'Stock symbol (e.g., TCS, RELIANCE)', }, }, required: ['symbol'], }, }, { name: 'get_equity_historical_data', description: 'Get historical data for a specific equity symbol', inputSchema: { type: 'object', properties: { symbol: { type: 'string', description: 'Stock symbol (e.g., TCS, RELIANCE)', }, start_date: { type: 'string', description: 'Start date in YYYY-MM-DD format', }, end_date: { type: 'string', description: 'End date in YYYY-MM-DD format', }, }, required: ['symbol'], }, }, { name: 'get_equity_series', description: 'Get series data for a specific equity symbol', inputSchema: { type: 'object', properties: { symbol: { type: 'string', description: 'Stock symbol (e.g., TCS, RELIANCE)', }, }, required: ['symbol'], }, }, { name: 'get_equity_stock_indices', description: 'Get equity stock indices for a specific index', inputSchema: { type: 'object', properties: { index: { type: 'string', description: 'Index name (e.g., NIFTY, BANKNIFTY)', }, }, required: ['index'], }, }, { name: 'get_index_intraday_data', description: 'Get intraday data for a specific index', inputSchema: { type: 'object', properties: { index: { type: 'string', description: 'Index name (e.g., NIFTY, BANKNIFTY)', }, }, required: ['index'], }, }, { name: 'get_index_option_chain', description: 'Get option chain data for a specific index', inputSchema: { type: 'object', properties: { index_symbol: { type: 'string', description: 'Index symbol (e.g., NIFTY, BANKNIFTY)', }, }, required: ['index_symbol'], }, }, { name: 'get_index_option_chain_contract_info', description: 'Get option chain contract information (expiry dates and strike prices) for a specific index', inputSchema: { type: 'object', properties: { index_symbol: { type: 'string', description: 'Index symbol (e.g., NIFTY, BANKNIFTY)', }, }, required: ['index_symbol'], }, }, { name: 'get_equity_option_chain', description: 'Get option chain data for a specific equity symbol', inputSchema: { type: 'object', properties: { symbol: { type: 'string', description: 'Stock symbol (e.g., TCS, RELIANCE)', }, }, required: ['symbol'], }, }, { name: 'get_commodity_option_chain', description: 'Get option chain data for a specific commodity symbol', inputSchema: { type: 'object', properties: { symbol: { type: 'string', description: 'Commodity symbol', }, }, required: ['symbol'], }, }, { name: 'get_glossary', description: 'Get NSE glossary content', inputSchema: { type: 'object', properties: {}, required: [], }, }, { name: 'get_trading_holidays', description: 'Get list of trading holidays', inputSchema: { type: 'object', properties: {}, required: [], }, }, { name: 'get_clearing_holidays', description: 'Get list of clearing holidays', inputSchema: { type: 'object', properties: {}, required: [], }, }, { name: 'get_market_status', description: 'Get current market status', inputSchema: { type: 'object', properties: {}, required: [], }, }, { name: 'get_market_turnover', description: 'Get market turnover data', inputSchema: { type: 'object', properties: {}, required: [], }, }, { name: 'get_all_indices', description: 'Get list of all indices', inputSchema: { type: 'object', properties: {}, required: [], }, }, { name: 'get_index_names', description: 'Get list of index names', inputSchema: { type: 'object', properties: {}, required: [], }, }, { name: 'get_circulars', description: 'Get list of circulars', inputSchema: { type: 'object', properties: {}, required: [], }, }, { name: 'get_latest_circulars', description: 'Get list of latest circulars', inputSchema: { type: 'object', properties: {}, required: [], }, }, { name: 'get_equity_master', description: 'Get equity master data with categorized indices', inputSchema: { type: 'object', properties: {}, required: [], }, }, { name: 'get_pre_open_market_data', description: 'Get pre-open market data', inputSchema: { type: 'object', properties: {}, required: [], }, }, { name: 'get_merged_daily_reports_capital', description: 'Get merged daily reports for capital market', inputSchema: { type: 'object', properties: {}, required: [], }, }, { name: 'get_merged_daily_reports_derivatives', description: 'Get merged daily reports for derivatives', inputSchema: { type: 'object', properties: {}, required: [], }, }, { name: 'get_merged_daily_reports_debt', description: 'Get merged daily reports for debt market', inputSchema: { type: 'object', properties: {}, required: [], }, }, { name: 'get_equity_technical_indicators', description: 'Get technical indicators for a specific equity symbol', inputSchema: { type: 'object', properties: { symbol: { type: 'string', description: 'Stock symbol (e.g., TCS, RELIANCE)', }, period: { type: 'number', description: 'Number of days for historical data (default: 200)', }, sma_periods: { type: 'array', items: { type: 'number' }, description: 'Array of periods for SMA indicators (e.g., [5, 10, 20, 50])', }, ema_periods: { type: 'array', items: { type: 'number' }, description: 'Array of periods for EMA indicators (e.g., [5, 10, 20, 50])', }, rsi_period: { type: 'number', description: 'RSI period (default: 14)', }, bb_period: { type: 'number', description: 'Bollinger Bands period (default: 20)', }, bb_std_dev: { type: 'number', description: 'Bollinger Bands standard deviation (default: 2)', }, show_only_latest: { type: 'boolean', description: 'Show only latest values (default: true)', }, }, required: ['symbol'], }, }, { name: 'get_gainers_and_losers_by_index', description: 'Get top gainers and losers for a specific index', inputSchema: { type: 'object', properties: { index_symbol: { type: 'string', description: 'Index symbol (e.g., NIFTY 50, NIFTY BANK)', }, }, required: ['index_symbol'], }, }, { name: 'get_most_active_equities', description: 'Get most actively traded equities for a specific index, sorted by volume and value', inputSchema: { type: 'object', properties: { index_symbol: { type: 'string', description: 'Index symbol (e.g., NIFTY 50, NIFTY BANK)', }, }, required: ['index_symbol'], }, }, { name: 'get_equity_chart_historical_data', description: 'Get historical chart data from charting.nseindia.com for equity symbols with OHLC candle data', inputSchema: { type: 'object', properties: { symbol: { type: 'string', description: 'Equity symbol with series code (e.g., ONGC, TCS)', }, start: { type: 'string', description: 'Optional unix timestamp for start date (e.g., 1775834999)', }, end: { type: 'string', description: 'Optional unix timestamp for end date (e.g., 1775999513)', }, token: { type: 'string', description: 'NSE script code (token / scripCode) for the symbol. ' + 'If omitted, it is looked up automatically via get_equity_chart_symbol_info.', }, symbol_type: { type: 'string', description: 'Type of symbol - Equity or Index (default: Equity)', }, chart_type: { type: 'string', description: 'Chart type - I for intraday, D for daily (default: I)', }, time_interval: { type: 'string', description: 'Time interval in minutes - 1, 5, 15, 30, 60. (default: 5)', }, }, required: ['symbol'], }, }, { name: 'get_equity_chart_symbol_info', description: 'Look up NSE charting symbol information for an equity symbol. Returns scripCode (token) ' + 'needed by get_equity_chart_historical_data. Call this first when you do not already know the token.', inputSchema: { type: 'object', properties: { symbol: { type: 'string', description: 'Equity symbol with or without series code (e.g., ONGC or ONGC)', }, segment: { type: 'string', description: 'Optional market segment filter. Leave empty to search all segments.', }, }, required: ['symbol'], }, }, ] // Common tool call handler function export async function handleMCPToolCall( nseClient: NseIndia, name: string, args: Record ): Promise { let result: unknown switch (name) { case 'get_all_stock_symbols': { result = await nseClient.getAllStockSymbols() break } case 'get_equity_details': { if (!args?.symbol || typeof args.symbol !== 'string') { throw new Error('Symbol parameter is required and must be a string') } result = await nseClient.getEquityDetails(args.symbol) break } case 'get_equity_trade_info': { if (!args?.symbol || typeof args.symbol !== 'string') { throw new Error('Symbol parameter is required and must be a string') } result = await nseClient.getEquityTradeInfo(args.symbol) break } case 'get_equity_corporate_info': { if (!args?.symbol || typeof args.symbol !== 'string') { throw new Error('Symbol parameter is required and must be a string') } result = await nseClient.getEquityCorporateInfo(args.symbol) break } case 'get_equity_intraday_data': { if (!args?.symbol || typeof args.symbol !== 'string') { throw new Error('Symbol parameter is required and must be a string') } result = await nseClient.getEquityIntradayData(args.symbol) break } case 'get_equity_historical_data': { if (!args?.symbol || typeof args.symbol !== 'string') { throw new Error('Symbol parameter is required and must be a string') } const range = args.start_date && args.end_date && typeof args.start_date === 'string' && typeof args.end_date === 'string' ? { start: new Date(args.start_date), end: new Date(args.end_date) } : undefined result = await nseClient.getEquityHistoricalData(args.symbol, range) break } case 'get_equity_series': { if (!args?.symbol || typeof args.symbol !== 'string') { throw new Error('Symbol parameter is required and must be a string') } result = await nseClient.getEquitySeries(args.symbol) break } case 'get_equity_stock_indices': { if (!args?.index || typeof args.index !== 'string') { throw new Error('Index parameter is required and must be a string') } result = await nseClient.getEquityStockIndices(args.index) break } case 'get_index_intraday_data': { if (!args?.index || typeof args.index !== 'string') { throw new Error('Index parameter is required and must be a string') } result = await nseClient.getIndexIntradayData(args.index) break } case 'get_index_option_chain': { if (!args?.index_symbol || typeof args.index_symbol !== 'string') { throw new Error('Index symbol parameter is required and must be a string') } result = await nseClient.getIndexOptionChain(args.index_symbol) break } case 'get_index_option_chain_contract_info': { if (!args?.index_symbol || typeof args.index_symbol !== 'string') { throw new Error('Index symbol parameter is required and must be a string') } result = await nseClient.getIndexOptionChainContractInfo(args.index_symbol) break } case 'get_equity_option_chain': { if (!args?.symbol || typeof args.symbol !== 'string') { throw new Error('Symbol parameter is required and must be a string') } result = await nseClient.getEquityOptionChain(args.symbol) break } case 'get_commodity_option_chain': { if (!args?.symbol || typeof args.symbol !== 'string') { throw new Error('Symbol parameter is required and must be a string') } result = await nseClient.getCommodityOptionChain(args.symbol) break } case 'get_glossary': { result = await nseClient.getGlossary() break } case 'get_trading_holidays': { result = await nseClient.getTradingHolidays() break } case 'get_clearing_holidays': { result = await nseClient.getClearingHolidays() break } case 'get_market_status': { result = await nseClient.getMarketStatus() break } case 'get_market_turnover': { result = await nseClient.getMarketTurnover() break } case 'get_all_indices': { result = await nseClient.getAllIndices() break } case 'get_index_names': { result = await nseClient.getIndexNames() break } case 'get_circulars': { result = await nseClient.getCirculars() break } case 'get_latest_circulars': { result = await nseClient.getLatestCirculars() break } case 'get_equity_master': { result = await nseClient.getEquityMaster() break } case 'get_pre_open_market_data': { result = await nseClient.getPreOpenMarketData() break } case 'get_merged_daily_reports_capital': { result = await nseClient.getMergedDailyReportsCapital() break } case 'get_merged_daily_reports_derivatives': { result = await nseClient.getMergedDailyReportsDerivatives() break } case 'get_merged_daily_reports_debt': { result = await nseClient.getMergedDailyReportsDebt() break } case 'get_equity_technical_indicators': { if (!args?.symbol || typeof args.symbol !== 'string') { throw new Error('Symbol parameter is required and must be a string') } const options: Record = {} const showOnlyLatest = args.show_only_latest !== undefined ? args.show_only_latest : true if (args.period && typeof args.period === 'number') { options.period = args.period } if (args.sma_periods && Array.isArray(args.sma_periods)) { options.smaPeriods = args.sma_periods } if (args.ema_periods && Array.isArray(args.ema_periods)) { options.emaPeriods = args.ema_periods } if (args.rsi_period && typeof args.rsi_period === 'number') { options.rsiPeriod = args.rsi_period } if (args.bb_period && typeof args.bb_period === 'number') { options.bbPeriod = args.bb_period } if (args.bb_std_dev && typeof args.bb_std_dev === 'number') { options.bbStdDev = args.bb_std_dev } const indicators = await nseClient.getTechnicalIndicators( args.symbol, (options.period as number) || 200, options ) // Helper function to round numbers to 2 decimal places const roundTo2Decimals = (value: number | null | undefined): number | null => { return value !== null && value !== undefined ? Math.round(value * 100) / 100 : null } // Helper function to round array of numbers to 2 decimal places const roundArrayTo2Decimals = (arr: number[]): number[] => { return arr.map(value => roundTo2Decimals(value) ?? 0) } if (showOnlyLatest) { // Return only the latest values const latestIndicators: Record = {} // Process SMA indicators latestIndicators.sma = {} Object.keys(indicators.sma).forEach(key => { const values = indicators.sma[key] ; (latestIndicators.sma as Record)[key] = values.length > 0 ? roundTo2Decimals(values[values.length - 1]) : null }) // Process EMA indicators latestIndicators.ema = {} Object.keys(indicators.ema).forEach(key => { const values = indicators.ema[key] ; (latestIndicators.ema as Record)[key] = values.length > 0 ? roundTo2Decimals(values[values.length - 1]) : null }) // Process other indicators latestIndicators.rsi = roundTo2Decimals( indicators.rsi.length > 0 ? indicators.rsi[indicators.rsi.length - 1] : null ) latestIndicators.macd = { macd: roundTo2Decimals( indicators.macd.macd.length > 0 ? indicators.macd.macd[indicators.macd.macd.length - 1] : null ), signal: roundTo2Decimals( indicators.macd.signal.length > 0 ? indicators.macd.signal[indicators.macd.signal.length - 1] : null ), histogram: roundTo2Decimals( indicators.macd.histogram.length > 0 ? indicators.macd.histogram[indicators.macd.histogram.length - 1] : null ) } latestIndicators.bollingerBands = { upper: roundTo2Decimals( indicators.bollingerBands.upper.length > 0 ? indicators.bollingerBands.upper[indicators.bollingerBands.upper.length - 1] : null ), middle: roundTo2Decimals( indicators.bollingerBands.middle.length > 0 ? indicators.bollingerBands.middle[indicators.bollingerBands.middle.length - 1] : null ), lower: roundTo2Decimals( indicators.bollingerBands.lower.length > 0 ? indicators.bollingerBands.lower[indicators.bollingerBands.lower.length - 1] : null ) } latestIndicators.stochastic = { k: roundTo2Decimals( indicators.stochastic.k.length > 0 ? indicators.stochastic.k[indicators.stochastic.k.length - 1] : null ), d: roundTo2Decimals( indicators.stochastic.d.length > 0 ? indicators.stochastic.d[indicators.stochastic.d.length - 1] : null ) } latestIndicators.williamsR = roundTo2Decimals( indicators.williamsR.length > 0 ? indicators.williamsR[indicators.williamsR.length - 1] : null ) latestIndicators.atr = roundTo2Decimals( indicators.atr.length > 0 ? indicators.atr[indicators.atr.length - 1] : null ) latestIndicators.adx = roundTo2Decimals( indicators.adx.length > 0 ? indicators.adx[indicators.adx.length - 1] : null ) latestIndicators.obv = roundTo2Decimals( indicators.obv.length > 0 ? indicators.obv[indicators.obv.length - 1] : null ) latestIndicators.cci = roundTo2Decimals( indicators.cci.length > 0 ? indicators.cci[indicators.cci.length - 1] : null ) latestIndicators.mfi = roundTo2Decimals( indicators.mfi.length > 0 ? indicators.mfi[indicators.mfi.length - 1] : null ) latestIndicators.roc = roundTo2Decimals( indicators.roc.length > 0 ? indicators.roc[indicators.roc.length - 1] : null ) latestIndicators.momentum = roundTo2Decimals( indicators.momentum.length > 0 ? indicators.momentum[indicators.momentum.length - 1] : null ) latestIndicators.ad = roundTo2Decimals( indicators.ad.length > 0 ? indicators.ad[indicators.ad.length - 1] : null ) latestIndicators.vwap = roundTo2Decimals( indicators.vwap.length > 0 ? indicators.vwap[indicators.vwap.length - 1] : null ) result = latestIndicators } else { // Return all values with 2 decimal precision const roundedIndicators: Record = {} // Process SMA indicators roundedIndicators.sma = {} Object.keys(indicators.sma).forEach(key => { (roundedIndicators.sma as Record)[key] = roundArrayTo2Decimals(indicators.sma[key]) }) // Process EMA indicators roundedIndicators.ema = {} Object.keys(indicators.ema).forEach(key => { (roundedIndicators.ema as Record)[key] = roundArrayTo2Decimals(indicators.ema[key]) }) // Process other indicators roundedIndicators.rsi = roundArrayTo2Decimals(indicators.rsi) roundedIndicators.macd = { macd: roundArrayTo2Decimals(indicators.macd.macd), signal: roundArrayTo2Decimals(indicators.macd.signal), histogram: roundArrayTo2Decimals(indicators.macd.histogram) } roundedIndicators.bollingerBands = { upper: roundArrayTo2Decimals(indicators.bollingerBands.upper), middle: roundArrayTo2Decimals(indicators.bollingerBands.middle), lower: roundArrayTo2Decimals(indicators.bollingerBands.lower) } roundedIndicators.stochastic = { k: roundArrayTo2Decimals(indicators.stochastic.k), d: roundArrayTo2Decimals(indicators.stochastic.d) } roundedIndicators.williamsR = roundArrayTo2Decimals(indicators.williamsR) roundedIndicators.atr = roundArrayTo2Decimals(indicators.atr) roundedIndicators.adx = roundArrayTo2Decimals(indicators.adx) roundedIndicators.obv = roundArrayTo2Decimals(indicators.obv) roundedIndicators.cci = roundArrayTo2Decimals(indicators.cci) roundedIndicators.mfi = roundArrayTo2Decimals(indicators.mfi) roundedIndicators.roc = roundArrayTo2Decimals(indicators.roc) roundedIndicators.momentum = roundArrayTo2Decimals(indicators.momentum) roundedIndicators.ad = roundArrayTo2Decimals(indicators.ad) roundedIndicators.vwap = roundArrayTo2Decimals(indicators.vwap) result = roundedIndicators } break } case 'get_gainers_and_losers_by_index': { if (!args?.index_symbol || typeof args.index_symbol !== 'string') { throw new Error('Index symbol parameter is required and must be a string') } result = await getGainersAndLosersByIndex(args.index_symbol) break } case 'get_most_active_equities': { if (!args?.index_symbol || typeof args.index_symbol !== 'string') { throw new Error('Index symbol parameter is required and must be a string') } result = await getMostActiveEquities(args.index_symbol) break } case 'get_equity_chart_historical_data': { if (!args?.symbol || typeof args.symbol !== 'string') { throw new Error('Symbol parameter is required and must be a string') } const startInput = args?.start ?? args?.from_date const endInput = args?.end ?? args?.to_date const hasStartDate = startInput !== undefined && startInput !== null const hasEndDate = endInput !== undefined && endInput !== null if (hasStartDate && typeof startInput !== 'string') { throw new Error('start parameter must be a string (unix timestamp)') } if (hasEndDate && typeof endInput !== 'string') { throw new Error('end parameter must be a string (unix timestamp)') } // token is now optional — the core method auto-fetches it via getEquitySymbolInfo const token = args.token && typeof args.token === 'string' ? args.token : undefined const symbolType = args.symbol_type && typeof args.symbol_type === 'string' ? args.symbol_type : 'Equity' const chartType = args.chart_type && typeof args.chart_type === 'string' ? args.chart_type : 'I' const timeInterval = args.time_interval && typeof args.time_interval === 'string' ? args.time_interval : '5' let range if (hasStartDate || hasEndDate) { const end = hasEndDate ? new Date(Number(endInput) * 1000) : new Date() const start = hasStartDate ? new Date(Number(startInput) * 1000) : new Date(end.getTime() - 24 * 60 * 60 * 1000) if (!(start.getTime() > 0 && end.getTime() > 0)) { throw new Error('Invalid date format. start/end must be unix timestamps') } range = { start, end } } result = await nseClient.getEquityChartHistoricalData( args.symbol, range, token, symbolType, chartType, timeInterval ) break } case 'get_equity_chart_symbol_info': { if (!args?.symbol || typeof args.symbol !== 'string') { throw new Error('Symbol parameter is required and must be a string') } const segment = args.segment && typeof args.segment === 'string' ? args.segment : '' result = await nseClient.getEquitySymbolInfo(args.symbol, segment) break } default: throw new Error(`Unknown tool: ${name}`) } return result } ================================================ FILE: src/mcp/memory-manager.ts ================================================ import * as fs from 'fs' import { ContextSummarizer, ContextSummary, ContextWindowConfig } from './context-summarizer' import OpenAI from 'openai' export interface ConversationMessage { role: 'user' | 'assistant' | 'system' content: string timestamp: string tools_used?: string[] metadata?: Record } export interface UserSession { sessionId: string userId?: string startTime: string lastActivity: string conversationHistory: ConversationMessage[] userPreferences: UserPreferences contextData: ContextData } export interface UserPreferences { preferredStocks: string[] preferredIndices: string[] analysisStyle: 'detailed' | 'brief' | 'technical' language: string timezone: string notificationSettings: { priceAlerts: boolean marketUpdates: boolean } } export interface SummarizationRecord { timestamp: string originalMessageCount: number summarizedMessageCount: number originalMessages: ConversationMessage[] summary: ContextSummary tokensSaved: number triggerReason: string } export interface ContextData { recentQueries: string[] frequentlyAccessedStocks: Record frequentlyUsedTools: Record marketContext: { currentMarketStatus?: any lastMarketUpdate?: string activeIndices?: string[] } userGoals: string[] investmentProfile?: 'conservative' | 'moderate' | 'aggressive' summarizationHistory?: SummarizationRecord[] lastSummarization?: SummarizationRecord } export interface MemoryConfig { maxConversationHistory: number maxRecentQueries: number sessionTimeoutMinutes: number persistToFile: boolean memoryFilePath: string contextWindowConfig: Partial } export class MemoryManager { private sessions: Map = new Map() private config: MemoryConfig private memoryFilePath: string private contextSummarizer: ContextSummarizer constructor(config: Partial = {}) { this.config = { maxConversationHistory: 50, maxRecentQueries: 20, sessionTimeoutMinutes: 30, persistToFile: true, memoryFilePath: './memory-data.json', contextWindowConfig: { maxTokens: 8000, reservedTokens: 2000, summarizationThreshold: 0.6, minMessagesToSummarize: 6, summaryCompressionRatio: 0.3 }, ...config } this.memoryFilePath = this.config.memoryFilePath // Initialize context summarizer const openai = new OpenAI({ apiKey: process.env.OPENAI_API_KEY, }) this.contextSummarizer = new ContextSummarizer(openai, this.config.contextWindowConfig) // Load any previously saved memory data synchronously so it's available immediately this.loadMemoryFromFile() } /** * Create or get existing user session */ getOrCreateSession(sessionId: string, userId?: string): UserSession { let session = this.sessions.get(sessionId) if (!session) { session = { sessionId, userId, startTime: new Date().toISOString(), lastActivity: new Date().toISOString(), conversationHistory: [], userPreferences: { preferredStocks: [], preferredIndices: [], analysisStyle: 'detailed', language: 'en', timezone: 'Asia/Kolkata', notificationSettings: { priceAlerts: false, marketUpdates: false } }, contextData: { recentQueries: [], frequentlyAccessedStocks: {}, frequentlyUsedTools: {}, marketContext: {}, userGoals: [] } } this.sessions.set(sessionId, session) } else { // Update last activity session.lastActivity = new Date().toISOString() } return session } /** * Add message to conversation history */ addMessage(sessionId: string, message: ConversationMessage): void { const session = this.getOrCreateSession(sessionId) // Add message to history session.conversationHistory.push(message) // Trim history if it exceeds max length if (session.conversationHistory.length > this.config.maxConversationHistory) { session.conversationHistory = session.conversationHistory.slice(-this.config.maxConversationHistory) } // Update context data if (message.role === 'user') { this.updateRecentQueries(sessionId, message.content) } if (message.tools_used) { this.updateToolUsage(sessionId, message.tools_used) } this.saveMemoryToFile() } /** * Update recent queries */ private updateRecentQueries(sessionId: string, query: string): void { const session = this.sessions.get(sessionId) if (!session) return // Add to recent queries session.contextData.recentQueries.unshift(query) // Trim if exceeds max length if (session.contextData.recentQueries.length > this.config.maxRecentQueries) { session.contextData.recentQueries = session.contextData.recentQueries.slice(0, this.config.maxRecentQueries) } } /** * Update tool usage statistics */ private updateToolUsage(sessionId: string, tools: string[]): void { const session = this.sessions.get(sessionId) if (!session) return tools.forEach(tool => { session.contextData.frequentlyUsedTools[tool] = (session.contextData.frequentlyUsedTools[tool] || 0) + 1 }) } /** * Update stock access frequency */ updateStockAccess(sessionId: string, symbol: string): void { const session = this.sessions.get(sessionId) if (!session) return session.contextData.frequentlyAccessedStocks[symbol] = (session.contextData.frequentlyAccessedStocks[symbol] || 0) + 1 } /** * Update user preferences */ updatePreferences(sessionId: string, preferences: Partial): void { const session = this.sessions.get(sessionId) if (!session) return session.userPreferences = { ...session.userPreferences, ...preferences } this.saveMemoryToFile() } /** * Update market context */ updateMarketContext(sessionId: string, marketData: Record): void { const session = this.sessions.get(sessionId) if (!session) return session.contextData.marketContext = { ...session.contextData.marketContext, currentMarketStatus: marketData, lastMarketUpdate: new Date().toISOString() } } /** * Get conversation context for AI with intelligent summarization */ async getConversationContext( sessionId: string, maxMessages?: number, systemPrompt?: string, persistSummarization = true ): Promise<{ messages: ConversationMessage[] summary?: ContextSummary wasSummarized: boolean tokenCount: any }> { const session = this.sessions.get(sessionId) if (!session) return { messages: [], wasSummarized: false, tokenCount: { totalTokens: 0 } } let messages = session.conversationHistory // Apply maxMessages limit if specified if (maxMessages && messages.length > maxMessages) { messages = messages.slice(-maxMessages) } // If no system prompt provided, use default const prompt = systemPrompt || this.getContextualSystemPrompt(sessionId) // Calculate tokens before optimization const tokensBefore = this.contextSummarizer.countTokens(messages, prompt) // Get optimized context with summarization const optimizedContext = await this.contextSummarizer.getOptimalContext(messages, prompt) // If summarization occurred and persistSummarization is true, update the session history if (optimizedContext.wasSummarized && persistSummarization) { // Calculate tokens saved const tokensAfter = optimizedContext.tokenCount const tokensSaved = tokensBefore.totalTokens - tokensAfter.totalTokens // Create summarization record const summarizationRecord: SummarizationRecord = { timestamp: new Date().toISOString(), originalMessageCount: messages.length, summarizedMessageCount: optimizedContext.messages.length, originalMessages: messages, // Store original messages before summarization summary: optimizedContext.summary!, tokensSaved: tokensSaved, triggerReason: `Token threshold exceeded: ${tokensBefore.totalTokens} > ` + `${this.config.contextWindowConfig.maxTokens! * (this.config.contextWindowConfig.summarizationThreshold || 0.7)}` } // Initialize summarization history if needed if (!session.contextData.summarizationHistory) { session.contextData.summarizationHistory = [] } // Add to history (keep last 10 summarizations) session.contextData.summarizationHistory.push(summarizationRecord) if (session.contextData.summarizationHistory.length > 10) { session.contextData.summarizationHistory = session.contextData.summarizationHistory.slice(-10) } // Update last summarization session.contextData.lastSummarization = summarizationRecord // Update conversation history with summarized version session.conversationHistory = optimizedContext.messages this.saveMemoryToFile() } return { messages: optimizedContext.messages, summary: optimizedContext.summary, wasSummarized: optimizedContext.wasSummarized, tokenCount: optimizedContext.tokenCount } } /** * Get conversation context for AI (backward compatibility) */ getConversationContextSync(sessionId: string, maxMessages = 10): ConversationMessage[] { const session = this.sessions.get(sessionId) if (!session) return [] return session.conversationHistory.slice(-maxMessages) } /** * Get user context summary */ getUserContextSummary(sessionId: string): string { const session = this.sessions.get(sessionId) if (!session) return '' const { userPreferences, contextData } = session let contextSummary = `User Preferences:\n` contextSummary += `- Analysis Style: ${userPreferences.analysisStyle}\n` contextSummary += `- Language: ${userPreferences.language}\n` contextSummary += `- Timezone: ${userPreferences.timezone}\n` if (userPreferences.preferredStocks.length > 0) { contextSummary += `- Preferred Stocks: ${userPreferences.preferredStocks.join(', ')}\n` } if (userPreferences.preferredIndices.length > 0) { contextSummary += `- Preferred Indices: ${userPreferences.preferredIndices.join(', ')}\n` } if (contextData.frequentlyAccessedStocks && Object.keys(contextData.frequentlyAccessedStocks).length > 0) { const topStocks = Object.entries(contextData.frequentlyAccessedStocks) .sort(([,a], [,b]) => b - a) .slice(0, 5) .map(([symbol]) => symbol) contextSummary += `- Frequently Accessed Stocks: ${topStocks.join(', ')}\n` } if (contextData.recentQueries.length > 0) { contextSummary += `- Recent Queries: ${contextData.recentQueries.slice(0, 3).join('; ')}\n` } if (contextData.userGoals.length > 0) { contextSummary += `- User Goals: ${contextData.userGoals.join(', ')}\n` } return contextSummary } /** * Get system prompt with context */ getContextualSystemPrompt(sessionId: string): string { const basePrompt = 'You are a helpful assistant that provides information about Indian stock market data from NSE India. ' + 'You have access to various tools to fetch real-time market data, stock information, ' + 'historical data, and more. ' + 'When a user asks a question, use the appropriate tools to gather the necessary data ' + 'and provide a comprehensive answer. ' + 'Always format your responses in a clear, professional manner with proper markdown ' + 'formatting when appropriate.' const userContext = this.getUserContextSummary(sessionId) if (userContext) { return `${basePrompt}\n\nUser Context:\n${userContext}\n\n` + `Use this context to provide personalized responses and remember user preferences.` } return basePrompt } /** * Clean up expired sessions */ cleanupExpiredSessions(): void { const now = new Date() const timeoutMs = this.config.sessionTimeoutMinutes * 60 * 1000 for (const [sessionId, session] of this.sessions.entries()) { const lastActivity = new Date(session.lastActivity) if (now.getTime() - lastActivity.getTime() > timeoutMs) { this.sessions.delete(sessionId) } } } /** * Save memory to file (synchronous to guarantee persistence before returning) */ private saveMemoryToFile(): void { if (!this.config.persistToFile) return try { const memoryData = { sessions: Object.fromEntries(this.sessions), config: this.config, lastSaved: new Date().toISOString() } fs.writeFileSync(this.memoryFilePath, JSON.stringify(memoryData, null, 2)) } catch (error) { console.error('Failed to save memory to file:', error) } } /** * Load memory from file (synchronous so sessions are ready after construction) */ private loadMemoryFromFile(): void { if (!this.config.persistToFile) return try { const data = fs.readFileSync(this.memoryFilePath, 'utf-8') const memoryData = JSON.parse(data) if (memoryData.sessions) { this.sessions = new Map(Object.entries(memoryData.sessions)) } } catch (error: any) { // If file doesn't exist, start fresh silently; otherwise log a warning if (error?.code !== 'ENOENT') { console.warn('Failed to load memory from file, starting with empty memory:', error) } } } /** * Get session statistics */ getSessionStats(sessionId: string): any { const session = this.sessions.get(sessionId) if (!session) return null return { sessionId: session.sessionId, userId: session.userId, startTime: session.startTime, lastActivity: session.lastActivity, messageCount: session.conversationHistory.length, recentQueriesCount: session.contextData.recentQueries.length, frequentlyAccessedStocks: Object.keys(session.contextData.frequentlyAccessedStocks).length, frequentlyUsedTools: Object.keys(session.contextData.frequentlyUsedTools).length } } /** * Export session data */ exportSessionData(sessionId: string): any { return this.sessions.get(sessionId) } /** * Clear session data */ clearSession(sessionId: string): void { this.sessions.delete(sessionId) this.saveMemoryToFile() } /** * Check if context needs summarization for a session */ async needsContextSummarization(sessionId: string, systemPrompt?: string): Promise { const session = this.sessions.get(sessionId) if (!session) return false const prompt = systemPrompt || this.getContextualSystemPrompt(sessionId) return this.contextSummarizer.needsSummarization(session.conversationHistory, prompt) } /** * Get context statistics for a session */ async getContextStats(sessionId: string, systemPrompt?: string): Promise<{ messageCount: number tokenCount: any needsSummarization: boolean contextWindowUsage: number }> { const session = this.sessions.get(sessionId) if (!session) { return { messageCount: 0, tokenCount: { totalTokens: 0 }, needsSummarization: false, contextWindowUsage: 0 } } const prompt = systemPrompt || this.getContextualSystemPrompt(sessionId) const tokenCount = this.contextSummarizer.countTokens(session.conversationHistory, prompt) const needsSummarization = await this.needsContextSummarization(sessionId, systemPrompt) const contextWindowUsage = (tokenCount.totalTokens / this.contextSummarizer.getConfig().maxTokens) * 100 return { messageCount: session.conversationHistory.length, tokenCount, needsSummarization, contextWindowUsage } } /** * Force context summarization for a session */ async forceContextSummarization(sessionId: string, systemPrompt?: string): Promise { const session = this.sessions.get(sessionId) if (!session) return null const prompt = systemPrompt || this.getContextualSystemPrompt(sessionId) const summary = await this.contextSummarizer.createContextSummary(session.conversationHistory) // Store summary in session metadata if (!session.contextData.marketContext) { session.contextData.marketContext = {} } (session.contextData.marketContext as any).lastSummary = summary this.saveMemoryToFile() return summary } /** * Update context window configuration */ updateContextWindowConfig(config: Partial): void { this.config.contextWindowConfig = { ...this.config.contextWindowConfig, ...config } this.contextSummarizer.updateConfig(this.config.contextWindowConfig) } /** * Get context window configuration */ getContextWindowConfig(): ContextWindowConfig { return this.contextSummarizer.getConfig() } /** * Get last summarization for a session */ getLastSummarization(sessionId: string): SummarizationRecord | null { const session = this.sessions.get(sessionId) return session?.contextData.lastSummarization || null } /** * Get summarization history for a session */ getSummarizationHistory(sessionId: string, limit?: number): SummarizationRecord[] { const session = this.sessions.get(sessionId) if (!session || !session.contextData.summarizationHistory) { return [] } const history = session.contextData.summarizationHistory return limit ? history.slice(-limit) : history } /** * Get detailed summarization info (without original messages for lighter payload) */ getSummarizationSummary(sessionId: string): { totalSummarizations: number totalTokensSaved: number lastSummarization?: { timestamp: string messagesBefore: number messagesAfter: number tokensSaved: number summary: string } } | null { const session = this.sessions.get(sessionId) if (!session) return null const history = session.contextData.summarizationHistory || [] const totalTokensSaved = history.reduce((sum, record) => sum + record.tokensSaved, 0) const result: any = { totalSummarizations: history.length, totalTokensSaved } if (session.contextData.lastSummarization) { const last = session.contextData.lastSummarization result.lastSummarization = { timestamp: last.timestamp, messagesBefore: last.originalMessageCount, messagesAfter: last.summarizedMessageCount, tokensSaved: last.tokensSaved, summary: last.summary.summary } } return result } } ================================================ FILE: src/mcp/server/mcp-server-stdio.ts ================================================ import { MCPServer } from "./mcp-server" // Start the server const server = new MCPServer() console.error('NSE India MCP Server started') ================================================ FILE: src/mcp/server/mcp-server.ts ================================================ import { NseIndia } from '../../index.js' import { mcpTools, handleMCPToolCall } from '../mcp-tools.js' // Initialize NSE India client const nseClient = new NseIndia() // MCP Protocol Implementation export class MCPServer { private serverInfo = { name: 'nse-india-stdio', version: '1.2.2', } constructor() { this.setupStdinHandling() } private setupStdinHandling() { process.stdin.setEncoding('utf8') let buffer = '' process.stdin.on('data', (chunk) => { buffer += chunk // Process complete JSON messages let newlineIndex while ((newlineIndex = buffer.indexOf('\n')) !== -1) { const message = buffer.substring(0, newlineIndex).trim() buffer = buffer.substring(newlineIndex + 1) if (message) { this.handleMessage(message) } } }) process.stdin.on('end', () => { process.exit(0) }) } private async handleMessage(message: string) { let parsed: any try { parsed = JSON.parse(message) const { id, method, params } = parsed // Check if this is a notification (no id) or a request (with id) if (id === undefined) { // This is a notification - handle it but don't send response if (method === 'notifications/initialized') { // Just acknowledge the notification silently return } // For other notifications without id, ignore them return } // This is a request - validate required fields if (method === undefined) { const response = { jsonrpc: '2.0', id, error: { code: -32600, message: 'Invalid Request: missing method', }, } this.sendResponse(response) return } let result: any let error: any = null try { switch (method) { case 'initialize': result = { protocolVersion: '2024-11-05', capabilities: { tools: {}, prompts: {}, resources: {}, }, serverInfo: this.serverInfo, } break case 'tools/list': result = { tools: mcpTools } break case 'tools/call': if (!params || !params.name) { error = { code: -32602, message: 'Invalid params: missing tool name', } } else { result = await this.handleToolCall(params) } break // Add missing MCP protocol methods case 'prompts/list': result = { prompts: [] } break case 'resources/list': result = { resources: [] } break default: error = { code: -32601, message: `Method not found: ${method}`, } } } catch (err) { error = { code: -32603, message: err instanceof Error ? err.message : String(err), } } const response = { jsonrpc: '2.0', id, ...(error ? { error } : { result }), } this.sendResponse(response) } catch (err) { // Invalid JSON - only send error if we have an id if (parsed && parsed.id !== undefined) { const response = { jsonrpc: '2.0', id: parsed.id, error: { code: -32700, message: 'Parse error', }, } this.sendResponse(response) } } } private async handleToolCall(params: any) { const { name, arguments: args } = params const result = await handleMCPToolCall(nseClient, name, args) return { content: [ { type: 'text', text: JSON.stringify(result, null, 2), }, ], } } private sendResponse(response: any) { // Ensure response has all required fields const validResponse = { jsonrpc: '2.0', id: response.id, ...(response.error ? { error: response.error } : { result: response.result }), } process.stdout.write(JSON.stringify(validResponse) + '\n') } } ================================================ FILE: src/root.graphql ================================================ #import Equity from 'equity.graphql' #import StringArrayFilter from 'inputs.graphql' #import ObjectFilter from 'inputs.graphql' #import Index from 'stockIndex.graphql' input ObjectKeyFilter { filterBy: String! criteria: ObjectFilter } type Query { equities(symbolFilter:StringArrayFilter!): [Equity] indices (filter:ObjectKeyFilter): [Index] } ================================================ FILE: src/root.resolver.ts ================================================ import { ApiList, NseIndia } from './index' import { EquityDetails } from './interface' const nseIndia = new NseIndia() interface StringArrayFilter { startsWith?: string regex?: string in?: string[] nin?: string[] eq?: string neq?: string offset?: number limit?: number } interface ObjectFilter { regex?: string } function stringArrayFilter(input: string[], filter: StringArrayFilter) { let data = [...input] const { offset, limit, eq, neq, in: inside, nin, startsWith, regex } = filter if (startsWith) { data = data.filter(item => item.startsWith(startsWith)) } if (regex) { const re = new RegExp(regex) data = data.filter(item => re.test(item)) } if (inside?.length) { data = data.filter(item => inside.includes(item)) } if (nin?.length) { data = data.filter(item => !nin.includes(item)) } if (eq) { data = data.filter(item => item === eq) } if (neq) { data = data.filter(item => item !== neq) } if (offset !== undefined) { data = data.filter((_, index) => index > offset) } if (limit !== undefined) { data = data.filter((_, index) => index < limit) } return data } function objectFilter(input: any, filterBy: string, filter: ObjectFilter) { const { regex } = filter let data = [...input] if (regex) { const re = new RegExp(regex) data = data.filter((item: { [x: string]: string }) => re.test(item[filterBy])) } return data } export default { Query: { equities: async (_parent: unknown, { symbolFilter }: { symbolFilter: StringArrayFilter }): Promise => { const results = await nseIndia.getAllStockSymbols() return stringArrayFilter(results, symbolFilter) }, indices: async (_parent: unknown, { filter }: { filter: any }): Promise => { const indices = await nseIndia.getDataByEndpoint(ApiList.ALL_INDICES) if (filter) return objectFilter(indices.data, filter.filterBy, filter.criteria) return indices.data } }, Equity: { symbol: (parent: string): string => { return parent }, details: async (parent: string): Promise => { const result = await nseIndia.getEquityDetails(parent) return result } } } ================================================ FILE: src/routes.ts ================================================ import { Router } from 'express' import { openapiSpecification } from './swaggerDocOptions' import { NseIndia, ApiList } from './index' import { getGainersAndLosersByIndex, getMostActiveEquities } from './helpers' import { mcpClient, MCPClientRequest, MCPClient } from './mcp/client/mcp-client.js' const mainRouter: Router = Router() const nseIndia = new NseIndia() /** * @openapi * /: * get: * description: To get market status * tags: * - Base * produces: * - application/json * responses: * 200: * description: Returns a JSON object of NSE market status * 400: * description: Returns a JSON error object of API call */ mainRouter.get('/', async (_req, res) => { try { res.json(await nseIndia.getDataByEndpoint(ApiList.MARKET_STATUS)) } catch (error) { res.status(400).json(error) } }) /** * @openapi * /api/v1/swagger.json: * get: * description: To get open api specification for swagger documentation * tags: * - Base * produces: * - application/json * responses: * 200: * description: Returns a JSON object of open api specification */ mainRouter.get('/api/v1/swagger.json', (_req, res) => { res.json(openapiSpecification) }) /** * @openapi * /api/glossary: * get: * description: To get glossary of NSE India * tags: * - Common * produces: * - application/json * responses: * 200: * description: Returns a JSON object of glossary for NSE India * 400: * description: Returns a JSON error object of API call */ mainRouter.get('/api/glossary', async (_req, res) => { try { res.json(await nseIndia.getDataByEndpoint(ApiList.GLOSSARY)) } catch (error) { res.status(400).json(error) } }) /** * @openapi * /api/marketStatus: * get: * description: To get market status * tags: * - Common * produces: * - application/json * responses: * 200: * description: Returns a JSON object of NSE market status * 400: * description: Returns a JSON error object of API call */ mainRouter.get('/api/marketStatus', async (_req, res) => { try { res.json(await nseIndia.getDataByEndpoint(ApiList.MARKET_STATUS)) } catch (error) { res.status(400).json(error) } }) /** * @openapi * /api/marketTurnover: * get: * description: To get market turn over * tags: * - Common * produces: * - application/json * responses: * 200: * description: Returns a JSON object of NSE market turn over * 400: * description: Returns a JSON error object of API call */ mainRouter.get('/api/marketTurnover', async (_req, res) => { try { res.json(await nseIndia.getDataByEndpoint(ApiList.MARKET_TURNOVER)) } catch (error) { res.status(400).json(error) } }) /** * @openapi * /api/equityMaster: * get: * description: To get equity master * tags: * - Common * produces: * - application/json * responses: * 200: * description: Returns a JSON object of NSE equity master * 400: * description: Returns a JSON error object of API call */ mainRouter.get('/api/equityMaster', async (_req, res) => { try { res.json(await nseIndia.getDataByEndpoint(ApiList.EQUITY_MASTER)) } catch (error) { res.status(400).json(error) } }) /** * @openapi * /api/holidays: * get: * description: To get holidays of NSE India * tags: * - Common * parameters: * - name: type * in: query * description: Holiday list for * required: true * schema: * type: string * enum: [trading,clearing] * produces: * - application/json * responses: * 200: * description: Returns a JSON object of NSE India's holidays * 400: * description: Returns a JSON error object of API call */ mainRouter.get('/api/holidays', async (req, res) => { try { const { type } = req.query if (type === 'clearing') { res.json(await nseIndia.getDataByEndpoint(ApiList.HOLIDAY_CLEARING)) } else { res.json(await nseIndia.getDataByEndpoint(ApiList.HOLIDAY_TRADING)) } } catch (error) { res.status(400).json(error) } }) /** * @openapi * /api/circulars: * get: * description: To get NSE India's circulars * tags: * - Common * parameters: * - name: isLatest * in: query * description: Boolean value get latest circulars * required: false * schema: * type: boolean * default: false * produces: * - application/json * responses: * 200: * description: Returns a JSON object of NSE India's circulars * 400: * description: Returns a JSON error object of API call */ mainRouter.get('/api/circulars', async (req, res) => { try { const { isLatest } = req.query if (isLatest === 'true') { res.json(await nseIndia.getDataByEndpoint(ApiList.LATEST_CIRCULARS)) } else { res.json(await nseIndia.getDataByEndpoint(ApiList.CIRCULARS)) } } catch (error) { res.status(400).json(error) } }) /** * @openapi * /api/mergedDailyReports: * get: * description: To get merged daily reports * tags: * - Common * parameters: * - name: key * in: query * description: Key for merged daily reports * required: true * schema: * type: string * enum: [capital,derivatives,debt] * produces: * - application/json * responses: * 200: * description: Returns a JSON object of NSE India's merged daily reports * 400: * description: Returns a JSON error object of API call */ mainRouter.get('/api/mergedDailyReports', async (req, res) => { try { const { key } = req.query if (key === 'debt') { res.json(await nseIndia.getDataByEndpoint(ApiList.MERGED_DAILY_REPORTS_DEBT)) } else if (key === 'derivatives') { res.json(await nseIndia.getDataByEndpoint(ApiList.MERGED_DAILY_REPORTS_DERIVATIVES)) } else { res.json(await nseIndia.getDataByEndpoint(ApiList.MERGED_DAILY_REPORTS_CAPITAL)) } } catch (error) { res.status(400).json(error) } }) /** * @openapi * /api/allIndices: * get: * description: To get all NSE indices * tags: * - Common * produces: * - application/json * responses: * 200: * description: Returns a JSON object of all NSE indices * 400: * description: Returns a JSON error object of API call */ mainRouter.get('/api/allIndices', async (_req, res) => { try { const allIndices = await nseIndia.getDataByEndpoint(ApiList.ALL_INDICES) res.json(allIndices) } catch (error) { res.status(400).json(error) } }) /** * @openapi * /api/indexNames: * get: * description: To get all NSE index names * tags: * - Common * produces: * - application/json * responses: * 200: * description: Returns a JSON object of all NSE index names * 400: * description: Returns a JSON error object of API call */ mainRouter.get('/api/indexNames', async (_req, res) => { try { const indexNames = await nseIndia.getDataByEndpoint(ApiList.INDEX_NAMES) res.json(indexNames) } catch (error) { res.status(400).json(error) } }) /** * @openapi * /api/allSymbols: * get: * description: To get all NSE equity symbols * tags: * - Common * produces: * - application/json * responses: * 200: * description: Returns an array of NSE equity symbols * 400: * description: Returns a JSON error object of API call */ mainRouter.get('/api/allSymbols', async (_req, res) => { try { const symbols = await nseIndia.getAllStockSymbols() res.json(symbols) } catch (error) { res.status(400).json(error) } }) /** * @openapi * /api/equity/{symbol}: * get: * description: To get details of the NSE symbol * tags: * - Equity * produces: * - application/json * parameters: * - name: symbol * in: path * description: NSE Symbol of the Equity * required: true * schema: * type: string * format: any * responses: * 200: * description: Returns a details of the NSE symbol * 400: * description: Returns a JSON error object of API call */ mainRouter.get('/api/equity/:symbol', async (req, res) => { try { const { symbol } = req.params; const data = await nseIndia.getEquityDetails(symbol); res.json(data); } catch (error) { res.status(400).json(error); } }) /** * @openapi * /api/equity/series/{symbol}: * get: * description: To get equity series of the NSE symbol * tags: * - Equity * produces: * - application/json * parameters: * - name: symbol * in: path * description: NSE Symbol of the Equity * required: true * schema: * type: string * format: any * responses: * 200: * description: Returns a equity series of the NSE symbol * 400: * description: Returns a JSON error object of API call */ mainRouter.get('/api/equity/series/:symbol', async (req, res) => { try { res.json(await nseIndia.getEquitySeries(req.params.symbol)) } catch (error) { res.status(400).json(error) } }) /** * @openapi * /api/equity/tradeInfo/{symbol}: * get: * description: To get trade info of the NSE symbol * tags: * - Equity * produces: * - application/json * parameters: * - name: symbol * in: path * description: NSE Symbol of the Equity * required: true * schema: * type: string * format: any * responses: * 200: * description: Returns a trade info of the NSE symbol * 400: * description: Returns a JSON error object of API call */ mainRouter.get('/api/equity/tradeInfo/:symbol', async (req, res) => { try { res.json(await nseIndia.getEquityTradeInfo(req.params.symbol)) } catch (error) { res.status(400).json(error) } }) /** * @openapi * /api/equity/corporateInfo/{symbol}: * get: * description: To get corporate info of the NSE symbol * tags: * - Equity * produces: * - application/json * parameters: * - name: symbol * in: path * description: NSE Symbol of the Equity * required: true * schema: * type: string * format: any * responses: * 200: * description: Returns a corporate info of the NSE symbol * 400: * description: Returns a JSON error object of API call */ mainRouter.get('/api/equity/corporateInfo/:symbol', async (req, res) => { try { res.json(await nseIndia.getEquityCorporateInfo(req.params.symbol)) } catch (error) { res.status(400).json(error) } }) /** * @openapi * /api/equity/options/{symbol}: * get: * description: To get options chain of the NSE symbol * tags: * - Equity * produces: * - application/json * parameters: * - name: symbol * in: path * description: NSE Symbol of the Equity * required: true * schema: * type: string * format: any * responses: * 200: * description: Returns a options chain of the NSE symbol * 400: * description: Returns a JSON error object of API call */ mainRouter.get('/api/equity/options/:symbol', async (req, res) => { try { res.json(await nseIndia.getEquityOptionChain(req.params.symbol)) } catch (error) { res.status(400).json(error) } }) /** * @openapi * /api/equity/intraday/{symbol}: * get: * description: To get intraday trade info of the NSE symbol * tags: * - Equity * produces: * - application/json * parameters: * - name: symbol * in: path * description: NSE Symbol of the Equity * required: true * schema: * type: string * format: any * responses: * 200: * description: Returns a intraday trade info of the NSE symbol * 400: * description: Returns a JSON error object of API call */ mainRouter.get('/api/equity/intraday/:symbol', async (req, res) => { try { const { symbol } = req.params; const data = await nseIndia.getEquityIntradayData(symbol); res.json(data); } catch (error) { res.status(400).json(error); } }) /** * @openapi * /api/equity/historical/{symbol}: * get: * description: To get details of the NSE symbol * tags: * - Equity * produces: * - application/json * parameters: * - name: symbol * in: path * description: NSE Symbol of the Equity * required: true * schema: * type: string * format: any * - name: dateStart * in: query * description: "Start date to pull historical data (format: YYYY-MM-DD)" * required: false * schema: * type: string * format: date * - name: dateEnd * in: query * description: "End date to pull historical data (format: YYYY-MM-DD)" * required: false * schema: * type: string * format: date * responses: * 200: * description: Returns a historical data of the NSE symbol * 400: * description: Returns a JSON error object of API call */ mainRouter.get('/api/equity/historical/:symbol', async (req, res) => { try { const dateStart = req.query.dateStart as string const dateEnd = req.query.dateEnd as string if (dateStart) { const start = new Date(dateStart) const end = dateEnd ? new Date(dateEnd) : new Date() if (start.getTime() > 0 && end.getTime() > 0) { const range = { start, end } res.json(await nseIndia.getEquityHistoricalData(req.params.symbol, range)) } else { res.status(400).json({ error: 'Invalid date format. Please use the format (YYYY-MM-DD)' }) } } else { res.json(await nseIndia.getEquityHistoricalData(req.params.symbol)) } } catch (error) { res.status(400).json(error) } }) /** * @openapi * /api/equity/technicalIndicators/{symbol}: * get: * description: To get technical indicators for the NSE symbol * tags: * - Equity * produces: * - application/json * parameters: * - name: symbol * in: path * description: NSE Symbol of the Equity * required: true * schema: * type: string * format: any * - name: period * in: query * description: "Number of days for historical data (default: 200)" * required: false * schema: * type: integer * default: 200 * - name: smaPeriods * in: query * description: "Comma-separated SMA periods (e.g., 5,10,20,50)" * required: false * schema: * type: string * default: "5,10,20,50,100,200" * - name: emaPeriods * in: query * description: "Comma-separated EMA periods (e.g., 5,10,20,50)" * required: false * schema: * type: string * default: "5,10,20,50,100,200" * - name: rsiPeriod * in: query * description: "RSI period (default: 14)" * required: false * schema: * type: integer * default: 14 * - name: bbPeriod * in: query * description: "Bollinger Bands period (default: 20)" * required: false * schema: * type: integer * default: 20 * - name: bbStdDev * in: query * description: "Bollinger Bands standard deviation (default: 2)" * required: false * schema: * type: number * default: 2 * - name: showOnlyLatest * in: query * description: "Show only latest values (true) or all values (false) - useful for charts (default: true)" * required: false * schema: * type: boolean * default: true * responses: * 200: * description: Returns technical indicators for the NSE symbol * content: * application/json: * schema: * type: object * properties: * sma: * type: object * description: "Simple Moving Averages with dynamic keys (sma5, sma10, etc.)" * additionalProperties: * type: array * items: * type: number * ema: * type: object * description: "Exponential Moving Averages with dynamic keys (ema5, ema10, etc.)" * additionalProperties: * type: array * items: * type: number * rsi: * type: array * items: * type: number * description: "Relative Strength Index" * macd: * type: object * properties: * macd: * type: array * items: * type: number * signal: * type: array * items: * type: number * histogram: * type: array * items: * type: number * bollingerBands: * type: object * properties: * upper: * type: array * items: * type: number * middle: * type: array * items: * type: number * lower: * type: array * items: * type: number * stochastic: * type: object * properties: * k: * type: array * items: * type: number * d: * type: array * items: * type: number * williamsR: * type: array * items: * type: number * description: "Williams %R" * atr: * type: array * items: * type: number * description: "Average True Range" * adx: * type: array * items: * type: number * description: "Average Directional Index" * obv: * type: array * items: * type: number * description: "On-Balance Volume" * cci: * type: array * items: * type: number * description: "Commodity Channel Index" * mfi: * type: array * items: * type: number * description: "Money Flow Index" * roc: * type: array * items: * type: number * description: "Rate of Change" * momentum: * type: array * items: * type: number * description: "Momentum" * ad: * type: array * items: * type: number * description: "Accumulation/Distribution" * vwap: * type: array * items: * type: number * description: "Volume Weighted Average Price" * 400: * description: Returns a JSON error object of API call */ mainRouter.get('/api/equity/technicalIndicators/:symbol', async (req, res) => { try { const { symbol } = req.params const { period, smaPeriods, emaPeriods, rsiPeriod, bbPeriod, bbStdDev, showOnlyLatest } = req.query // Parse query parameters const options: any = {} if (period) { options.period = parseInt(period as string) } if (smaPeriods) { options.smaPeriods = (smaPeriods as string).split(',').map(p => parseInt(p.trim())) } if (emaPeriods) { options.emaPeriods = (emaPeriods as string).split(',').map(p => parseInt(p.trim())) } if (rsiPeriod) { options.rsiPeriod = parseInt(rsiPeriod as string) } if (bbPeriod) { options.bbPeriod = parseInt(bbPeriod as string) } if (bbStdDev) { options.bbStdDev = parseFloat(bbStdDev as string) } const indicators = await nseIndia.getTechnicalIndicators(symbol, (options.period as number) || 200, options) // Parse showOnlyLatest flag (default: true) const showLatest = showOnlyLatest === undefined || showOnlyLatest === 'true' // Helper function to round numbers to 2 decimal places const roundTo2Decimals = (value: number | null): number | null => { return value !== null ? Math.round(value * 100) / 100 : null } // Helper function to round array of numbers to 2 decimal places const roundArrayTo2Decimals = (arr: number[]): number[] => { return arr.map(value => roundTo2Decimals(value) as number) } if (showLatest) { // Return only the latest values const latestIndicators: any = {} // Process SMA indicators latestIndicators.sma = {} Object.keys(indicators.sma).forEach(key => { const values = indicators.sma[key] latestIndicators.sma[key] = values.length > 0 ? roundTo2Decimals(values[values.length - 1]) : null }) // Process EMA indicators latestIndicators.ema = {} Object.keys(indicators.ema).forEach(key => { const values = indicators.ema[key] latestIndicators.ema[key] = values.length > 0 ? roundTo2Decimals(values[values.length - 1]) : null }) // Process other indicators latestIndicators.rsi = roundTo2Decimals( indicators.rsi.length > 0 ? indicators.rsi[indicators.rsi.length - 1] : null ) latestIndicators.macd = { macd: roundTo2Decimals( indicators.macd.macd.length > 0 ? indicators.macd.macd[indicators.macd.macd.length - 1] : null ), signal: roundTo2Decimals( indicators.macd.signal.length > 0 ? indicators.macd.signal[indicators.macd.signal.length - 1] : null ), histogram: roundTo2Decimals( indicators.macd.histogram.length > 0 ? indicators.macd.histogram[indicators.macd.histogram.length - 1] : null ) } latestIndicators.bollingerBands = { upper: roundTo2Decimals( indicators.bollingerBands.upper.length > 0 ? indicators.bollingerBands.upper[indicators.bollingerBands.upper.length - 1] : null ), middle: roundTo2Decimals( indicators.bollingerBands.middle.length > 0 ? indicators.bollingerBands.middle[indicators.bollingerBands.middle.length - 1] : null ), lower: roundTo2Decimals( indicators.bollingerBands.lower.length > 0 ? indicators.bollingerBands.lower[indicators.bollingerBands.lower.length - 1] : null ) } latestIndicators.stochastic = { k: roundTo2Decimals( indicators.stochastic.k.length > 0 ? indicators.stochastic.k[indicators.stochastic.k.length - 1] : null ), d: roundTo2Decimals( indicators.stochastic.d.length > 0 ? indicators.stochastic.d[indicators.stochastic.d.length - 1] : null ) } latestIndicators.williamsR = roundTo2Decimals( indicators.williamsR.length > 0 ? indicators.williamsR[indicators.williamsR.length - 1] : null ) latestIndicators.atr = roundTo2Decimals( indicators.atr.length > 0 ? indicators.atr[indicators.atr.length - 1] : null ) latestIndicators.adx = roundTo2Decimals( indicators.adx.length > 0 ? indicators.adx[indicators.adx.length - 1] : null ) latestIndicators.obv = roundTo2Decimals( indicators.obv.length > 0 ? indicators.obv[indicators.obv.length - 1] : null ) latestIndicators.cci = roundTo2Decimals( indicators.cci.length > 0 ? indicators.cci[indicators.cci.length - 1] : null ) latestIndicators.mfi = roundTo2Decimals( indicators.mfi.length > 0 ? indicators.mfi[indicators.mfi.length - 1] : null ) latestIndicators.roc = roundTo2Decimals( indicators.roc.length > 0 ? indicators.roc[indicators.roc.length - 1] : null ) latestIndicators.momentum = roundTo2Decimals( indicators.momentum.length > 0 ? indicators.momentum[indicators.momentum.length - 1] : null ) latestIndicators.ad = roundTo2Decimals( indicators.ad.length > 0 ? indicators.ad[indicators.ad.length - 1] : null ) latestIndicators.vwap = roundTo2Decimals( indicators.vwap.length > 0 ? indicators.vwap[indicators.vwap.length - 1] : null ) res.json(latestIndicators) } else { // Return all values with 2 decimal precision const roundedIndicators: any = {} // Process SMA indicators roundedIndicators.sma = {} Object.keys(indicators.sma).forEach(key => { roundedIndicators.sma[key] = roundArrayTo2Decimals(indicators.sma[key]) }) // Process EMA indicators roundedIndicators.ema = {} Object.keys(indicators.ema).forEach(key => { roundedIndicators.ema[key] = roundArrayTo2Decimals(indicators.ema[key]) }) // Process other indicators roundedIndicators.rsi = roundArrayTo2Decimals(indicators.rsi) roundedIndicators.macd = { macd: roundArrayTo2Decimals(indicators.macd.macd), signal: roundArrayTo2Decimals(indicators.macd.signal), histogram: roundArrayTo2Decimals(indicators.macd.histogram) } roundedIndicators.bollingerBands = { upper: roundArrayTo2Decimals(indicators.bollingerBands.upper), middle: roundArrayTo2Decimals(indicators.bollingerBands.middle), lower: roundArrayTo2Decimals(indicators.bollingerBands.lower) } roundedIndicators.stochastic = { k: roundArrayTo2Decimals(indicators.stochastic.k), d: roundArrayTo2Decimals(indicators.stochastic.d) } roundedIndicators.williamsR = roundArrayTo2Decimals(indicators.williamsR) roundedIndicators.atr = roundArrayTo2Decimals(indicators.atr) roundedIndicators.adx = roundArrayTo2Decimals(indicators.adx) roundedIndicators.obv = roundArrayTo2Decimals(indicators.obv) roundedIndicators.cci = roundArrayTo2Decimals(indicators.cci) roundedIndicators.mfi = roundArrayTo2Decimals(indicators.mfi) roundedIndicators.roc = roundArrayTo2Decimals(indicators.roc) roundedIndicators.momentum = roundArrayTo2Decimals(indicators.momentum) roundedIndicators.ad = roundArrayTo2Decimals(indicators.ad) roundedIndicators.vwap = roundArrayTo2Decimals(indicators.vwap) res.json(roundedIndicators) } } catch (error) { res.status(400).json(error) } }) /** * @openapi * /api/index/{indexSymbol}: * get: * description: To get detailsof the NSE index * tags: * - Index * produces: * - application/json * parameters: * - name: indexSymbol * in: path * description: NSE index symbol * required: true * schema: * type: string * format: any * responses: * 200: * description: Returns a details of the NSE index symbol * 400: * description: Returns a JSON error object of API call */ mainRouter.get('/api/index/:indexSymbol', async (req, res) => { try { res.json(await nseIndia.getEquityStockIndices(req.params.indexSymbol)) } catch (error) { res.status(400).json(error) } }) /** * @openapi * /api/index/options/{indexSymbol}: * get: * description: To get index Option chain data * tags: * - Index * produces: * - application/json * parameters: * - name: indexSymbol * in: path * description: NSE index symbol * required: true * schema: * type: string * format: any * responses: * 200: * description: Returns Data for Index OPTION CHAIN * 400: * description: Returns a JSON error object of API call */ mainRouter.get('/api/index/options/:indexSymbol', async (req, res) => { try { res.json(await nseIndia.getIndexOptionChain(req.params.indexSymbol)) } catch (error) { res.status(400).json(error) } }) /** * @swagger * /api/index/options/contract-info/{indexSymbol}: * get: * summary: Get option chain contract information for an index * tags: [Index] * parameters: * - in: path * name: indexSymbol * required: true * schema: * type: string * description: Index symbol (e.g., NIFTY, BANKNIFTY) * responses: * 200: * description: Returns option chain contract information (expiry dates and strike prices) * 400: * description: Returns a JSON error object of API call */ mainRouter.get('/api/index/options/contract-info/:indexSymbol', async (req, res) => { try { res.json(await nseIndia.getIndexOptionChainContractInfo(req.params.indexSymbol)) } catch (error) { res.status(400).json(error) } }) /** * @openapi * /api/commodity/options/{commoditySymbol}: * get: * description: To get commodity Option chain data * tags: * - Commodity * produces: * - application/json * parameters: * - name: commoditySymbol * in: path * description: NSE commodity symbol * required: true * schema: * type: string * format: any * responses: * 200: * description: Returns a option chain data of the NSE commodity symbol * 400: * description: Returns a JSON error object of API call */ mainRouter.get('/api/commodity/options/:commoditySymbol', async (req, res) => { try { res.json(await nseIndia.getCommodityOptionChain(req.params.commoditySymbol)) } catch (error) { res.status(400).json(error) } }) /** * @openapi * /api/index/intraday/{indexSymbol}: * get: * description: To get intraday trade info of the NSE index symbol * tags: * - Index * produces: * - application/json * parameters: * - name: indexSymbol * in: path * description: NSE index symbol * required: true * schema: * type: string * format: any * responses: * 200: * description: Returns a intraday trade info of the NSE index symbol * 400: * description: Returns a JSON error object of API call */ mainRouter.get('/api/index/intraday/:indexSymbol', async (req, res) => { try { res.json(await nseIndia.getIndexIntradayData(req.params.indexSymbol)) } catch (error) { res.status(400).json(error) } }) /** * @openapi * /api/gainersAndLosers/{indexSymbol}: * get: * description: To get gainers and losers of the specific index * tags: * - Helpers * parameters: * - name: indexSymbol * in: path * description: NSE index symbol * required: true * schema: * type: string * format: any * produces: * - application/json * responses: * 200: * description: Returns a JSON object of the specified index's gainers and losers * 400: * description: Returns a JSON error object of API call */ mainRouter.get('/api/gainersAndLosers/:indexSymbol', async (req, res) => { try { res.json(await getGainersAndLosersByIndex(req.params.indexSymbol)) } catch (error) { res.status(400).json(error) } }) /** * @openapi * /api/mostActive/{indexSymbol}: * get: * description: To get most active equities of the specific index * tags: * - Helpers * parameters: * - name: indexSymbol * in: path * description: NSE index symbol * required: true * schema: * type: string * format: any * produces: * - application/json * responses: * 200: * description: Returns a JSON object of most active equities of the specified index * 400: * description: Returns a JSON error object of API call */ mainRouter.get('/api/mostActive/:indexSymbol', async (req, res) => { try { res.json(await getMostActiveEquities(req.params.indexSymbol)) } catch (error) { res.status(400).json(error) } }) /** * @openapi * /api/charts/equity-historical-data: * get: * description: Get historical chart data from charting.nseindia.com for equity symbols * tags: * - Charting * produces: * - application/json * parameters: * - name: symbol * in: query * description: Equity symbol with series code (e.g., 'ONGC') * required: true * schema: * type: string * example: ONGC * - name: start * in: query * description: > * Start date/time. Supports YYYY-MM-DD, YYYY-MM-DD HH:MM:SS, unix timestamp * (seconds or milliseconds) * required: false * schema: * type: string * example: "2026-04-10 09:15:00" * - name: end * in: query * description: > * End date/time. Supports YYYY-MM-DD, YYYY-MM-DD HH:MM:SS, unix timestamp * (seconds or milliseconds) * required: false * schema: * type: string * example: "2026-04-12 15:30:00" * - name: token * in: query * description: Optional token value for charting API (auto-fetched when omitted) * required: false * schema: * type: string * example: "2475" * - name: symbolType * in: query * description: Type of symbol (e.g., 'Equity', 'Index') * required: false * schema: * type: string * default: Equity * example: Equity * - name: chartType * in: query * description: Chart type ('I' for intraday, 'D' for daily pattern, etc.) * required: false * schema: * type: string * default: I * example: I * - name: timeInterval * in: query * description: Time interval in minutes (e.g., '5', '15', '60') * required: false * schema: * type: string * default: "5" * example: "5" * responses: * 200: * description: Returns historical chart data with OHLC values and timestamps * content: * application/json: * schema: * type: object * properties: * status: * type: boolean * description: true if request was successful * example: true * data: * type: array * description: Array of candle data points * items: * type: object * properties: * volume: * type: number * example: 46151 * high: * type: number * example: 286.7 * low: * type: number * example: 286.3 * time: * type: number * description: Unix timestamp in milliseconds * example: 1775834999000 * close: * type: number * example: 286.7 * open: * type: number * example: 286.65 * 400: * description: Returns error object if API call fails or parameters are invalid */ mainRouter.get('/api/charts/equity-historical-data', async (req, res) => { try { const { symbol, start, end, token, symbolType = 'Equity', chartType = 'I', timeInterval = '5' } = req.query // Validate required parameters if (!symbol) { return res.status(400).json({ error: 'Missing required parameter: symbol' }) } // Call the charting method const parseChartDateParam = (value: unknown): Date => { const input = String(value).trim() const numeric = Number(input) // Accept unix timestamp in seconds (10 digits) or milliseconds (13 digits). if (!Number.isNaN(numeric) && input !== '') { const unixMs = input.length <= 10 ? numeric * 1000 : numeric return new Date(unixMs) } return new Date(input) } let range if (start || end) { const endDate = end ? parseChartDateParam(end) : new Date() const startDate = start ? parseChartDateParam(start) : new Date(endDate.getTime() - 24 * 60 * 60 * 1000) if (!(startDate.getTime() > 0 && endDate.getTime() > 0)) { return res.status(400).json({ error: 'Invalid date format. Use YYYY-MM-DD, YYYY-MM-DD HH:MM:SS, or unix timestamp' }) } range = { start: startDate, end: endDate } } const chartData = await nseIndia.getEquityChartHistoricalData( String(symbol), range, token ? String(token) : undefined, String(symbolType), String(chartType), String(timeInterval) ) res.json(chartData) } catch (error) { res.status(400).json(error) } }) /** * @openapi * /api/charts/symbol-info: * get: * description: > * Look up NSE charting symbol information (including scripCode / token) for a * given equity symbol. The returned `scripCode` is the value that must be passed * as `token` to the `/api/charts/equity-historical-data` endpoint. * tags: * - Charting * produces: * - application/json * parameters: * - name: symbol * in: query * description: Equity symbol with or without series code (e.g., 'ONGC' or 'ONGC') * required: true * schema: * type: string * example: ONGC * - name: segment * in: query * description: Optional market segment filter (leave empty to search all segments) * required: false * schema: * type: string * example: '' * responses: * 200: * description: Returns charting symbol information including scripCode (token) * content: * application/json: * schema: * type: object * properties: * symbol: * type: string * example: ONGC * scripCode: * type: string * description: The token value required by the historical chart API * example: "2475" * companyName: * type: string * isin: * type: string * segment: * type: string * series: * type: string * status: * type: string * 400: * description: Returns error if symbol is missing or lookup fails */ mainRouter.get('/api/charts/symbol-info', async (req, res) => { try { const { symbol, segment = '' } = req.query if (!symbol) { return res.status(400).json({ error: 'Missing required parameter: symbol' }) } const symbolInfo = await nseIndia.getEquitySymbolInfo(String(symbol), String(segment)) res.json(symbolInfo) } catch (error) { res.status(400).json(error) } }) // ============================================================================ // MCP CLIENT - CORE ENDPOINTS // ============================================================================ /** * @openapi * /api/mcp/query: * post: * description: Query NSE India data using natural language. Supports OpenAI function calling, * memory, context summarization, and session management. * tags: * - MCP Client * requestBody: * required: true * content: * application/json: * schema: * type: object * required: * - query * properties: * query: * type: string * description: Natural language query about NSE India stock market data * example: "What is the current price of TCS stock? Also compare it with RELIANCE." * sessionId: * type: string * description: Optional session identifier for memory features * example: "user123_session456" * userId: * type: string * description: Optional user identifier for personalization * example: "user123" * model: * type: string * description: OpenAI model to use * default: gpt-4o-mini * temperature: * type: number * description: Temperature for response generation * default: 0.7 * max_tokens: * type: number * description: Maximum tokens in response * default: 2000 * includeContext: * type: boolean * description: Whether to include conversation context (requires sessionId) * default: true * updatePreferences: * type: boolean * description: Whether to update user preferences based on query (requires sessionId) * default: true * useMemory: * type: boolean * description: Whether to use memory features (requires sessionId) * default: true * maxIterations: * type: number * description: Maximum number of iterations for complex queries * default: 5 * enableDebugLogging: * type: boolean * description: Enable debug logging for AI messages and tool calls * default: false * responses: * 200: * description: Returns AI-generated response with NSE data * content: * application/json: * schema: * type: object * properties: * response: * type: string * description: AI-generated response * tools_used: * type: array * items: * type: string * description: List of unique MCP tools used across all iterations * data_sources: * type: array * items: * type: string * description: Data sources used * timestamp: * type: string * format: date-time * description: Response timestamp * sessionId: * type: string * description: Session identifier (if memory was used) * context_used: * type: boolean * description: Whether context was used * user_preferences_updated: * type: boolean * description: Whether user preferences were updated * conversation_length: * type: number * description: Current conversation length * context_summarized: * type: boolean * description: Whether context was summarized * context_summary: * type: object * description: Context summary (if summarized) * token_count: * type: object * description: Token count information * iterations_used: * type: number * description: Number of iterations used to process the query * iteration_details: * type: array * items: * type: object * properties: * iteration: * type: number * tools_called: * type: array * items: * type: string * purpose: * type: string * tool_parameters: * type: array * items: * type: object * properties: * tool_name: * type: string * parameters: * type: object * description: Detailed breakdown of each iteration including tool parameters * 400: * description: Returns error if query processing fails * 500: * description: Returns error if OpenAI API fails */ mainRouter.post('/api/mcp/query', async (req, res) => { try { const { query, sessionId: providedSessionId, userId, model, temperature, max_tokens, includeContext, updatePreferences, useMemory, maxIterations, enableDebugLogging } = req.body as MCPClientRequest if (!query || typeof query !== 'string') { return res.status(400).json({ error: 'Query is required and must be a string' }) } // Generate sessionId if not provided to enable memory features const sessionId = providedSessionId || `auto_session_${Date.now()}_${Math.random().toString(36).substr(2, 9)}` if (!process.env.OPENAI_API_KEY) { return res.status(500).json({ error: 'OpenAI API key not configured. Please set OPENAI_API_KEY environment variable.' }) } // Enable debug logging if requested, or check environment variable const shouldEnableDebug = enableDebugLogging || process.env.MCP_DEBUG_LOGGING === 'true' // Store original debug state to restore later const originalDebugState = mcpClient.isDebugLoggingEnabled() // Temporarily enable debug logging if requested if (shouldEnableDebug) { mcpClient.setDebugLogging(true) } try { const result = await mcpClient.processQuery({ query, sessionId, userId, model, temperature, max_tokens, includeContext, updatePreferences, useMemory, maxIterations }) res.json(result) } finally { // Restore original debug state mcpClient.setDebugLogging(originalDebugState) } } catch (error) { console.error('MCP Query Error:', error) res.status(500).json({ error: error instanceof Error ? error.message : 'Internal server error' }) } }) /** * @openapi * /api/mcp/tools: * get: * description: Get list of available MCP tools for NSE India data * tags: * - MCP Client * responses: * 200: * description: Returns list of available MCP tools * content: * application/json: * schema: * type: object * properties: * tools: * type: array * items: * type: object * properties: * name: * type: string * description: Tool name * description: * type: string * description: Tool description * inputSchema: * type: object * description: Tool input schema * 500: * description: Returns error if tools cannot be retrieved */ mainRouter.get('/api/mcp/tools', async (_req, res) => { try { const tools = mcpClient.getAvailableTools() res.json({ tools }) } catch (error) { console.error('MCP Tools Error:', error) res.status(500).json({ error: error instanceof Error ? error.message : 'Internal server error' }) } }) /** * @openapi * /api/mcp/test: * get: * description: Test MCP client connection and OpenAI integration * tags: * - MCP Client * responses: * 200: * description: Returns test result * content: * application/json: * schema: * type: object * properties: * status: * type: string * description: Test status * message: * type: string * description: Test message * timestamp: * type: string * format: date-time * description: Test timestamp * 500: * description: Returns error if test fails */ mainRouter.get('/api/mcp/test', async (_req, res) => { try { if (!process.env.OPENAI_API_KEY) { return res.status(500).json({ status: 'error', message: 'OpenAI API key not configured', timestamp: new Date().toISOString() }) } const isConnected = await mcpClient.testConnection() if (isConnected) { res.json({ status: 'success', message: 'MCP client is working correctly', timestamp: new Date().toISOString() }) } else { res.status(500).json({ status: 'error', message: 'MCP client test failed', timestamp: new Date().toISOString() }) } } catch (error) { console.error('MCP Test Error:', error) res.status(500).json({ status: 'error', message: error instanceof Error ? error.message : 'Test failed', timestamp: new Date().toISOString() }) } }) // ============================================================================ // MCP CLIENT - UTILITY ENDPOINTS // ============================================================================ /** * @openapi * /api/mcp/functions: * get: * description: Get list of available MCP tools in OpenAI function format * tags: * - MCP Client * responses: * 200: * description: Returns list of available MCP tools in OpenAI function format * content: * application/json: * schema: * type: object * properties: * functions: * type: array * items: * type: object * properties: * name: * type: string * description: Function name * description: * type: string * description: Function description * parameters: * type: object * description: Function parameters schema * 500: * description: Returns error if functions cannot be retrieved */ mainRouter.get('/api/mcp/functions', async (_req, res) => { try { const functions = mcpClient.getOpenAIFunctions() res.json({ functions }) } catch (error) { console.error('MCP Functions Error:', error) res.status(500).json({ error: error instanceof Error ? error.message : 'Internal server error' }) } }) // ============================================================================ // MCP CLIENT - SESSION MANAGEMENT ENDPOINTS // ============================================================================ /** * @openapi * /api/mcp/session/{sessionId}: * get: * description: Get session information and statistics * tags: * - MCP Client * parameters: * - name: sessionId * in: path * description: Session identifier * required: true * schema: * type: string * responses: * 200: * description: Returns session information * content: * application/json: * schema: * type: object * properties: * sessionId: * type: string * userId: * type: string * startTime: * type: string * format: date-time * lastActivity: * type: string * format: date-time * messageCount: * type: number * recentQueriesCount: * type: number * frequentlyAccessedStocks: * type: number * frequentlyUsedTools: * type: number * 404: * description: Session not found */ mainRouter.get('/api/mcp/session/:sessionId', async (req, res) => { try { const { sessionId } = req.params const sessionInfo = mcpClient.getSessionInfo(sessionId) if (!sessionInfo) { return res.status(404).json({ error: 'Session not found' }) } res.json(sessionInfo) } catch (error) { console.error('Get Session Info Error:', error) res.status(500).json({ error: error instanceof Error ? error.message : 'Internal server error' }) } }) /** * @openapi * /api/mcp/session/{sessionId}/history: * get: * description: Get conversation history for a session * tags: * - MCP Client * parameters: * - name: sessionId * in: path * description: Session identifier * required: true * schema: * type: string * - name: maxMessages * in: query * description: Maximum number of messages to return * required: false * schema: * type: integer * default: 10 * responses: * 200: * description: Returns conversation history * content: * application/json: * schema: * type: object * properties: * messages: * type: array * items: * type: object * properties: * role: * type: string * enum: [user, assistant, system] * content: * type: string * timestamp: * type: string * format: date-time * tools_used: * type: array * items: * type: string * metadata: * type: object * 404: * description: Session not found */ mainRouter.get('/api/mcp/session/:sessionId/history', async (req, res) => { try { const { sessionId } = req.params const { maxMessages } = req.query const history = mcpClient.getConversationHistory( sessionId, maxMessages ? parseInt(maxMessages as string) : undefined ) if (history.length === 0) { return res.status(404).json({ error: 'Session not found or no history available' }) } res.json({ messages: history }) } catch (error) { console.error('Get Conversation History Error:', error) res.status(500).json({ error: error instanceof Error ? error.message : 'Internal server error' }) } }) /** * @openapi * /api/mcp/session/{sessionId}/preferences: * put: * description: Update user preferences for a session * tags: * - MCP Client * parameters: * - name: sessionId * in: path * description: Session identifier * required: true * schema: * type: string * requestBody: * required: true * content: * application/json: * schema: * type: object * properties: * preferredStocks: * type: array * items: * type: string * description: List of preferred stock symbols * preferredIndices: * type: array * items: * type: string * description: List of preferred indices * analysisStyle: * type: string * enum: [detailed, brief, technical] * description: Preferred analysis style * language: * type: string * description: Preferred language * timezone: * type: string * description: User timezone * notificationSettings: * type: object * properties: * priceAlerts: * type: boolean * marketUpdates: * type: boolean * responses: * 200: * description: Preferences updated successfully * 400: * description: Invalid preferences data * 404: * description: Session not found */ mainRouter.put('/api/mcp/session/:sessionId/preferences', async (req, res) => { try { const { sessionId } = req.params const preferences = req.body mcpClient.updateUserPreferences(sessionId, preferences) res.json({ message: 'Preferences updated successfully', sessionId }) } catch (error) { console.error('Update Preferences Error:', error) res.status(500).json({ error: error instanceof Error ? error.message : 'Internal server error' }) } }) /** * @openapi * /api/mcp/session/{sessionId}/clear: * delete: * description: Clear session data and conversation history * tags: * - MCP Client * parameters: * - name: sessionId * in: path * description: Session identifier * required: true * schema: * type: string * responses: * 200: * description: Session cleared successfully * 404: * description: Session not found */ mainRouter.delete('/api/mcp/session/:sessionId/clear', async (req, res) => { try { const { sessionId } = req.params mcpClient.clearSession(sessionId) res.json({ message: 'Session cleared successfully', sessionId }) } catch (error) { console.error('Clear Session Error:', error) res.status(500).json({ error: error instanceof Error ? error.message : 'Internal server error' }) } }) /** * @openapi * /api/mcp/session/{sessionId}/export: * get: * description: Export session data * tags: * - MCP Client * parameters: * - name: sessionId * in: path * description: Session identifier * required: true * schema: * type: string * responses: * 200: * description: Returns exported session data * 404: * description: Session not found */ mainRouter.get('/api/mcp/session/:sessionId/export', async (req, res) => { try { const { sessionId } = req.params const sessionData = mcpClient.exportSessionData(sessionId) if (!sessionData) { return res.status(404).json({ error: 'Session not found' }) } res.json(sessionData) } catch (error) { console.error('Export Session Data Error:', error) res.status(500).json({ error: error instanceof Error ? error.message : 'Internal server error' }) } }) /** * @openapi * /api/mcp/cleanup: * post: * description: Cleanup expired sessions * tags: * - MCP Client * responses: * 200: * description: Cleanup completed successfully */ mainRouter.post('/api/mcp/cleanup', async (_req, res) => { try { mcpClient.cleanupExpiredSessions() res.json({ message: 'Cleanup completed successfully', timestamp: new Date().toISOString() }) } catch (error) { console.error('Cleanup Error:', error) res.status(500).json({ error: error instanceof Error ? error.message : 'Internal server error' }) } }) // ============================================================================ // MCP CLIENT - CONTEXT MANAGEMENT ENDPOINTS // ============================================================================ /** * @openapi * /api/mcp/session/{sessionId}/context-stats: * get: * description: Get context statistics for a session * tags: * - MCP Client * parameters: * - name: sessionId * in: path * description: Session identifier * required: true * schema: * type: string * responses: * 200: * description: Returns context statistics * content: * application/json: * schema: * type: object * properties: * messageCount: * type: number * description: Number of messages in conversation * tokenCount: * type: object * description: Token count breakdown * needsSummarization: * type: boolean * description: Whether context needs summarization * contextWindowUsage: * type: number * description: Context window usage percentage * 404: * description: Session not found */ mainRouter.get('/api/mcp/session/:sessionId/context-stats', async (req, res) => { try { const { sessionId } = req.params const stats = await mcpClient.getContextStats(sessionId) res.json(stats) } catch (error) { console.error('Get Context Stats Error:', error) res.status(500).json({ error: error instanceof Error ? error.message : 'Internal server error' }) } }) /** * @openapi * /api/mcp/session/{sessionId}/summarize: * post: * description: Force context summarization for a session * tags: * - MCP Client * parameters: * - name: sessionId * in: path * description: Session identifier * required: true * schema: * type: string * responses: * 200: * description: Context summarization completed * content: * application/json: * schema: * type: object * properties: * summary: * type: object * description: Generated context summary * message: * type: string * description: Success message * 404: * description: Session not found */ mainRouter.post('/api/mcp/session/:sessionId/summarize', async (req, res) => { try { const { sessionId } = req.params const summary = await mcpClient.forceContextSummarization(sessionId) if (!summary) { return res.status(404).json({ error: 'Session not found' }) } res.json({ summary, message: 'Context summarization completed successfully' }) } catch (error) { console.error('Context Summarization Error:', error) res.status(500).json({ error: error instanceof Error ? error.message : 'Internal server error' }) } }) /** * @openapi * /api/mcp/session/{sessionId}/context-window: * get: * description: Get context window configuration * tags: * - MCP Client * parameters: * - name: sessionId * in: path * description: Session identifier * required: true * schema: * type: string * responses: * 200: * description: Returns context window configuration */ mainRouter.get('/api/mcp/session/:sessionId/context-window', async (req, res) => { try { const config = mcpClient.getContextWindowConfig() res.json(config) } catch (error) { console.error('Get Context Window Config Error:', error) res.status(500).json({ error: error instanceof Error ? error.message : 'Internal server error' }) } }) /** * @openapi * /api/mcp/session/{sessionId}/context-window: * put: * description: Update context window configuration * tags: * - MCP Client * parameters: * - name: sessionId * in: path * description: Session identifier * required: true * schema: * type: string * requestBody: * required: true * content: * application/json: * schema: * type: object * properties: * maxTokens: * type: number * description: Maximum tokens in context window * reservedTokens: * type: number * description: Reserved tokens for system prompt and response * summarizationThreshold: * type: number * description: Threshold for triggering summarization (0-1) * minMessagesToSummarize: * type: number * description: Minimum messages before summarization * summaryCompressionRatio: * type: number * description: Compression ratio for summaries (0-1) * responses: * 200: * description: Context window configuration updated */ mainRouter.put('/api/mcp/session/:sessionId/context-window', async (req, res) => { try { const config = req.body mcpClient.updateContextWindowConfig(config) res.json({ message: 'Context window configuration updated successfully', config: mcpClient.getContextWindowConfig() }) } catch (error) { console.error('Update Context Window Config Error:', error) res.status(500).json({ error: error instanceof Error ? error.message : 'Internal server error' }) } }) // ============================================================================ // SUMMARIZATION HISTORY ENDPOINTS // ============================================================================ /** * @openapi * /api/mcp/session/{sessionId}/summarization/last: * get: * description: Get the last summarization details for a session * tags: * - MCP Memory * parameters: * - in: path * name: sessionId * required: true * schema: * type: string * description: Session identifier * responses: * 200: * description: Returns last summarization details * 404: * description: No summarization found */ mainRouter.get('/api/mcp/session/:sessionId/summarization/last', async (req, res) => { try { const { sessionId } = req.params if (!mcpClient.isMemoryEnabled()) { return res.status(500).json({ error: 'Memory manager not enabled' }) } const lastSummarization = mcpClient.getLastSummarization(sessionId) if (!lastSummarization) { return res.status(404).json({ message: 'No summarization found for this session' }) } res.json(lastSummarization) } catch (error) { console.error('Get Last Summarization Error:', error) res.status(500).json({ error: error instanceof Error ? error.message : 'Internal server error' }) } }) /** * @openapi * /api/mcp/session/{sessionId}/summarization/history: * get: * description: Get summarization history for a session * tags: * - MCP Memory * parameters: * - in: path * name: sessionId * required: true * schema: * type: string * description: Session identifier * - in: query * name: limit * schema: * type: number * description: Limit number of records returned * responses: * 200: * description: Returns summarization history */ mainRouter.get('/api/mcp/session/:sessionId/summarization/history', async (req, res) => { try { const { sessionId } = req.params const limit = req.query.limit ? parseInt(req.query.limit as string) : undefined if (!mcpClient.isMemoryEnabled()) { return res.status(500).json({ error: 'Memory manager not enabled' }) } const history = mcpClient.getSummarizationHistory(sessionId, limit) res.json({ sessionId, count: history.length, history }) } catch (error) { console.error('Get Summarization History Error:', error) res.status(500).json({ error: error instanceof Error ? error.message : 'Internal server error' }) } }) /** * @openapi * /api/mcp/session/{sessionId}/summarization/summary: * get: * description: Get summarization summary (overview without full message history) * tags: * - MCP Memory * parameters: * - in: path * name: sessionId * required: true * schema: * type: string * description: Session identifier * responses: * 200: * description: Returns summarization summary */ mainRouter.get('/api/mcp/session/:sessionId/summarization/summary', async (req, res) => { try { const { sessionId } = req.params if (!mcpClient.isMemoryEnabled()) { return res.status(500).json({ error: 'Memory manager not enabled' }) } const summary = mcpClient.getSummarizationSummary(sessionId) if (!summary) { return res.status(404).json({ message: 'Session not found' }) } res.json(summary) } catch (error) { console.error('Get Summarization Summary Error:', error) res.status(500).json({ error: error instanceof Error ? error.message : 'Internal server error' }) } }) /** * @openapi * /api/mcp/session/{sessionId}/openai-messages: * get: * description: Get the exact messages that would be sent to OpenAI (including system message) * tags: * - MCP Memory * parameters: * - in: path * name: sessionId * required: true * schema: * type: string * description: Session identifier * responses: * 200: * description: Returns messages in OpenAI format */ mainRouter.get('/api/mcp/session/:sessionId/openai-messages', async (req, res) => { try { const { sessionId } = req.params if (!mcpClient.isMemoryEnabled()) { return res.status(500).json({ error: 'Memory manager not enabled' }) } const data = mcpClient.getOpenAIMessages(sessionId) if (!data) { return res.status(404).json({ error: 'Session not found' }) } // Format messages as they would be sent to OpenAI const openaiMessages = [ { role: 'system', content: data.systemPrompt, metadata: { type: 'system_prompt', includes_user_context: true } }, ...data.conversationHistory.map((msg: any) => ({ role: msg.role, content: msg.content, timestamp: msg.timestamp, metadata: { ...msg.metadata, is_summary: msg.metadata?.isSummary || false, tools_used: msg.tools_used || [] } })) ] // Calculate statistics const summaryMessages = openaiMessages.filter( m => m.metadata && 'is_summary' in m.metadata && m.metadata.is_summary ) const stats = { total_messages: openaiMessages.length, system_messages: 1, summary_messages: summaryMessages.length, user_messages: openaiMessages.filter(m => m.role === 'user').length, assistant_messages: openaiMessages.filter(m => m.role === 'assistant').length } res.json({ sessionId, messages: openaiMessages, statistics: stats, note: 'This is exactly what OpenAI would receive for the next query' }) } catch (error) { console.error('Get OpenAI Messages Error:', error) res.status(500).json({ error: error instanceof Error ? error.message : 'Internal server error' }) } }) export { mainRouter } ================================================ FILE: src/server.ts ================================================ /* eslint-disable no-console */ import express from 'express' import http from 'http'; import swaggerUi from 'swagger-ui-express' import { ApolloServer } from 'apollo-server-express'; import { ApolloServerPluginDrainHttpServer } from 'apollo-server-core'; import { print } from 'graphql' import { loadSchemaSync } from '@graphql-tools/load' import { loadFilesSync } from '@graphql-tools/load-files' import { mergeTypeDefs, mergeResolvers } from '@graphql-tools/merge' import { GraphQLFileLoader } from '@graphql-tools/graphql-file-loader' import { openapiSpecification } from './swaggerDocOptions' import path from 'path'; import { mainRouter } from './routes' import cors from 'cors'; const app = express() const port = process.env.PORT || 3000 const hostUrl = process.env.HOST_URL || `http://localhost:${port}` // CORS Configuration from environment variables // CORS_ORIGINS: Comma-separated list of allowed origins // CORS_METHODS: Comma-separated list of allowed HTTP methods // CORS_HEADERS: Comma-separated list of allowed headers // CORS_CREDENTIALS: Enable/disable credentials (default: true) // Enable CORS for all routes const corsOrigins = process.env.CORS_ORIGINS ? process.env.CORS_ORIGINS.split(',').map(origin => origin.trim()) : []; const corsMethods = process.env.CORS_METHODS ? process.env.CORS_METHODS.split(',').map(method => method.trim()) : ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS']; const corsHeaders = process.env.CORS_HEADERS ? process.env.CORS_HEADERS.split(',').map(header => header.trim()) : ['Content-Type', 'Authorization']; app.use(cors({ origin: [ ...corsOrigins, /^http:\/\/localhost:\d+$/, // Allow any localhost port /^http:\/\/127\.0\.0\.1:\d+$/ // Allow any 127.0.0.1 port ], methods: corsMethods, allowedHeaders: corsHeaders, credentials: process.env.CORS_CREDENTIALS !== 'false' })); // Add JSON body parsing middleware app.use(express.json()); app.use(express.urlencoded({ extended: true })); app.use(mainRouter) app.use('/api-docs', swaggerUi.serve as any); app.use('/api-docs', swaggerUi.setup(openapiSpecification) as any); const loadedTypeDefs = loadSchemaSync(path.join(__dirname, './**/*.graphql'), { loaders: [new GraphQLFileLoader()] }) const loadedResolvers = loadFilesSync(path.join(__dirname, './**/*.resolver.{ts,js}')) const typeDefs = mergeTypeDefs(loadedTypeDefs) if (process.env.NODE_ENV === 'development') { console.log('\n=== GraphQL Schema Start ===\n') const printedTypeDefs = print(typeDefs) console.log(printedTypeDefs) console.log('\n=== GraphQL Schema End ===\n') } const resolvers = mergeResolvers(loadedResolvers) const httpServer = http.createServer(app); const server = new ApolloServer({ typeDefs, resolvers, plugins: [ApolloServerPluginDrainHttpServer({ httpServer })] }); server.start().then(() => { server.applyMiddleware({ app }); app.listen(port, () => { console.log(`NseIndia App started in port ${port}`); console.log(`For API docs: ${hostUrl}/api-docs`); console.log(`Open ${hostUrl} in browser.`); console.log(`For graphql: ${hostUrl}${server.graphqlPath}`); // Log CORS configuration if (corsOrigins.length > 0) { console.log(`CORS Origins: ${corsOrigins.join(', ')}`); } console.log(`CORS Methods: ${corsMethods.join(', ')}`); console.log(`CORS Headers: ${corsHeaders.join(', ')}`); console.log(`CORS Credentials: ${process.env.CORS_CREDENTIALS !== 'false'}`); }) }) ================================================ FILE: src/stockIndex.graphql ================================================ type Index { key: String index: String indexSymbol: String last: Float variation: Float percentChange: Float open: Float high: Float low: Float previousClose: Float yearHigh: Float yearLow: Float } ================================================ FILE: src/swaggerDocOptions.ts ================================================ import swaggerJsDoc from 'swagger-jsdoc' const port = process.env.PORT || 3000 const hostUrl = process.env.HOST_URL || `http://localhost:${port}` export const swaggerDocOptions = { definition: { "openapi": "3.0.0", "info": { "version": "1.1.0", "title": "National Stock Exchange - India (Unofficial)", "description": "This package will help us to get equity details and historical data" + " from National Stock Exchange of India.", "contact": { "email": "asraf.cse@gmail.com" }, "license": { "name": "MIT", "url": "https://github.com/hi-imcodeman/stock-nse-india/blob/master/LICENSE" } }, "servers": [ { "url": hostUrl } ], "tags": [ { "name": "Base", "description": "Base API of NSE India" }, { "name": "Common", "description": "Contains all common APIs of NSE India" }, { "name": "Equity", "description": "Contains all equity related APIs of NSE India" }, { "name": "Index", "description": "Contains all index related APIs of NSE India" }, { "name": "Commodity", "description": "Contains all commodity related APIs of NSE India" }, { "name": "Helpers", "description": "Contains all helper APIs of NSE India" }, ] }, apis: ['./build/routes.js'] } export const openapiSpecification = swaggerJsDoc(swaggerDocOptions); ================================================ FILE: src/utils.spec.ts ================================================ import { getDataSchema } from './utils' describe('Utils', () => { const data={ a: 1, b: 'b', c: [1,2,3], d: {a:1,b:[2,3,4],c:{d:1},e:[]}, e: new Date('2022-09-12'), f: [[1,2],[3,4]] } test('getDataSchema with type strict',()=>{ expect(getDataSchema(data)).toMatchSnapshot() expect(getDataSchema(['hi'])).toMatchSnapshot('array_validation') }) test('getDataSchema for date value having typeStrict:false',()=>{ expect(getDataSchema(data,false)).toMatchSnapshot() expect(getDataSchema(['hi'],false)).toMatchSnapshot('array_validation') }) }) ================================================ FILE: src/utils.ts ================================================ import { extendMoment } from 'moment-range'; import * as Moment from 'moment'; const moment = extendMoment(Moment); /** * @private */ export const getDateRangeChunks = (startDate: Date, endDate: Date, chunkInDays: number): { start: string, end: string }[] => { const range = moment.range(startDate, endDate) const chunks = Array.from(range.by('days', { step: chunkInDays })) const dateRanges = [] for (let i = 0; i < chunks.length; i++) { dateRanges.push({ start: i > 0 ? chunks[i].add(1, 'day').format('DD-MM-YYYY') : chunks[i].format('DD-MM-YYYY'), end: chunks[i + 1] ? chunks[i + 1].format('DD-MM-YYYY') : range.end.format('DD-MM-YYYY') }) } return dateRanges } /** * @private */ export const sleep = (ms: number): Promise => { return new Promise(resolve => { setTimeout(() => { resolve() }, ms) }) } /** * @private * @param obj * @returns */ // eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types export const getDataSchema = (data: any, isTypeStrict=true): any[] | string => { if (typeof data !== 'object') return isTypeStrict ? `${typeof data}` : 'any' if(Array.isArray(data) && typeof data[0] !== 'object'){ return isTypeStrict ? `${typeof data[0]}[]` : 'any' } return Object.entries(data).map(([key, value]) => { if (Moment.isDate(value)) return `${key}: ${isTypeStrict ? 'Date': 'any'}` if (value === null || typeof value === 'string') return `${key}: ${isTypeStrict ? 'string | null': 'any'}` if (typeof value !== 'string' && Array.isArray(value)) { const typeForEmpty = isTypeStrict ? [] : 'any' return { [`${key}`]: value.length ? getDataSchema(value[0],isTypeStrict) : typeForEmpty } } if (typeof value === 'object') { return { [`${key}`]: getDataSchema(value,isTypeStrict) } } return `${key}: ${isTypeStrict ? typeof value : 'any'}` }) } ================================================ FILE: tsconfig.json ================================================ { "compilerOptions": { /* Basic Options */ // "incremental": true, /* Enable incremental compilation */ "target": "es2018", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */ "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */ "lib": ["es2018"], /* Specify library files to be included in the compilation. */ // "allowJs": true, /* Allow javascript files to be compiled. */ // "checkJs": true, /* Report errors in .js files. */ // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ "declaration": true, // Generates corresponding '.d.ts' file. "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ "sourceMap": true, /* Generates corresponding '.map' file. */ // "outFile": "./", /* Concatenate and emit output to single file. */ "outDir": "./build", // Redirect output structure to the directory. */ // "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ // "composite": true, /* Enable project compilation */ // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */ // "removeComments": true, /* Do not emit comments to output. */ // "noEmit": true, /* Do not emit outputs. */ // "importHelpers": true, /* Import emit helpers from 'tslib'. */ // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ /* Strict Type-Checking Options */ "strict": true, /* Enable all strict type-checking options. */ // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ // "strictNullChecks": true, /* Enable strict null checks. */ // "strictFunctionTypes": true, /* Enable strict checking of function types. */ // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ /* Additional Checks */ // "noUnusedLocals": true, /* Report errors on unused locals. */ // "noUnusedParameters": true, /* Report errors on unused parameters. */ // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ /* Module Resolution Options */ // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ // "typeRoots": [], /* List of folders to include type definitions from. */ // "types": [], /* Type declaration files to be included in compilation. */ // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ /* Source Map Options */ // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ /* Experimental Options */ // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ /* Advanced Options */ "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */ }, "include": [ "src/**/*.ts" ], "exclude": [ "**/*.spec.ts", "**/__mocks__" ], "typedocOptions": { "exclude": [ "**/*+(.spec|.e2e).ts", "**/cli", "**/server.ts", "**/swagger*.ts", "**/utils.ts", "**/constants.ts", "**/root.resolver.ts", "**/routes.ts" ], "excludePrivate": true, "includeVersion": true, "entryPoints": ["src"] } }