From 6af931d2d9361076302073c102732ee10f43736e Mon Sep 17 00:00:00 2001 From: Eddie Atkinson <45678264+eddie-atkinson@users.noreply.github.com> Date: Fri, 26 Jul 2024 13:57:25 +1000 Subject: [PATCH] Remove JSON schema validation pathway entirely --- .circleci/config.yml | 3 - CONTRIBUTING.md | 16 +- docs/validation.md | 5 +- package.json | 14 +- schema.json | 10291 ---------------- scripts/json-transform.sh | 51 - scripts/schema-check.sh | 14 - scripts/schema.ts | 75 - .../schema/TypeFormatter/yfFunctionIgnorer.ts | 20 - .../TypeFormatter/yfNumberTypeFormatter.ts | 23 - .../TypeFormatter/yfReferenceTypeFormatter.ts | 20 - scripts/schema/postWalker.js | 74 - src/index-common.ts | 4 +- src/lib/errors.ts | 11 +- src/lib/moduleCommon.ts | 8 +- src/lib/moduleExec.spec.ts | 117 +- src/lib/moduleExec.ts | 58 +- src/lib/moduleExecTypebox.spec.ts | 208 - src/lib/moduleExecTypebox.ts | 209 - src/lib/options.ts | 56 +- src/lib/queue.ts | 22 +- src/lib/setGlobalConfig.spec.ts | 46 +- src/lib/setGlobalConfig.ts | 30 +- src/lib/validateAndCoerceTypes.spec.ts | 578 +- src/lib/validateAndCoerceTypes.ts | 376 +- src/modules/chart.spec.ts | 4 +- src/modules/chart.ts | 2 +- src/modules/dailyGainers.ts | 2 +- src/modules/fundamentalsTimeSeries.ts | 2 +- src/modules/historical.spec.ts | 4 +- src/modules/historical.ts | 2 +- src/modules/insights.ts | 2 +- src/modules/options.ts | 2 +- src/modules/quote.ts | 2 +- src/modules/quoteSummary.ts | 2 +- src/modules/recommendationsBySymbol.ts | 2 +- src/modules/screener.ts | 2 +- src/modules/search.ts | 2 +- src/modules/trendingSymbols.ts | 2 +- tests/http/getCrumb-getcrumb | 67 - tests/testYf.ts | 2 - yarn.lock | 90 - 42 files changed, 440 insertions(+), 12080 deletions(-) delete mode 100644 schema.json delete mode 100755 scripts/json-transform.sh delete mode 100755 scripts/schema-check.sh delete mode 100644 scripts/schema.ts delete mode 100644 scripts/schema/TypeFormatter/yfFunctionIgnorer.ts delete mode 100644 scripts/schema/TypeFormatter/yfNumberTypeFormatter.ts delete mode 100644 scripts/schema/TypeFormatter/yfReferenceTypeFormatter.ts delete mode 100644 scripts/schema/postWalker.js delete mode 100644 src/lib/moduleExecTypebox.spec.ts delete mode 100644 src/lib/moduleExecTypebox.ts delete mode 100644 tests/http/getCrumb-getcrumb diff --git a/.circleci/config.yml b/.circleci/config.yml index 79d8873f..b2566445 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -42,9 +42,6 @@ jobs: # Check for TypeScript errors - run: yarn test:ts - # Check that schema is up-to-date - - run: scripts/schema-check.sh - - run: yarn prettier --check src tests tests-modules # run tests! diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 51fe1a1e..c3d4fbac 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -71,11 +71,6 @@ work and submitting your PR. All PRs should be submitted against the `devel` branch (github default). -**Changing TypeScript Interfaces** - -Run `yarn generateSchema` after changing any interfaces, this will regenerate -the `schema.json` file which is used for run-time tests. - **Commit Messages** Commit messages should follow the @@ -134,12 +129,11 @@ TODO Checklist: 1. Create it in `src/modules/myAmazingModule.ts` -1. Run `yarn generateSchema` (and on any future interface changes) -1. Test it in `src/modules/myAmazingModule.spec.ts` -1. Add it to `src/index-common.ts` -1. Docs in `docs/modules/myAmazingModule.md` -1. Link these docs in `README.md` and `docs/README.md`. -1. Commit all the above and any `tests/http/*` created in your tests. +2. Test it in `src/modules/myAmazingModule.spec.ts` +3. Add it to `src/index-common.ts` +4. Docs in `docs/modules/myAmazingModule.md` +5. Link these docs in `README.md` and `docs/README.md`. +6. Commit all the above and any `tests/http/*` created in your tests. For a model example, see the [recommendationsBySymbol PR](https://github.com/gadicc/node-yahoo-finance2/pull/28) diff --git a/docs/validation.md b/docs/validation.md index d6f18de1..2f69f595 100644 --- a/docs/validation.md +++ b/docs/validation.md @@ -146,16 +146,17 @@ receive back, we'll no longer throw a new error on new unknown keys. This is important because Yahoo constantly add new fields, and this would break all existing deployments. -You can revert to the old behaviour with: +You can revert to the old behaviour by passing the `_internalThrowOnAdditionalProperties` to the global configuration like so: ```js -yahooFinance._disallowAdditionalProps(); +yahooFinance.setGlobalConfig({ validation: { _internalThrowOnAdditionalProperties: true} }); ``` which is the default when `NODE_ENV==="test"`. This means that during our development of the library itself, we make sure that we're testing against all types. + ## Help Fix Validation Errors diff --git a/package.json b/package.json index e3ec9675..b589e3e0 100644 --- a/package.json +++ b/package.json @@ -37,15 +37,10 @@ "scripts": { "coverage": "yarn test --coverage", "lint": "eslint . --ext .js,.ts", - "//schema": "ts-json-schema-generator -f tsconfig.json -p 'src/{modules/**/*.ts,lib/options.ts}' -t '*' | node bin/schema-tweak.js > schema.json", - "schema": "node --loader ts-node/esm scripts/schema.js > schema.json", "timeseries": "node --loader ts-node/esm scripts/timeseries.js", - "build": "yarn run build:esm && yarn run build:cjs && yarn run build:post", + "build": "yarn run build:esm && yarn run build:cjs", "build:esm": "tsc --module es2020 --target es2019 --outDir dist/esm", "build:cjs": "tsc --module commonjs --target es2015 --outDir dist/cjs && sed 's/\"type\": \"module\",/\"type:\": \"commonjs\",/' dist/cjs/package.json > dist/cjs/package-changed.json && mv dist/cjs/package-changed.json dist/cjs/package.json", - "build:post": "scripts/json-transform.sh", - "generateSchema": "yarn schema", - "prepublishOnly": "yarn build && yarn generateSchema && yarn build:post", "test": "node --experimental-vm-modules ./node_modules/jest/bin/jest.js", "test:ts": "tsc --noEmit", "test:esm": "node --experimental-vm-modules ./node_modules/jest/bin/jest.js -c tests-modules/esm/jest.config.js tests-modules/esm/tests/*", @@ -54,14 +49,11 @@ "test:build": "yarn test:modules" }, "files": [ - "dist", - "schema.json" + "dist" ], "dependencies": { "@sinclair/typebox": "^0.32.27", "@types/tough-cookie": "^4.0.2", - "ajv": "8.10.0", - "ajv-formats": "2.1.1", "node-fetch": "^2.6.1", "tough-cookie": "^4.1.2", "tough-cookie-file-store": "^2.0.3" @@ -84,11 +76,9 @@ "globby": "13.2.2", "jest": "29.7.0", "jest-tobetype": "1.2.3", - "oas-schema-walker": "1.1.5", "prettier": "2.8.8", "semantic-release": "19.0.5", "ts-jest": "29.1.2", - "ts-json-schema-generator": "1.5.0", "ts-node": "10.9.2", "typescript": "5.4.3" } diff --git a/schema.json b/schema.json deleted file mode 100644 index f0248010..00000000 --- a/schema.json +++ /dev/null @@ -1,10291 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "$comment": "DO NOT EDIT THIS FILE. It is generated automatically from typescript interfaces in the project. To update, run `yarn schema`.", - "definitions": { - "Logger": { - "type": "object", - "properties": { - "info": {}, - "warn": {}, - "error": {}, - "debug": {} - }, - "required": [ - "info", - "warn", - "error", - "debug" - ], - "additionalProperties": false - }, - "YahooFinanceOptions": { - "type": "object", - "properties": { - "YF_QUERY_HOST": { - "type": "string" - }, - "cookieJar": { - "$ref": "#/definitions/ExtendedCookieJar" - }, - "queue": { - "$ref": "#/definitions/QueueOptions" - }, - "validation": { - "$ref": "#/definitions/ValidationOptions" - }, - "logger": { - "$ref": "#/definitions/Logger" - } - }, - "additionalProperties": false - }, - "ExtendedCookieJar": { - "type": "object", - "additionalProperties": false, - "properties": {} - }, - "CookieJar": { - "type": "object", - "additionalProperties": false - }, - "QueueOptions": { - "type": "object", - "properties": { - "concurrency": { - "yahooFinanceType": "number" - }, - "timeout": { - "yahooFinanceType": "number" - } - }, - "additionalProperties": false - }, - "ValidationOptions": { - "type": "object", - "properties": { - "logErrors": { - "type": "boolean" - }, - "logOptionsErrors": { - "type": "boolean" - } - }, - "additionalProperties": false - }, - "NamedParameters": { - "type": "object", - "additionalProperties": false - }, - "NamedParameters": { - "type": "object", - "properties": { - "this": { - "$ref": "#/definitions/ModuleThis" - }, - "symbol": { - "type": "string" - }, - "queryOptionsOverrides": { - "$ref": "#/definitions/ChartOptions" - }, - "moduleOptions": { - "$ref": "#/definitions/ModuleOptions" - } - }, - "required": [ - "this", - "symbol", - "queryOptionsOverrides" - ], - "additionalProperties": false - }, - "ModuleThis": { - "type": "object", - "properties": { - "_moduleExec": {}, - "_moduleExecTypebox": { - "$comment": "(\n this: { [key: string]: any },\n opts: ModuleExecOptions) -> undefined" - } - }, - "required": [ - "_moduleExec", - "_moduleExecTypebox" - ] - }, - "ChartOptions": { - "type": "object", - "properties": { - "period1": { - "anyOf": [ - { - "yahooFinanceType": "date" - }, - { - "type": "string" - }, - { - "yahooFinanceType": "number" - } - ] - }, - "period2": { - "anyOf": [ - { - "yahooFinanceType": "date" - }, - { - "type": "string" - }, - { - "yahooFinanceType": "number" - } - ] - }, - "useYfid": { - "type": "boolean" - }, - "interval": { - "type": "string", - "enum": [ - "1m", - "2m", - "5m", - "15m", - "30m", - "60m", - "90m", - "1h", - "1d", - "5d", - "1wk", - "1mo", - "3mo" - ] - }, - "includePrePost": { - "type": "boolean" - }, - "events": { - "type": "string" - }, - "lang": { - "type": "string" - }, - "return": { - "type": "string", - "enum": [ - "array", - "object" - ] - } - }, - "required": [ - "period1" - ], - "additionalProperties": false - }, - "ModuleOptions": { - "type": "object", - "properties": { - "validateResult": { - "type": "boolean" - }, - "devel": { - "type": [ - "boolean", - "string" - ] - }, - "fetchOptions": { - "type": "object" - } - }, - "additionalProperties": false - }, - "ChartResultObject": { - "type": "object", - "properties": { - "meta": { - "$ref": "#/definitions/ChartMeta" - }, - "timestamp": { - "type": "array", - "items": { - "yahooFinanceType": "number" - } - }, - "events": { - "$ref": "#/definitions/ChartEventsObject" - }, - "indicators": { - "$ref": "#/definitions/ChartIndicatorsObject" - } - }, - "required": [ - "meta", - "indicators" - ] - }, - "ChartMeta": { - "type": "object", - "properties": { - "currency": { - "type": "string" - }, - "symbol": { - "type": "string" - }, - "exchangeName": { - "type": "string" - }, - "instrumentType": { - "type": "string" - }, - "firstTradeDate": { - "yahooFinanceType": "date|null" - }, - "regularMarketTime": { - "yahooFinanceType": "date" - }, - "gmtoffset": { - "yahooFinanceType": "number" - }, - "timezone": { - "type": "string" - }, - "exchangeTimezoneName": { - "type": "string" - }, - "regularMarketPrice": { - "yahooFinanceType": "number" - }, - "chartPreviousClose": { - "yahooFinanceType": "number" - }, - "previousClose": { - "yahooFinanceType": "number" - }, - "scale": { - "yahooFinanceType": "number" - }, - "priceHint": { - "yahooFinanceType": "number" - }, - "currentTradingPeriod": { - "type": "object", - "properties": { - "pre": { - "$ref": "#/definitions/ChartMetaTradingPeriod" - }, - "regular": { - "$ref": "#/definitions/ChartMetaTradingPeriod" - }, - "post": { - "$ref": "#/definitions/ChartMetaTradingPeriod" - } - }, - "required": [ - "pre", - "regular", - "post" - ] - }, - "tradingPeriods": { - "$ref": "#/definitions/ChartMetaTradingPeriods" - }, - "dataGranularity": { - "type": "string" - }, - "range": { - "type": "string" - }, - "validRanges": { - "type": "array", - "items": { - "type": "string" - } - } - }, - "required": [ - "currency", - "symbol", - "exchangeName", - "instrumentType", - "firstTradeDate", - "regularMarketTime", - "gmtoffset", - "timezone", - "exchangeTimezoneName", - "regularMarketPrice", - "priceHint", - "currentTradingPeriod", - "dataGranularity", - "range", - "validRanges" - ] - }, - "ChartMetaTradingPeriod": { - "type": "object", - "properties": { - "timezone": { - "type": "string" - }, - "start": { - "yahooFinanceType": "date" - }, - "end": { - "yahooFinanceType": "date" - }, - "gmtoffset": { - "yahooFinanceType": "number" - } - }, - "required": [ - "timezone", - "start", - "end", - "gmtoffset" - ] - }, - "ChartMetaTradingPeriods": { - "type": "object", - "properties": { - "pre": { - "type": "array", - "items": { - "type": "array", - "items": { - "$ref": "#/definitions/ChartMetaTradingPeriod" - } - } - }, - "post": { - "type": "array", - "items": { - "type": "array", - "items": { - "$ref": "#/definitions/ChartMetaTradingPeriod" - } - } - }, - "regular": { - "type": "array", - "items": { - "type": "array", - "items": { - "$ref": "#/definitions/ChartMetaTradingPeriod" - } - } - } - } - }, - "ChartEventsObject": { - "type": "object", - "properties": { - "dividends": { - "$ref": "#/definitions/ChartEventDividends" - }, - "splits": { - "$ref": "#/definitions/ChartEventSplits" - } - } - }, - "ChartEventDividends": { - "type": "object", - "additionalProperties": { - "$ref": "#/definitions/ChartEventDividend" - } - }, - "ChartEventDividend": { - "type": "object", - "properties": { - "amount": { - "yahooFinanceType": "number" - }, - "date": { - "yahooFinanceType": "date" - } - }, - "required": [ - "amount", - "date" - ] - }, - "ChartEventSplits": { - "type": "object", - "additionalProperties": { - "$ref": "#/definitions/ChartEventSplit" - } - }, - "ChartEventSplit": { - "type": "object", - "properties": { - "date": { - "yahooFinanceType": "date" - }, - "numerator": { - "yahooFinanceType": "number" - }, - "denominator": { - "yahooFinanceType": "number" - }, - "splitRatio": { - "type": "string" - } - }, - "required": [ - "date", - "numerator", - "denominator", - "splitRatio" - ] - }, - "ChartIndicatorsObject": { - "type": "object", - "properties": { - "quote": { - "type": "array", - "items": { - "$ref": "#/definitions/ChartIndicatorQuote" - } - }, - "adjclose": { - "type": "array", - "items": { - "$ref": "#/definitions/ChartIndicatorAdjclose" - } - } - }, - "required": [ - "quote" - ] - }, - "ChartIndicatorQuote": { - "type": "object", - "properties": { - "high": { - "type": "array", - "items": { - "yahooFinanceType": "number|null" - } - }, - "low": { - "type": "array", - "items": { - "yahooFinanceType": "number|null" - } - }, - "open": { - "type": "array", - "items": { - "yahooFinanceType": "number|null" - } - }, - "close": { - "type": "array", - "items": { - "yahooFinanceType": "number|null" - } - }, - "volume": { - "type": "array", - "items": { - "yahooFinanceType": "number|null" - } - } - }, - "required": [ - "high", - "low", - "open", - "close", - "volume" - ] - }, - "ChartIndicatorAdjclose": { - "type": "object", - "properties": { - "adjclose": { - "type": "array", - "items": { - "yahooFinanceType": "number|null" - } - } - } - }, - "ChartResultArray": { - "type": "object", - "properties": { - "meta": { - "$ref": "#/definitions/ChartMeta" - }, - "events": { - "$ref": "#/definitions/ChartEventsArray" - }, - "quotes": { - "type": "array", - "items": { - "$ref": "#/definitions/ChartResultArrayQuote" - } - } - }, - "required": [ - "meta", - "quotes" - ], - "additionalProperties": false - }, - "ChartEventsArray": { - "type": "object", - "properties": { - "dividends": { - "type": "array", - "items": { - "$ref": "#/definitions/ChartEventDividend" - } - }, - "splits": { - "type": "array", - "items": { - "$ref": "#/definitions/ChartEventSplit" - } - } - } - }, - "ChartResultArrayQuote": { - "type": "object", - "properties": { - "date": { - "yahooFinanceType": "date" - }, - "high": { - "yahooFinanceType": "number|null" - }, - "low": { - "yahooFinanceType": "number|null" - }, - "open": { - "yahooFinanceType": "number|null" - }, - "close": { - "yahooFinanceType": "number|null" - }, - "volume": { - "yahooFinanceType": "number|null" - }, - "adjclose": { - "yahooFinanceType": "number|null" - } - }, - "required": [ - "date", - "high", - "low", - "open", - "close", - "volume" - ] - }, - "ChartOptionsWithReturnArray": { - "type": "object", - "properties": { - "period1": { - "anyOf": [ - { - "yahooFinanceType": "date" - }, - { - "type": "string" - }, - { - "yahooFinanceType": "number" - } - ] - }, - "period2": { - "anyOf": [ - { - "yahooFinanceType": "date" - }, - { - "type": "string" - }, - { - "yahooFinanceType": "number" - } - ] - }, - "useYfid": { - "type": "boolean" - }, - "interval": { - "type": "string", - "enum": [ - "1m", - "2m", - "5m", - "15m", - "30m", - "60m", - "90m", - "1h", - "1d", - "5d", - "1wk", - "1mo", - "3mo" - ] - }, - "includePrePost": { - "type": "boolean" - }, - "events": { - "type": "string" - }, - "lang": { - "type": "string" - }, - "return": { - "type": "string", - "const": "array" - } - }, - "additionalProperties": false, - "required": [ - "period1" - ] - }, - "ChartOptionsWithReturnObject": { - "type": "object", - "properties": { - "period1": { - "anyOf": [ - { - "yahooFinanceType": "date" - }, - { - "type": "string" - }, - { - "yahooFinanceType": "number" - } - ] - }, - "period2": { - "anyOf": [ - { - "yahooFinanceType": "date" - }, - { - "type": "string" - }, - { - "yahooFinanceType": "number" - } - ] - }, - "useYfid": { - "type": "boolean" - }, - "interval": { - "type": "string", - "enum": [ - "1m", - "2m", - "5m", - "15m", - "30m", - "60m", - "90m", - "1h", - "1d", - "5d", - "1wk", - "1mo", - "3mo" - ] - }, - "includePrePost": { - "type": "boolean" - }, - "events": { - "type": "string" - }, - "lang": { - "type": "string" - }, - "return": { - "type": "string", - "const": "object" - } - }, - "required": [ - "period1", - "return" - ], - "additionalProperties": false - }, - "NamedParameters": { - "type": "object", - "properties": { - "this": { - "$ref": "#/definitions/ModuleThis" - }, - "queryOptionsOverrides": { - "$ref": "#/definitions/DailyGainersOptions" - }, - "moduleOptions": { - "$ref": "#/definitions/ModuleOptions" - } - }, - "required": [ - "this" - ], - "additionalProperties": false - }, - "DailyGainersOptions": { - "type": "object", - "properties": { - "lang": { - "type": "string" - }, - "region": { - "type": "string" - }, - "count": { - "yahooFinanceType": "number" - } - }, - "additionalProperties": false - }, - "DailyGainersResult": { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "title": { - "type": "string" - }, - "description": { - "type": "string" - }, - "canonicalName": { - "type": "string" - }, - "criteriaMeta": { - "$ref": "#/definitions/DailyGainersCriteriaMeta" - }, - "rawCriteria": { - "type": "string" - }, - "start": { - "yahooFinanceType": "number" - }, - "count": { - "yahooFinanceType": "number" - }, - "total": { - "yahooFinanceType": "number" - }, - "quotes": { - "type": "array", - "items": { - "$ref": "#/definitions/DailyGainersQuote" - } - }, - "useRecords": { - "type": "boolean" - }, - "predefinedScr": { - "type": "boolean" - }, - "versionId": { - "yahooFinanceType": "number" - }, - "creationDate": { - "yahooFinanceType": "number" - }, - "lastUpdated": { - "yahooFinanceType": "number" - }, - "isPremium": { - "type": "boolean" - }, - "iconUrl": { - "type": "string" - } - }, - "required": [ - "id", - "title", - "description", - "canonicalName", - "criteriaMeta", - "rawCriteria", - "start", - "count", - "total", - "quotes", - "useRecords", - "predefinedScr", - "versionId", - "creationDate", - "lastUpdated", - "isPremium", - "iconUrl" - ], - "additionalProperties": false - }, - "DailyGainersCriteriaMeta": { - "type": "object", - "properties": { - "size": { - "yahooFinanceType": "number" - }, - "offset": { - "yahooFinanceType": "number" - }, - "sortField": { - "type": "string" - }, - "sortType": { - "type": "string" - }, - "quoteType": { - "type": "string" - }, - "criteria": { - "type": "array", - "items": { - "$ref": "#/definitions/DailyGainersCriterum" - } - }, - "topOperator": { - "type": "string" - } - }, - "required": [ - "size", - "offset", - "sortField", - "sortType", - "quoteType", - "criteria", - "topOperator" - ], - "additionalProperties": false - }, - "DailyGainersCriterum": { - "type": "object", - "properties": { - "field": { - "type": "string" - }, - "operators": { - "type": "array", - "items": { - "type": "string" - } - }, - "values": { - "type": "array", - "items": { - "yahooFinanceType": "number" - } - }, - "labelsSelected": { - "type": "array", - "items": { - "yahooFinanceType": "number" - } - }, - "dependentValues": { - "type": "array", - "items": {} - } - }, - "required": [ - "field", - "operators", - "values", - "labelsSelected", - "dependentValues" - ], - "additionalProperties": false - }, - "DailyGainersQuote": { - "type": "object", - "properties": { - "language": { - "type": "string" - }, - "region": { - "type": "string" - }, - "quoteType": { - "type": "string" - }, - "typeDisp": { - "type": "string" - }, - "quoteSourceName": { - "type": "string" - }, - "triggerable": { - "type": "boolean" - }, - "customPriceAlertConfidence": { - "type": "string" - }, - "lastCloseTevEbitLtm": { - "yahooFinanceType": "number" - }, - "lastClosePriceToNNWCPerShare": { - "yahooFinanceType": "number" - }, - "firstTradeDateMilliseconds": { - "yahooFinanceType": "number" - }, - "priceHint": { - "yahooFinanceType": "number" - }, - "postMarketChangePercent": { - "yahooFinanceType": "number" - }, - "postMarketTime": { - "yahooFinanceType": "number" - }, - "postMarketPrice": { - "yahooFinanceType": "number" - }, - "postMarketChange": { - "yahooFinanceType": "number" - }, - "regularMarketChange": { - "yahooFinanceType": "number" - }, - "regularMarketTime": { - "yahooFinanceType": "number" - }, - "regularMarketPrice": { - "yahooFinanceType": "number" - }, - "regularMarketDayHigh": { - "yahooFinanceType": "number" - }, - "regularMarketDayRange": { - "type": "string" - }, - "currency": { - "type": "string" - }, - "regularMarketDayLow": { - "yahooFinanceType": "number" - }, - "regularMarketVolume": { - "yahooFinanceType": "number" - }, - "regularMarketPreviousClose": { - "yahooFinanceType": "number" - }, - "bid": { - "yahooFinanceType": "number" - }, - "ask": { - "yahooFinanceType": "number" - }, - "bidSize": { - "yahooFinanceType": "number" - }, - "askSize": { - "yahooFinanceType": "number" - }, - "market": { - "type": "string" - }, - "messageBoardId": { - "type": "string" - }, - "fullExchangeName": { - "type": "string" - }, - "longName": { - "type": "string" - }, - "financialCurrency": { - "type": "string" - }, - "regularMarketOpen": { - "yahooFinanceType": "number" - }, - "averageDailyVolume3Month": { - "yahooFinanceType": "number" - }, - "averageDailyVolume10Day": { - "yahooFinanceType": "number" - }, - "fiftyTwoWeekLowChange": { - "yahooFinanceType": "number" - }, - "fiftyTwoWeekLowChangePercent": { - "yahooFinanceType": "number" - }, - "fiftyTwoWeekRange": { - "type": "string" - }, - "fiftyTwoWeekHighChange": { - "yahooFinanceType": "number" - }, - "fiftyTwoWeekHighChangePercent": { - "yahooFinanceType": "number" - }, - "fiftyTwoWeekChangePercent": { - "yahooFinanceType": "number" - }, - "earningsTimestamp": { - "yahooFinanceType": "number" - }, - "earningsTimestampStart": { - "yahooFinanceType": "number" - }, - "earningsTimestampEnd": { - "yahooFinanceType": "number" - }, - "trailingAnnualDividendRate": { - "yahooFinanceType": "number" - }, - "trailingAnnualDividendYield": { - "yahooFinanceType": "number" - }, - "marketState": { - "type": "string" - }, - "epsTrailingTwelveMonths": { - "yahooFinanceType": "number" - }, - "epsForward": { - "yahooFinanceType": "number" - }, - "epsCurrentYear": { - "yahooFinanceType": "number" - }, - "priceEpsCurrentYear": { - "yahooFinanceType": "number" - }, - "sharesOutstanding": { - "yahooFinanceType": "number" - }, - "bookValue": { - "yahooFinanceType": "number" - }, - "fiftyDayAverage": { - "yahooFinanceType": "number" - }, - "fiftyDayAverageChange": { - "yahooFinanceType": "number" - }, - "fiftyDayAverageChangePercent": { - "yahooFinanceType": "number" - }, - "twoHundredDayAverage": { - "yahooFinanceType": "number" - }, - "twoHundredDayAverageChange": { - "yahooFinanceType": "number" - }, - "twoHundredDayAverageChangePercent": { - "yahooFinanceType": "number" - }, - "marketCap": { - "yahooFinanceType": "number" - }, - "forwardPE": { - "yahooFinanceType": "number" - }, - "priceToBook": { - "yahooFinanceType": "number" - }, - "sourceInterval": { - "yahooFinanceType": "number" - }, - "exchangeDataDelayedBy": { - "yahooFinanceType": "number" - }, - "exchangeTimezoneName": { - "type": "string" - }, - "exchangeTimezoneShortName": { - "type": "string" - }, - "gmtOffSetMilliseconds": { - "yahooFinanceType": "number" - }, - "esgPopulated": { - "type": "boolean" - }, - "tradeable": { - "type": "boolean" - }, - "cryptoTradeable": { - "type": "boolean" - }, - "exchange": { - "type": "string" - }, - "fiftyTwoWeekLow": { - "yahooFinanceType": "number" - }, - "fiftyTwoWeekHigh": { - "yahooFinanceType": "number" - }, - "shortName": { - "type": "string" - }, - "averageAnalystRating": { - "type": "string" - }, - "regularMarketChangePercent": { - "yahooFinanceType": "number" - }, - "symbol": { - "type": "string" - }, - "dividendDate": { - "yahooFinanceType": "number" - }, - "displayName": { - "type": "string" - }, - "trailingPE": { - "yahooFinanceType": "number" - }, - "prevName": { - "type": "string" - }, - "nameChangeDate": { - "yahooFinanceType": "number" - }, - "ipoExpectedDate": { - "yahooFinanceType": "number" - }, - "dividendYield": { - "yahooFinanceType": "number" - }, - "dividendRate": { - "yahooFinanceType": "number" - } - }, - "required": [ - "language", - "region", - "quoteType", - "typeDisp", - "quoteSourceName", - "triggerable", - "customPriceAlertConfidence", - "firstTradeDateMilliseconds", - "priceHint", - "regularMarketChange", - "regularMarketTime", - "regularMarketPrice", - "regularMarketDayHigh", - "regularMarketDayRange", - "currency", - "regularMarketDayLow", - "regularMarketVolume", - "regularMarketPreviousClose", - "market", - "messageBoardId", - "fullExchangeName", - "longName", - "regularMarketOpen", - "averageDailyVolume3Month", - "averageDailyVolume10Day", - "fiftyTwoWeekLowChange", - "fiftyTwoWeekLowChangePercent", - "fiftyTwoWeekRange", - "fiftyTwoWeekHighChange", - "fiftyTwoWeekHighChangePercent", - "fiftyTwoWeekChangePercent", - "trailingAnnualDividendRate", - "trailingAnnualDividendYield", - "marketState", - "sharesOutstanding", - "fiftyDayAverage", - "fiftyDayAverageChange", - "fiftyDayAverageChangePercent", - "twoHundredDayAverage", - "twoHundredDayAverageChange", - "twoHundredDayAverageChangePercent", - "marketCap", - "sourceInterval", - "exchangeDataDelayedBy", - "exchangeTimezoneName", - "exchangeTimezoneShortName", - "gmtOffSetMilliseconds", - "esgPopulated", - "tradeable", - "cryptoTradeable", - "exchange", - "fiftyTwoWeekLow", - "fiftyTwoWeekHigh", - "shortName", - "regularMarketChangePercent", - "symbol" - ], - "additionalProperties": false - }, - "NamedParameters": { - "type": "object", - "properties": { - "this": { - "$ref": "#/definitions/ModuleThis" - }, - "symbol": { - "type": "string" - }, - "queryOptionsOverrides": { - "$ref": "#/definitions/FundamentalsTimeSeriesOptions" - }, - "moduleOptions": { - "$ref": "#/definitions/ModuleOptions" - } - }, - "required": [ - "this", - "symbol", - "queryOptionsOverrides" - ], - "additionalProperties": false - }, - "FundamentalsTimeSeriesOptions": { - "type": "object", - "properties": { - "period1": { - "anyOf": [ - { - "yahooFinanceType": "date" - }, - { - "yahooFinanceType": "number" - }, - { - "type": "string" - } - ] - }, - "period2": { - "anyOf": [ - { - "yahooFinanceType": "date" - }, - { - "yahooFinanceType": "number" - }, - { - "type": "string" - } - ] - }, - "type": { - "type": "string" - }, - "merge": { - "type": "boolean" - }, - "padTimeSeries": { - "type": "boolean" - }, - "lang": { - "type": "string" - }, - "region": { - "type": "string" - }, - "module": { - "type": "string" - } - }, - "required": [ - "period1", - "module" - ], - "additionalProperties": false - }, - "NamedParameters": { - "type": "object", - "properties": { - "queryOptions": { - "$ref": "#/definitions/FundamentalsTimeSeriesOptions", - "description": "Input query options." - } - }, - "required": [ - "queryOptions" - ], - "additionalProperties": false - }, - "NamedParameters": { - "type": "object", - "properties": { - "response": { - "description": "Query response." - } - }, - "required": [ - "response" - ], - "additionalProperties": false - }, - "FundamentalsTimeSeriesResults": { - "type": "array", - "items": { - "$ref": "#/definitions/FundamentalsTimeSeriesResult" - } - }, - "FundamentalsTimeSeriesResult": { - "type": "object", - "properties": { - "date": { - "yahooFinanceType": "date" - } - }, - "required": [ - "date" - ], - "additionalProperties": {} - }, - "NamedParameters": { - "type": "object", - "properties": { - "this": { - "$ref": "#/definitions/ModuleThis" - }, - "symbol": { - "type": "string" - }, - "queryOptionsOverrides": { - "$ref": "#/definitions/HistoricalOptions" - }, - "moduleOptions": { - "$ref": "#/definitions/ModuleOptions" - } - }, - "required": [ - "this", - "symbol", - "queryOptionsOverrides" - ], - "additionalProperties": false - }, - "HistoricalOptions": { - "type": "object", - "properties": { - "period1": { - "anyOf": [ - { - "yahooFinanceType": "date" - }, - { - "type": "string" - }, - { - "yahooFinanceType": "number" - } - ] - }, - "period2": { - "anyOf": [ - { - "yahooFinanceType": "date" - }, - { - "type": "string" - }, - { - "yahooFinanceType": "number" - } - ] - }, - "interval": { - "type": "string", - "enum": [ - "1d", - "1wk", - "1mo" - ] - }, - "events": { - "type": "string" - }, - "includeAdjustedClose": { - "type": "boolean" - } - }, - "required": [ - "period1" - ], - "additionalProperties": false - }, - "HistoricalHistoryResult": { - "type": "array", - "items": { - "$ref": "#/definitions/HistoricalRowHistory" - } - }, - "HistoricalRowHistory": { - "type": "object", - "properties": { - "date": { - "yahooFinanceType": "date" - }, - "open": { - "yahooFinanceType": "number" - }, - "high": { - "yahooFinanceType": "number" - }, - "low": { - "yahooFinanceType": "number" - }, - "close": { - "yahooFinanceType": "number" - }, - "adjClose": { - "yahooFinanceType": "number" - }, - "volume": { - "yahooFinanceType": "number" - } - }, - "required": [ - "date", - "open", - "high", - "low", - "close", - "volume" - ] - }, - "HistoricalDividendsResult": { - "type": "array", - "items": { - "$ref": "#/definitions/HistoricalRowDividend" - } - }, - "HistoricalRowDividend": { - "type": "object", - "properties": { - "date": { - "yahooFinanceType": "date" - }, - "dividends": { - "yahooFinanceType": "number" - } - }, - "required": [ - "date", - "dividends" - ], - "additionalProperties": false - }, - "HistoricalStockSplitsResult": { - "type": "array", - "items": { - "$ref": "#/definitions/HistoricalRowStockSplit" - } - }, - "HistoricalRowStockSplit": { - "type": "object", - "properties": { - "date": { - "yahooFinanceType": "date" - }, - "stockSplits": { - "type": "string" - } - }, - "required": [ - "date", - "stockSplits" - ], - "additionalProperties": false - }, - "HistoricalResult": { - "anyOf": [ - { - "$ref": "#/definitions/HistoricalHistoryResult" - }, - { - "$ref": "#/definitions/HistoricalDividendsResult" - }, - { - "$ref": "#/definitions/HistoricalStockSplitsResult" - } - ] - }, - "HistoricalOptionsEventsHistory": { - "type": "object", - "properties": { - "period1": { - "anyOf": [ - { - "yahooFinanceType": "date" - }, - { - "type": "string" - }, - { - "yahooFinanceType": "number" - } - ] - }, - "period2": { - "anyOf": [ - { - "yahooFinanceType": "date" - }, - { - "type": "string" - }, - { - "yahooFinanceType": "number" - } - ] - }, - "interval": { - "type": "string", - "enum": [ - "1d", - "1wk", - "1mo" - ] - }, - "events": { - "type": "string", - "const": "history" - }, - "includeAdjustedClose": { - "type": "boolean" - } - }, - "additionalProperties": false, - "required": [ - "period1" - ] - }, - "HistoricalOptionsEventsDividends": { - "type": "object", - "properties": { - "period1": { - "anyOf": [ - { - "yahooFinanceType": "date" - }, - { - "type": "string" - }, - { - "yahooFinanceType": "number" - } - ] - }, - "period2": { - "anyOf": [ - { - "yahooFinanceType": "date" - }, - { - "type": "string" - }, - { - "yahooFinanceType": "number" - } - ] - }, - "interval": { - "type": "string", - "enum": [ - "1d", - "1wk", - "1mo" - ] - }, - "events": { - "type": "string", - "const": "dividends" - }, - "includeAdjustedClose": { - "type": "boolean" - } - }, - "required": [ - "events", - "period1" - ], - "additionalProperties": false - }, - "HistoricalOptionsEventsSplit": { - "type": "object", - "properties": { - "period1": { - "anyOf": [ - { - "yahooFinanceType": "date" - }, - { - "type": "string" - }, - { - "yahooFinanceType": "number" - } - ] - }, - "period2": { - "anyOf": [ - { - "yahooFinanceType": "date" - }, - { - "type": "string" - }, - { - "yahooFinanceType": "number" - } - ] - }, - "interval": { - "type": "string", - "enum": [ - "1d", - "1wk", - "1mo" - ] - }, - "events": { - "type": "string", - "const": "split" - }, - "includeAdjustedClose": { - "type": "boolean" - } - }, - "required": [ - "events", - "period1" - ], - "additionalProperties": false - }, - "InsightsInstrumentInfo": { - "type": "object", - "properties": { - "keyTechnicals": { - "type": "object", - "properties": { - "provider": { - "type": "string" - }, - "support": { - "yahooFinanceType": "number" - }, - "resistance": { - "yahooFinanceType": "number" - }, - "stopLoss": { - "yahooFinanceType": "number" - } - }, - "required": [ - "provider" - ] - }, - "technicalEvents": { - "type": "object", - "properties": { - "provider": { - "type": "string" - }, - "sector": { - "type": "string" - }, - "shortTermOutlook": { - "$ref": "#/definitions/InsightsOutlook" - }, - "intermediateTermOutlook": { - "$ref": "#/definitions/InsightsOutlook" - }, - "longTermOutlook": { - "$ref": "#/definitions/InsightsOutlook" - } - }, - "required": [ - "provider", - "shortTermOutlook", - "intermediateTermOutlook", - "longTermOutlook" - ] - }, - "valuation": { - "type": "object", - "properties": { - "color": { - "yahooFinanceType": "number" - }, - "description": { - "type": "string" - }, - "discount": { - "type": "string" - }, - "provider": { - "type": "string" - }, - "relativeValue": { - "type": "string" - } - }, - "required": [ - "provider" - ] - } - }, - "required": [ - "keyTechnicals", - "technicalEvents", - "valuation" - ] - }, - "InsightsOutlook": { - "type": "object", - "properties": { - "stateDescription": { - "type": "string" - }, - "direction": { - "$ref": "#/definitions/InsightsDirection" - }, - "score": { - "yahooFinanceType": "number" - }, - "scoreDescription": { - "type": "string" - }, - "sectorDirection": { - "$ref": "#/definitions/InsightsDirection" - }, - "sectorScore": { - "yahooFinanceType": "number" - }, - "sectorScoreDescription": { - "type": "string" - }, - "indexDirection": { - "$ref": "#/definitions/InsightsDirection" - }, - "indexScore": { - "yahooFinanceType": "number" - }, - "indexScoreDescription": { - "type": "string" - } - }, - "required": [ - "stateDescription", - "direction", - "score", - "scoreDescription", - "indexDirection", - "indexScore", - "indexScoreDescription" - ] - }, - "InsightsDirection": { - "type": "string", - "enum": [ - "Bearish", - "Bullish", - "Neutral" - ] - }, - "InsightsCompanySnapshot": { - "type": "object", - "properties": { - "sectorInfo": { - "type": "string" - }, - "company": { - "type": "object", - "properties": { - "innovativeness": { - "yahooFinanceType": "number" - }, - "hiring": { - "yahooFinanceType": "number" - }, - "sustainability": { - "yahooFinanceType": "number" - }, - "insiderSentiments": { - "yahooFinanceType": "number" - }, - "earningsReports": { - "yahooFinanceType": "number" - }, - "dividends": { - "yahooFinanceType": "number" - } - } - }, - "sector": { - "type": "object", - "properties": { - "innovativeness": { - "yahooFinanceType": "number" - }, - "hiring": { - "yahooFinanceType": "number" - }, - "sustainability": { - "yahooFinanceType": "number" - }, - "insiderSentiments": { - "yahooFinanceType": "number" - }, - "earningsReports": { - "yahooFinanceType": "number" - }, - "dividends": { - "yahooFinanceType": "number" - } - }, - "required": [ - "innovativeness", - "hiring", - "insiderSentiments", - "dividends" - ] - } - }, - "required": [ - "company", - "sector" - ] - }, - "NamedParameters": { - "type": "object", - "properties": { - "this": { - "$ref": "#/definitions/ModuleThis" - }, - "query": { - "type": "string" - }, - "queryOptionsOverrides": { - "$ref": "#/definitions/TrendingSymbolsOptions" - }, - "moduleOptions": { - "$ref": "#/definitions/ModuleOptions" - } - }, - "required": [ - "this", - "query" - ], - "additionalProperties": false - }, - "TrendingSymbolsOptions": { - "type": "object", - "properties": { - "lang": { - "type": "string" - }, - "region": { - "type": "string" - }, - "count": { - "yahooFinanceType": "number" - } - }, - "additionalProperties": false - }, - "InsightsResult": { - "type": "object", - "properties": { - "symbol": { - "type": "string" - }, - "instrumentInfo": { - "$ref": "#/definitions/InsightsInstrumentInfo" - }, - "companySnapshot": { - "$ref": "#/definitions/InsightsCompanySnapshot" - }, - "recommendation": { - "type": "object", - "properties": { - "targetPrice": { - "yahooFinanceType": "number" - }, - "provider": { - "type": "string" - }, - "rating": { - "type": "string", - "enum": [ - "BUY", - "SELL", - "HOLD" - ] - } - }, - "required": [ - "provider", - "rating" - ], - "additionalProperties": false - }, - "events": { - "type": "array", - "items": { - "$ref": "#/definitions/InsightsEvent" - } - }, - "reports": { - "type": "array", - "items": { - "$ref": "#/definitions/InsightsReport" - } - }, - "sigDevs": { - "type": "array", - "items": { - "$ref": "#/definitions/InsightsSigDev" - } - }, - "upsell": { - "$ref": "#/definitions/InsightsUpsell" - }, - "upsellSearchDD": { - "type": "object", - "properties": { - "researchReports": { - "$ref": "#/definitions/InsightsResearchReport" - } - }, - "required": [ - "researchReports" - ], - "additionalProperties": false - }, - "secReports": { - "type": "array", - "items": { - "$ref": "#/definitions/InsightsSecReport" - } - } - }, - "required": [ - "symbol", - "sigDevs" - ] - }, - "InsightsEvent": { - "type": "object", - "properties": { - "eventType": { - "type": "string" - }, - "pricePeriod": { - "type": "string" - }, - "tradingHorizon": { - "type": "string" - }, - "tradeType": { - "type": "string" - }, - "imageUrl": { - "type": "string" - }, - "startDate": { - "yahooFinanceType": "date" - }, - "endDate": { - "yahooFinanceType": "date" - } - }, - "required": [ - "eventType", - "pricePeriod", - "tradingHorizon", - "tradeType", - "imageUrl", - "startDate", - "endDate" - ] - }, - "InsightsReport": { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "headHtml": { - "type": "string" - }, - "provider": { - "type": "string" - }, - "reportDate": { - "yahooFinanceType": "date" - }, - "reportTitle": { - "type": "string" - }, - "reportType": { - "type": "string" - }, - "targetPrice": { - "yahooFinanceType": "number" - }, - "targetPriceStatus": { - "type": "string", - "enum": [ - "Increased", - "Maintained", - "Decreased", - "-" - ] - }, - "investmentRating": { - "type": "string", - "enum": [ - "Bullish", - "Neutral", - "Bearish" - ] - }, - "tickers": { - "type": "array", - "items": { - "type": "string" - } - } - }, - "required": [ - "id", - "headHtml", - "provider", - "reportDate", - "reportTitle", - "reportType" - ] - }, - "InsightsSigDev": { - "type": "object", - "properties": { - "headline": { - "type": "string" - }, - "date": { - "yahooFinanceType": "date" - } - }, - "required": [ - "headline", - "date" - ] - }, - "InsightsUpsell": { - "type": "object", - "properties": { - "msBullishSummary": { - "type": "array", - "items": { - "type": "string" - } - }, - "msBearishSummary": { - "type": "array", - "items": { - "type": "string" - } - }, - "msBullishBearishSummariesPublishDate": { - "yahooFinanceType": "DateInMs" - }, - "companyName": { - "type": "string" - }, - "upsellReportType": { - "type": "string" - } - } - }, - "DateInMs": { - "yahooFinanceType": "date" - }, - "InsightsResearchReport": { - "type": "object", - "properties": { - "reportId": { - "type": "string" - }, - "provider": { - "type": "string" - }, - "title": { - "type": "string" - }, - "reportDate": { - "yahooFinanceType": "date" - }, - "summary": { - "type": "string" - }, - "investmentRating": { - "type": "string", - "enum": [ - "Bullish", - "Neutral", - "Bearish" - ] - } - }, - "required": [ - "reportId", - "provider", - "title", - "reportDate", - "summary" - ], - "additionalProperties": false - }, - "InsightsSecReport": { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "type": { - "type": "string" - }, - "title": { - "type": "string" - }, - "description": { - "type": "string" - }, - "filingDate": { - "yahooFinanceType": "DateInMs" - }, - "snapshotUrl": { - "type": "string" - }, - "formType": { - "type": "string" - } - }, - "required": [ - "id", - "type", - "title", - "description", - "filingDate", - "snapshotUrl", - "formType" - ], - "additionalProperties": false - }, - "InsightsOptions": { - "type": "object", - "properties": { - "lang": { - "type": "string" - }, - "region": { - "type": "string" - }, - "reportsCount": { - "yahooFinanceType": "number" - } - }, - "additionalProperties": false - }, - "NamedParameters": { - "type": "object", - "properties": { - "this": { - "$ref": "#/definitions/ModuleThis" - }, - "symbol": { - "type": "string" - }, - "queryOptionsOverrides": { - "$ref": "#/definitions/OptionsOptions" - }, - "moduleOptions": { - "$ref": "#/definitions/ModuleOptions" - } - }, - "required": [ - "this", - "symbol", - "queryOptionsOverrides" - ], - "additionalProperties": false - }, - "OptionsOptions": { - "type": "object", - "properties": { - "formatted": { - "type": "boolean" - }, - "lang": { - "type": "string" - }, - "region": { - "type": "string" - }, - "date": { - "anyOf": [ - { - "yahooFinanceType": "date" - }, - { - "yahooFinanceType": "number" - }, - { - "type": "string" - } - ] - } - }, - "additionalProperties": false - }, - "QuoteBase": { - "type": "object", - "properties": { - "language": { - "type": "string" - }, - "region": { - "type": "string" - }, - "quoteType": { - "type": "string" - }, - "typeDisp": { - "type": "string" - }, - "quoteSourceName": { - "type": "string" - }, - "triggerable": { - "type": "boolean" - }, - "currency": { - "type": "string" - }, - "customPriceAlertConfidence": { - "type": "string" - }, - "marketState": { - "type": "string", - "enum": [ - "REGULAR", - "CLOSED", - "PRE", - "PREPRE", - "POST", - "POSTPOST" - ] - }, - "tradeable": { - "type": "boolean" - }, - "cryptoTradeable": { - "type": "boolean" - }, - "exchange": { - "type": "string" - }, - "shortName": { - "type": "string" - }, - "longName": { - "type": "string" - }, - "messageBoardId": { - "type": "string" - }, - "exchangeTimezoneName": { - "type": "string" - }, - "exchangeTimezoneShortName": { - "type": "string" - }, - "gmtOffSetMilliseconds": { - "yahooFinanceType": "number" - }, - "market": { - "type": "string" - }, - "esgPopulated": { - "type": "boolean" - }, - "fiftyTwoWeekLowChange": { - "yahooFinanceType": "number" - }, - "fiftyTwoWeekLowChangePercent": { - "yahooFinanceType": "number" - }, - "fiftyTwoWeekRange": { - "yahooFinanceType": "TwoNumberRange" - }, - "fiftyTwoWeekHighChange": { - "yahooFinanceType": "number" - }, - "fiftyTwoWeekHighChangePercent": { - "yahooFinanceType": "number" - }, - "fiftyTwoWeekLow": { - "yahooFinanceType": "number" - }, - "fiftyTwoWeekHigh": { - "yahooFinanceType": "number" - }, - "fiftyTwoWeekChangePercent": { - "yahooFinanceType": "number" - }, - "dividendDate": { - "yahooFinanceType": "date" - }, - "earningsTimestamp": { - "yahooFinanceType": "date" - }, - "earningsTimestampStart": { - "yahooFinanceType": "date" - }, - "earningsTimestampEnd": { - "yahooFinanceType": "date" - }, - "trailingAnnualDividendRate": { - "yahooFinanceType": "number" - }, - "trailingPE": { - "yahooFinanceType": "number" - }, - "trailingAnnualDividendYield": { - "yahooFinanceType": "number" - }, - "epsTrailingTwelveMonths": { - "yahooFinanceType": "number" - }, - "epsForward": { - "yahooFinanceType": "number" - }, - "epsCurrentYear": { - "yahooFinanceType": "number" - }, - "priceEpsCurrentYear": { - "yahooFinanceType": "number" - }, - "sharesOutstanding": { - "yahooFinanceType": "number" - }, - "bookValue": { - "yahooFinanceType": "number" - }, - "fiftyDayAverage": { - "yahooFinanceType": "number" - }, - "fiftyDayAverageChange": { - "yahooFinanceType": "number" - }, - "fiftyDayAverageChangePercent": { - "yahooFinanceType": "number" - }, - "twoHundredDayAverage": { - "yahooFinanceType": "number" - }, - "twoHundredDayAverageChange": { - "yahooFinanceType": "number" - }, - "twoHundredDayAverageChangePercent": { - "yahooFinanceType": "number" - }, - "marketCap": { - "yahooFinanceType": "number" - }, - "forwardPE": { - "yahooFinanceType": "number" - }, - "priceToBook": { - "yahooFinanceType": "number" - }, - "sourceInterval": { - "yahooFinanceType": "number" - }, - "exchangeDataDelayedBy": { - "yahooFinanceType": "number" - }, - "firstTradeDateMilliseconds": { - "yahooFinanceType": "DateInMs" - }, - "priceHint": { - "yahooFinanceType": "number" - }, - "postMarketChangePercent": { - "yahooFinanceType": "number" - }, - "postMarketTime": { - "yahooFinanceType": "date" - }, - "postMarketPrice": { - "yahooFinanceType": "number" - }, - "postMarketChange": { - "yahooFinanceType": "number" - }, - "regularMarketChange": { - "yahooFinanceType": "number" - }, - "regularMarketChangePercent": { - "yahooFinanceType": "number" - }, - "regularMarketTime": { - "yahooFinanceType": "date" - }, - "regularMarketPrice": { - "yahooFinanceType": "number" - }, - "regularMarketDayHigh": { - "yahooFinanceType": "number" - }, - "regularMarketDayRange": { - "yahooFinanceType": "TwoNumberRange" - }, - "regularMarketDayLow": { - "yahooFinanceType": "number" - }, - "regularMarketVolume": { - "yahooFinanceType": "number" - }, - "regularMarketPreviousClose": { - "yahooFinanceType": "number" - }, - "preMarketChange": { - "yahooFinanceType": "number" - }, - "preMarketChangePercent": { - "yahooFinanceType": "number" - }, - "preMarketTime": { - "yahooFinanceType": "date" - }, - "preMarketPrice": { - "yahooFinanceType": "number" - }, - "bid": { - "yahooFinanceType": "number" - }, - "ask": { - "yahooFinanceType": "number" - }, - "bidSize": { - "yahooFinanceType": "number" - }, - "askSize": { - "yahooFinanceType": "number" - }, - "fullExchangeName": { - "type": "string" - }, - "financialCurrency": { - "type": "string" - }, - "regularMarketOpen": { - "yahooFinanceType": "number" - }, - "averageDailyVolume3Month": { - "yahooFinanceType": "number" - }, - "averageDailyVolume10Day": { - "yahooFinanceType": "number" - }, - "displayName": { - "type": "string" - }, - "symbol": { - "type": "string" - }, - "underlyingSymbol": { - "type": "string" - }, - "ytdReturn": { - "yahooFinanceType": "number" - }, - "trailingThreeMonthReturns": { - "yahooFinanceType": "number" - }, - "trailingThreeMonthNavReturns": { - "yahooFinanceType": "number" - }, - "ipoExpectedDate": { - "yahooFinanceType": "date" - }, - "newListingDate": { - "yahooFinanceType": "date" - }, - "nameChangeDate": { - "yahooFinanceType": "date" - }, - "prevName": { - "type": "string" - }, - "averageAnalystRating": { - "type": "string" - }, - "pageViewGrowthWeekly": { - "yahooFinanceType": "number" - }, - "openInterest": { - "yahooFinanceType": "number" - }, - "beta": { - "yahooFinanceType": "number" - } - }, - "required": [ - "language", - "region", - "quoteType", - "triggerable", - "marketState", - "tradeable", - "exchange", - "exchangeTimezoneName", - "exchangeTimezoneShortName", - "gmtOffSetMilliseconds", - "market", - "esgPopulated", - "sourceInterval", - "exchangeDataDelayedBy", - "priceHint", - "fullExchangeName", - "symbol" - ] - }, - "TwoNumberRange": { - "type": "object", - "properties": { - "low": { - "yahooFinanceType": "number" - }, - "high": { - "yahooFinanceType": "number" - } - }, - "required": [ - "low", - "high" - ], - "additionalProperties": false - }, - "QuoteCryptoCurrency": { - "type": "object", - "properties": { - "language": { - "type": "string" - }, - "region": { - "type": "string" - }, - "quoteType": { - "type": "string", - "const": "CRYPTOCURRENCY" - }, - "typeDisp": { - "type": "string" - }, - "quoteSourceName": { - "type": "string" - }, - "triggerable": { - "type": "boolean" - }, - "currency": { - "type": "string" - }, - "customPriceAlertConfidence": { - "type": "string" - }, - "marketState": { - "type": "string", - "enum": [ - "REGULAR", - "CLOSED", - "PRE", - "PREPRE", - "POST", - "POSTPOST" - ] - }, - "tradeable": { - "type": "boolean" - }, - "cryptoTradeable": { - "type": "boolean" - }, - "exchange": { - "type": "string" - }, - "shortName": { - "type": "string" - }, - "longName": { - "type": "string" - }, - "messageBoardId": { - "type": "string" - }, - "exchangeTimezoneName": { - "type": "string" - }, - "exchangeTimezoneShortName": { - "type": "string" - }, - "gmtOffSetMilliseconds": { - "yahooFinanceType": "number" - }, - "market": { - "type": "string" - }, - "esgPopulated": { - "type": "boolean" - }, - "fiftyTwoWeekLowChange": { - "yahooFinanceType": "number" - }, - "fiftyTwoWeekLowChangePercent": { - "yahooFinanceType": "number" - }, - "fiftyTwoWeekRange": { - "yahooFinanceType": "TwoNumberRange" - }, - "fiftyTwoWeekHighChange": { - "yahooFinanceType": "number" - }, - "fiftyTwoWeekHighChangePercent": { - "yahooFinanceType": "number" - }, - "fiftyTwoWeekLow": { - "yahooFinanceType": "number" - }, - "fiftyTwoWeekHigh": { - "yahooFinanceType": "number" - }, - "fiftyTwoWeekChangePercent": { - "yahooFinanceType": "number" - }, - "dividendDate": { - "yahooFinanceType": "date" - }, - "earningsTimestamp": { - "yahooFinanceType": "date" - }, - "earningsTimestampStart": { - "yahooFinanceType": "date" - }, - "earningsTimestampEnd": { - "yahooFinanceType": "date" - }, - "trailingAnnualDividendRate": { - "yahooFinanceType": "number" - }, - "trailingPE": { - "yahooFinanceType": "number" - }, - "trailingAnnualDividendYield": { - "yahooFinanceType": "number" - }, - "epsTrailingTwelveMonths": { - "yahooFinanceType": "number" - }, - "epsForward": { - "yahooFinanceType": "number" - }, - "epsCurrentYear": { - "yahooFinanceType": "number" - }, - "priceEpsCurrentYear": { - "yahooFinanceType": "number" - }, - "sharesOutstanding": { - "yahooFinanceType": "number" - }, - "bookValue": { - "yahooFinanceType": "number" - }, - "fiftyDayAverage": { - "yahooFinanceType": "number" - }, - "fiftyDayAverageChange": { - "yahooFinanceType": "number" - }, - "fiftyDayAverageChangePercent": { - "yahooFinanceType": "number" - }, - "twoHundredDayAverage": { - "yahooFinanceType": "number" - }, - "twoHundredDayAverageChange": { - "yahooFinanceType": "number" - }, - "twoHundredDayAverageChangePercent": { - "yahooFinanceType": "number" - }, - "marketCap": { - "yahooFinanceType": "number" - }, - "forwardPE": { - "yahooFinanceType": "number" - }, - "priceToBook": { - "yahooFinanceType": "number" - }, - "sourceInterval": { - "yahooFinanceType": "number" - }, - "exchangeDataDelayedBy": { - "yahooFinanceType": "number" - }, - "firstTradeDateMilliseconds": { - "yahooFinanceType": "DateInMs" - }, - "priceHint": { - "yahooFinanceType": "number" - }, - "postMarketChangePercent": { - "yahooFinanceType": "number" - }, - "postMarketTime": { - "yahooFinanceType": "date" - }, - "postMarketPrice": { - "yahooFinanceType": "number" - }, - "postMarketChange": { - "yahooFinanceType": "number" - }, - "regularMarketChange": { - "yahooFinanceType": "number" - }, - "regularMarketChangePercent": { - "yahooFinanceType": "number" - }, - "regularMarketTime": { - "yahooFinanceType": "date" - }, - "regularMarketPrice": { - "yahooFinanceType": "number" - }, - "regularMarketDayHigh": { - "yahooFinanceType": "number" - }, - "regularMarketDayRange": { - "yahooFinanceType": "TwoNumberRange" - }, - "regularMarketDayLow": { - "yahooFinanceType": "number" - }, - "regularMarketVolume": { - "yahooFinanceType": "number" - }, - "regularMarketPreviousClose": { - "yahooFinanceType": "number" - }, - "preMarketChange": { - "yahooFinanceType": "number" - }, - "preMarketChangePercent": { - "yahooFinanceType": "number" - }, - "preMarketTime": { - "yahooFinanceType": "date" - }, - "preMarketPrice": { - "yahooFinanceType": "number" - }, - "bid": { - "yahooFinanceType": "number" - }, - "ask": { - "yahooFinanceType": "number" - }, - "bidSize": { - "yahooFinanceType": "number" - }, - "askSize": { - "yahooFinanceType": "number" - }, - "fullExchangeName": { - "type": "string" - }, - "financialCurrency": { - "type": "string" - }, - "regularMarketOpen": { - "yahooFinanceType": "number" - }, - "averageDailyVolume3Month": { - "yahooFinanceType": "number" - }, - "averageDailyVolume10Day": { - "yahooFinanceType": "number" - }, - "displayName": { - "type": "string" - }, - "symbol": { - "type": "string" - }, - "underlyingSymbol": { - "type": "string" - }, - "ytdReturn": { - "yahooFinanceType": "number" - }, - "trailingThreeMonthReturns": { - "yahooFinanceType": "number" - }, - "trailingThreeMonthNavReturns": { - "yahooFinanceType": "number" - }, - "ipoExpectedDate": { - "yahooFinanceType": "date" - }, - "newListingDate": { - "yahooFinanceType": "date" - }, - "nameChangeDate": { - "yahooFinanceType": "date" - }, - "prevName": { - "type": "string" - }, - "averageAnalystRating": { - "type": "string" - }, - "pageViewGrowthWeekly": { - "yahooFinanceType": "number" - }, - "openInterest": { - "yahooFinanceType": "number" - }, - "beta": { - "yahooFinanceType": "number" - }, - "circulatingSupply": { - "yahooFinanceType": "number" - }, - "fromCurrency": { - "type": "string" - }, - "toCurrency": { - "type": "string" - }, - "lastMarket": { - "type": "string" - }, - "coinImageUrl": { - "type": "string" - }, - "volume24Hr": { - "yahooFinanceType": "number" - }, - "volumeAllCurrencies": { - "yahooFinanceType": "number" - }, - "startDate": { - "yahooFinanceType": "date" - } - }, - "required": [ - "circulatingSupply", - "esgPopulated", - "exchange", - "exchangeDataDelayedBy", - "exchangeTimezoneName", - "exchangeTimezoneShortName", - "fromCurrency", - "fullExchangeName", - "gmtOffSetMilliseconds", - "language", - "lastMarket", - "market", - "marketState", - "priceHint", - "quoteType", - "region", - "sourceInterval", - "symbol", - "toCurrency", - "tradeable", - "triggerable" - ] - }, - "QuoteCurrency": { - "type": "object", - "properties": { - "language": { - "type": "string" - }, - "region": { - "type": "string" - }, - "quoteType": { - "type": "string", - "const": "CURRENCY" - }, - "typeDisp": { - "type": "string" - }, - "quoteSourceName": { - "type": "string" - }, - "triggerable": { - "type": "boolean" - }, - "currency": { - "type": "string" - }, - "customPriceAlertConfidence": { - "type": "string" - }, - "marketState": { - "type": "string", - "enum": [ - "REGULAR", - "CLOSED", - "PRE", - "PREPRE", - "POST", - "POSTPOST" - ] - }, - "tradeable": { - "type": "boolean" - }, - "cryptoTradeable": { - "type": "boolean" - }, - "exchange": { - "type": "string" - }, - "shortName": { - "type": "string" - }, - "longName": { - "type": "string" - }, - "messageBoardId": { - "type": "string" - }, - "exchangeTimezoneName": { - "type": "string" - }, - "exchangeTimezoneShortName": { - "type": "string" - }, - "gmtOffSetMilliseconds": { - "yahooFinanceType": "number" - }, - "market": { - "type": "string" - }, - "esgPopulated": { - "type": "boolean" - }, - "fiftyTwoWeekLowChange": { - "yahooFinanceType": "number" - }, - "fiftyTwoWeekLowChangePercent": { - "yahooFinanceType": "number" - }, - "fiftyTwoWeekRange": { - "yahooFinanceType": "TwoNumberRange" - }, - "fiftyTwoWeekHighChange": { - "yahooFinanceType": "number" - }, - "fiftyTwoWeekHighChangePercent": { - "yahooFinanceType": "number" - }, - "fiftyTwoWeekLow": { - "yahooFinanceType": "number" - }, - "fiftyTwoWeekHigh": { - "yahooFinanceType": "number" - }, - "fiftyTwoWeekChangePercent": { - "yahooFinanceType": "number" - }, - "dividendDate": { - "yahooFinanceType": "date" - }, - "earningsTimestamp": { - "yahooFinanceType": "date" - }, - "earningsTimestampStart": { - "yahooFinanceType": "date" - }, - "earningsTimestampEnd": { - "yahooFinanceType": "date" - }, - "trailingAnnualDividendRate": { - "yahooFinanceType": "number" - }, - "trailingPE": { - "yahooFinanceType": "number" - }, - "trailingAnnualDividendYield": { - "yahooFinanceType": "number" - }, - "epsTrailingTwelveMonths": { - "yahooFinanceType": "number" - }, - "epsForward": { - "yahooFinanceType": "number" - }, - "epsCurrentYear": { - "yahooFinanceType": "number" - }, - "priceEpsCurrentYear": { - "yahooFinanceType": "number" - }, - "sharesOutstanding": { - "yahooFinanceType": "number" - }, - "bookValue": { - "yahooFinanceType": "number" - }, - "fiftyDayAverage": { - "yahooFinanceType": "number" - }, - "fiftyDayAverageChange": { - "yahooFinanceType": "number" - }, - "fiftyDayAverageChangePercent": { - "yahooFinanceType": "number" - }, - "twoHundredDayAverage": { - "yahooFinanceType": "number" - }, - "twoHundredDayAverageChange": { - "yahooFinanceType": "number" - }, - "twoHundredDayAverageChangePercent": { - "yahooFinanceType": "number" - }, - "marketCap": { - "yahooFinanceType": "number" - }, - "forwardPE": { - "yahooFinanceType": "number" - }, - "priceToBook": { - "yahooFinanceType": "number" - }, - "sourceInterval": { - "yahooFinanceType": "number" - }, - "exchangeDataDelayedBy": { - "yahooFinanceType": "number" - }, - "firstTradeDateMilliseconds": { - "yahooFinanceType": "DateInMs" - }, - "priceHint": { - "yahooFinanceType": "number" - }, - "postMarketChangePercent": { - "yahooFinanceType": "number" - }, - "postMarketTime": { - "yahooFinanceType": "date" - }, - "postMarketPrice": { - "yahooFinanceType": "number" - }, - "postMarketChange": { - "yahooFinanceType": "number" - }, - "regularMarketChange": { - "yahooFinanceType": "number" - }, - "regularMarketChangePercent": { - "yahooFinanceType": "number" - }, - "regularMarketTime": { - "yahooFinanceType": "date" - }, - "regularMarketPrice": { - "yahooFinanceType": "number" - }, - "regularMarketDayHigh": { - "yahooFinanceType": "number" - }, - "regularMarketDayRange": { - "yahooFinanceType": "TwoNumberRange" - }, - "regularMarketDayLow": { - "yahooFinanceType": "number" - }, - "regularMarketVolume": { - "yahooFinanceType": "number" - }, - "regularMarketPreviousClose": { - "yahooFinanceType": "number" - }, - "preMarketChange": { - "yahooFinanceType": "number" - }, - "preMarketChangePercent": { - "yahooFinanceType": "number" - }, - "preMarketTime": { - "yahooFinanceType": "date" - }, - "preMarketPrice": { - "yahooFinanceType": "number" - }, - "bid": { - "yahooFinanceType": "number" - }, - "ask": { - "yahooFinanceType": "number" - }, - "bidSize": { - "yahooFinanceType": "number" - }, - "askSize": { - "yahooFinanceType": "number" - }, - "fullExchangeName": { - "type": "string" - }, - "financialCurrency": { - "type": "string" - }, - "regularMarketOpen": { - "yahooFinanceType": "number" - }, - "averageDailyVolume3Month": { - "yahooFinanceType": "number" - }, - "averageDailyVolume10Day": { - "yahooFinanceType": "number" - }, - "displayName": { - "type": "string" - }, - "symbol": { - "type": "string" - }, - "underlyingSymbol": { - "type": "string" - }, - "ytdReturn": { - "yahooFinanceType": "number" - }, - "trailingThreeMonthReturns": { - "yahooFinanceType": "number" - }, - "trailingThreeMonthNavReturns": { - "yahooFinanceType": "number" - }, - "ipoExpectedDate": { - "yahooFinanceType": "date" - }, - "newListingDate": { - "yahooFinanceType": "date" - }, - "nameChangeDate": { - "yahooFinanceType": "date" - }, - "prevName": { - "type": "string" - }, - "averageAnalystRating": { - "type": "string" - }, - "pageViewGrowthWeekly": { - "yahooFinanceType": "number" - }, - "openInterest": { - "yahooFinanceType": "number" - }, - "beta": { - "yahooFinanceType": "number" - } - }, - "required": [ - "esgPopulated", - "exchange", - "exchangeDataDelayedBy", - "exchangeTimezoneName", - "exchangeTimezoneShortName", - "fullExchangeName", - "gmtOffSetMilliseconds", - "language", - "market", - "marketState", - "priceHint", - "quoteType", - "region", - "sourceInterval", - "symbol", - "tradeable", - "triggerable" - ] - }, - "QuoteEtf": { - "type": "object", - "properties": { - "language": { - "type": "string" - }, - "region": { - "type": "string" - }, - "quoteType": { - "type": "string", - "const": "ETF" - }, - "typeDisp": { - "type": "string" - }, - "quoteSourceName": { - "type": "string" - }, - "triggerable": { - "type": "boolean" - }, - "currency": { - "type": "string" - }, - "customPriceAlertConfidence": { - "type": "string" - }, - "marketState": { - "type": "string", - "enum": [ - "REGULAR", - "CLOSED", - "PRE", - "PREPRE", - "POST", - "POSTPOST" - ] - }, - "tradeable": { - "type": "boolean" - }, - "cryptoTradeable": { - "type": "boolean" - }, - "exchange": { - "type": "string" - }, - "shortName": { - "type": "string" - }, - "longName": { - "type": "string" - }, - "messageBoardId": { - "type": "string" - }, - "exchangeTimezoneName": { - "type": "string" - }, - "exchangeTimezoneShortName": { - "type": "string" - }, - "gmtOffSetMilliseconds": { - "yahooFinanceType": "number" - }, - "market": { - "type": "string" - }, - "esgPopulated": { - "type": "boolean" - }, - "fiftyTwoWeekLowChange": { - "yahooFinanceType": "number" - }, - "fiftyTwoWeekLowChangePercent": { - "yahooFinanceType": "number" - }, - "fiftyTwoWeekRange": { - "yahooFinanceType": "TwoNumberRange" - }, - "fiftyTwoWeekHighChange": { - "yahooFinanceType": "number" - }, - "fiftyTwoWeekHighChangePercent": { - "yahooFinanceType": "number" - }, - "fiftyTwoWeekLow": { - "yahooFinanceType": "number" - }, - "fiftyTwoWeekHigh": { - "yahooFinanceType": "number" - }, - "fiftyTwoWeekChangePercent": { - "yahooFinanceType": "number" - }, - "dividendDate": { - "yahooFinanceType": "date" - }, - "earningsTimestamp": { - "yahooFinanceType": "date" - }, - "earningsTimestampStart": { - "yahooFinanceType": "date" - }, - "earningsTimestampEnd": { - "yahooFinanceType": "date" - }, - "trailingAnnualDividendRate": { - "yahooFinanceType": "number" - }, - "trailingPE": { - "yahooFinanceType": "number" - }, - "trailingAnnualDividendYield": { - "yahooFinanceType": "number" - }, - "epsTrailingTwelveMonths": { - "yahooFinanceType": "number" - }, - "epsForward": { - "yahooFinanceType": "number" - }, - "epsCurrentYear": { - "yahooFinanceType": "number" - }, - "priceEpsCurrentYear": { - "yahooFinanceType": "number" - }, - "sharesOutstanding": { - "yahooFinanceType": "number" - }, - "bookValue": { - "yahooFinanceType": "number" - }, - "fiftyDayAverage": { - "yahooFinanceType": "number" - }, - "fiftyDayAverageChange": { - "yahooFinanceType": "number" - }, - "fiftyDayAverageChangePercent": { - "yahooFinanceType": "number" - }, - "twoHundredDayAverage": { - "yahooFinanceType": "number" - }, - "twoHundredDayAverageChange": { - "yahooFinanceType": "number" - }, - "twoHundredDayAverageChangePercent": { - "yahooFinanceType": "number" - }, - "marketCap": { - "yahooFinanceType": "number" - }, - "forwardPE": { - "yahooFinanceType": "number" - }, - "priceToBook": { - "yahooFinanceType": "number" - }, - "sourceInterval": { - "yahooFinanceType": "number" - }, - "exchangeDataDelayedBy": { - "yahooFinanceType": "number" - }, - "firstTradeDateMilliseconds": { - "yahooFinanceType": "DateInMs" - }, - "priceHint": { - "yahooFinanceType": "number" - }, - "postMarketChangePercent": { - "yahooFinanceType": "number" - }, - "postMarketTime": { - "yahooFinanceType": "date" - }, - "postMarketPrice": { - "yahooFinanceType": "number" - }, - "postMarketChange": { - "yahooFinanceType": "number" - }, - "regularMarketChange": { - "yahooFinanceType": "number" - }, - "regularMarketChangePercent": { - "yahooFinanceType": "number" - }, - "regularMarketTime": { - "yahooFinanceType": "date" - }, - "regularMarketPrice": { - "yahooFinanceType": "number" - }, - "regularMarketDayHigh": { - "yahooFinanceType": "number" - }, - "regularMarketDayRange": { - "yahooFinanceType": "TwoNumberRange" - }, - "regularMarketDayLow": { - "yahooFinanceType": "number" - }, - "regularMarketVolume": { - "yahooFinanceType": "number" - }, - "regularMarketPreviousClose": { - "yahooFinanceType": "number" - }, - "preMarketChange": { - "yahooFinanceType": "number" - }, - "preMarketChangePercent": { - "yahooFinanceType": "number" - }, - "preMarketTime": { - "yahooFinanceType": "date" - }, - "preMarketPrice": { - "yahooFinanceType": "number" - }, - "bid": { - "yahooFinanceType": "number" - }, - "ask": { - "yahooFinanceType": "number" - }, - "bidSize": { - "yahooFinanceType": "number" - }, - "askSize": { - "yahooFinanceType": "number" - }, - "fullExchangeName": { - "type": "string" - }, - "financialCurrency": { - "type": "string" - }, - "regularMarketOpen": { - "yahooFinanceType": "number" - }, - "averageDailyVolume3Month": { - "yahooFinanceType": "number" - }, - "averageDailyVolume10Day": { - "yahooFinanceType": "number" - }, - "displayName": { - "type": "string" - }, - "symbol": { - "type": "string" - }, - "underlyingSymbol": { - "type": "string" - }, - "ytdReturn": { - "yahooFinanceType": "number" - }, - "trailingThreeMonthReturns": { - "yahooFinanceType": "number" - }, - "trailingThreeMonthNavReturns": { - "yahooFinanceType": "number" - }, - "ipoExpectedDate": { - "yahooFinanceType": "date" - }, - "newListingDate": { - "yahooFinanceType": "date" - }, - "nameChangeDate": { - "yahooFinanceType": "date" - }, - "prevName": { - "type": "string" - }, - "averageAnalystRating": { - "type": "string" - }, - "pageViewGrowthWeekly": { - "yahooFinanceType": "number" - }, - "openInterest": { - "yahooFinanceType": "number" - }, - "beta": { - "yahooFinanceType": "number" - } - }, - "required": [ - "esgPopulated", - "exchange", - "exchangeDataDelayedBy", - "exchangeTimezoneName", - "exchangeTimezoneShortName", - "fullExchangeName", - "gmtOffSetMilliseconds", - "language", - "market", - "marketState", - "priceHint", - "quoteType", - "region", - "sourceInterval", - "symbol", - "tradeable", - "triggerable" - ] - }, - "QuoteEquity": { - "type": "object", - "properties": { - "language": { - "type": "string" - }, - "region": { - "type": "string" - }, - "quoteType": { - "type": "string", - "const": "EQUITY" - }, - "typeDisp": { - "type": "string" - }, - "quoteSourceName": { - "type": "string" - }, - "triggerable": { - "type": "boolean" - }, - "currency": { - "type": "string" - }, - "customPriceAlertConfidence": { - "type": "string" - }, - "marketState": { - "type": "string", - "enum": [ - "REGULAR", - "CLOSED", - "PRE", - "PREPRE", - "POST", - "POSTPOST" - ] - }, - "tradeable": { - "type": "boolean" - }, - "cryptoTradeable": { - "type": "boolean" - }, - "exchange": { - "type": "string" - }, - "shortName": { - "type": "string" - }, - "longName": { - "type": "string" - }, - "messageBoardId": { - "type": "string" - }, - "exchangeTimezoneName": { - "type": "string" - }, - "exchangeTimezoneShortName": { - "type": "string" - }, - "gmtOffSetMilliseconds": { - "yahooFinanceType": "number" - }, - "market": { - "type": "string" - }, - "esgPopulated": { - "type": "boolean" - }, - "fiftyTwoWeekLowChange": { - "yahooFinanceType": "number" - }, - "fiftyTwoWeekLowChangePercent": { - "yahooFinanceType": "number" - }, - "fiftyTwoWeekRange": { - "yahooFinanceType": "TwoNumberRange" - }, - "fiftyTwoWeekHighChange": { - "yahooFinanceType": "number" - }, - "fiftyTwoWeekHighChangePercent": { - "yahooFinanceType": "number" - }, - "fiftyTwoWeekLow": { - "yahooFinanceType": "number" - }, - "fiftyTwoWeekHigh": { - "yahooFinanceType": "number" - }, - "fiftyTwoWeekChangePercent": { - "yahooFinanceType": "number" - }, - "dividendDate": { - "yahooFinanceType": "date" - }, - "earningsTimestamp": { - "yahooFinanceType": "date" - }, - "earningsTimestampStart": { - "yahooFinanceType": "date" - }, - "earningsTimestampEnd": { - "yahooFinanceType": "date" - }, - "trailingAnnualDividendRate": { - "yahooFinanceType": "number" - }, - "trailingPE": { - "yahooFinanceType": "number" - }, - "trailingAnnualDividendYield": { - "yahooFinanceType": "number" - }, - "epsTrailingTwelveMonths": { - "yahooFinanceType": "number" - }, - "epsForward": { - "yahooFinanceType": "number" - }, - "epsCurrentYear": { - "yahooFinanceType": "number" - }, - "priceEpsCurrentYear": { - "yahooFinanceType": "number" - }, - "sharesOutstanding": { - "yahooFinanceType": "number" - }, - "bookValue": { - "yahooFinanceType": "number" - }, - "fiftyDayAverage": { - "yahooFinanceType": "number" - }, - "fiftyDayAverageChange": { - "yahooFinanceType": "number" - }, - "fiftyDayAverageChangePercent": { - "yahooFinanceType": "number" - }, - "twoHundredDayAverage": { - "yahooFinanceType": "number" - }, - "twoHundredDayAverageChange": { - "yahooFinanceType": "number" - }, - "twoHundredDayAverageChangePercent": { - "yahooFinanceType": "number" - }, - "marketCap": { - "yahooFinanceType": "number" - }, - "forwardPE": { - "yahooFinanceType": "number" - }, - "priceToBook": { - "yahooFinanceType": "number" - }, - "sourceInterval": { - "yahooFinanceType": "number" - }, - "exchangeDataDelayedBy": { - "yahooFinanceType": "number" - }, - "firstTradeDateMilliseconds": { - "yahooFinanceType": "DateInMs" - }, - "priceHint": { - "yahooFinanceType": "number" - }, - "postMarketChangePercent": { - "yahooFinanceType": "number" - }, - "postMarketTime": { - "yahooFinanceType": "date" - }, - "postMarketPrice": { - "yahooFinanceType": "number" - }, - "postMarketChange": { - "yahooFinanceType": "number" - }, - "regularMarketChange": { - "yahooFinanceType": "number" - }, - "regularMarketChangePercent": { - "yahooFinanceType": "number" - }, - "regularMarketTime": { - "yahooFinanceType": "date" - }, - "regularMarketPrice": { - "yahooFinanceType": "number" - }, - "regularMarketDayHigh": { - "yahooFinanceType": "number" - }, - "regularMarketDayRange": { - "yahooFinanceType": "TwoNumberRange" - }, - "regularMarketDayLow": { - "yahooFinanceType": "number" - }, - "regularMarketVolume": { - "yahooFinanceType": "number" - }, - "regularMarketPreviousClose": { - "yahooFinanceType": "number" - }, - "preMarketChange": { - "yahooFinanceType": "number" - }, - "preMarketChangePercent": { - "yahooFinanceType": "number" - }, - "preMarketTime": { - "yahooFinanceType": "date" - }, - "preMarketPrice": { - "yahooFinanceType": "number" - }, - "bid": { - "yahooFinanceType": "number" - }, - "ask": { - "yahooFinanceType": "number" - }, - "bidSize": { - "yahooFinanceType": "number" - }, - "askSize": { - "yahooFinanceType": "number" - }, - "fullExchangeName": { - "type": "string" - }, - "financialCurrency": { - "type": "string" - }, - "regularMarketOpen": { - "yahooFinanceType": "number" - }, - "averageDailyVolume3Month": { - "yahooFinanceType": "number" - }, - "averageDailyVolume10Day": { - "yahooFinanceType": "number" - }, - "displayName": { - "type": "string" - }, - "symbol": { - "type": "string" - }, - "underlyingSymbol": { - "type": "string" - }, - "ytdReturn": { - "yahooFinanceType": "number" - }, - "trailingThreeMonthReturns": { - "yahooFinanceType": "number" - }, - "trailingThreeMonthNavReturns": { - "yahooFinanceType": "number" - }, - "ipoExpectedDate": { - "yahooFinanceType": "date" - }, - "newListingDate": { - "yahooFinanceType": "date" - }, - "nameChangeDate": { - "yahooFinanceType": "date" - }, - "prevName": { - "type": "string" - }, - "averageAnalystRating": { - "type": "string" - }, - "pageViewGrowthWeekly": { - "yahooFinanceType": "number" - }, - "openInterest": { - "yahooFinanceType": "number" - }, - "beta": { - "yahooFinanceType": "number" - }, - "dividendRate": { - "yahooFinanceType": "number" - }, - "dividendYield": { - "yahooFinanceType": "number" - } - }, - "required": [ - "esgPopulated", - "exchange", - "exchangeDataDelayedBy", - "exchangeTimezoneName", - "exchangeTimezoneShortName", - "fullExchangeName", - "gmtOffSetMilliseconds", - "language", - "market", - "marketState", - "priceHint", - "quoteType", - "region", - "sourceInterval", - "symbol", - "tradeable", - "triggerable" - ] - }, - "QuoteFuture": { - "type": "object", - "properties": { - "language": { - "type": "string" - }, - "region": { - "type": "string" - }, - "quoteType": { - "type": "string", - "const": "FUTURE" - }, - "typeDisp": { - "type": "string" - }, - "quoteSourceName": { - "type": "string" - }, - "triggerable": { - "type": "boolean" - }, - "currency": { - "type": "string" - }, - "customPriceAlertConfidence": { - "type": "string" - }, - "marketState": { - "type": "string", - "enum": [ - "REGULAR", - "CLOSED", - "PRE", - "PREPRE", - "POST", - "POSTPOST" - ] - }, - "tradeable": { - "type": "boolean" - }, - "cryptoTradeable": { - "type": "boolean" - }, - "exchange": { - "type": "string" - }, - "shortName": { - "type": "string" - }, - "longName": { - "type": "string" - }, - "messageBoardId": { - "type": "string" - }, - "exchangeTimezoneName": { - "type": "string" - }, - "exchangeTimezoneShortName": { - "type": "string" - }, - "gmtOffSetMilliseconds": { - "yahooFinanceType": "number" - }, - "market": { - "type": "string" - }, - "esgPopulated": { - "type": "boolean" - }, - "fiftyTwoWeekLowChange": { - "yahooFinanceType": "number" - }, - "fiftyTwoWeekLowChangePercent": { - "yahooFinanceType": "number" - }, - "fiftyTwoWeekRange": { - "yahooFinanceType": "TwoNumberRange" - }, - "fiftyTwoWeekHighChange": { - "yahooFinanceType": "number" - }, - "fiftyTwoWeekHighChangePercent": { - "yahooFinanceType": "number" - }, - "fiftyTwoWeekLow": { - "yahooFinanceType": "number" - }, - "fiftyTwoWeekHigh": { - "yahooFinanceType": "number" - }, - "fiftyTwoWeekChangePercent": { - "yahooFinanceType": "number" - }, - "dividendDate": { - "yahooFinanceType": "date" - }, - "earningsTimestamp": { - "yahooFinanceType": "date" - }, - "earningsTimestampStart": { - "yahooFinanceType": "date" - }, - "earningsTimestampEnd": { - "yahooFinanceType": "date" - }, - "trailingAnnualDividendRate": { - "yahooFinanceType": "number" - }, - "trailingPE": { - "yahooFinanceType": "number" - }, - "trailingAnnualDividendYield": { - "yahooFinanceType": "number" - }, - "epsTrailingTwelveMonths": { - "yahooFinanceType": "number" - }, - "epsForward": { - "yahooFinanceType": "number" - }, - "epsCurrentYear": { - "yahooFinanceType": "number" - }, - "priceEpsCurrentYear": { - "yahooFinanceType": "number" - }, - "sharesOutstanding": { - "yahooFinanceType": "number" - }, - "bookValue": { - "yahooFinanceType": "number" - }, - "fiftyDayAverage": { - "yahooFinanceType": "number" - }, - "fiftyDayAverageChange": { - "yahooFinanceType": "number" - }, - "fiftyDayAverageChangePercent": { - "yahooFinanceType": "number" - }, - "twoHundredDayAverage": { - "yahooFinanceType": "number" - }, - "twoHundredDayAverageChange": { - "yahooFinanceType": "number" - }, - "twoHundredDayAverageChangePercent": { - "yahooFinanceType": "number" - }, - "marketCap": { - "yahooFinanceType": "number" - }, - "forwardPE": { - "yahooFinanceType": "number" - }, - "priceToBook": { - "yahooFinanceType": "number" - }, - "sourceInterval": { - "yahooFinanceType": "number" - }, - "exchangeDataDelayedBy": { - "yahooFinanceType": "number" - }, - "firstTradeDateMilliseconds": { - "yahooFinanceType": "DateInMs" - }, - "priceHint": { - "yahooFinanceType": "number" - }, - "postMarketChangePercent": { - "yahooFinanceType": "number" - }, - "postMarketTime": { - "yahooFinanceType": "date" - }, - "postMarketPrice": { - "yahooFinanceType": "number" - }, - "postMarketChange": { - "yahooFinanceType": "number" - }, - "regularMarketChange": { - "yahooFinanceType": "number" - }, - "regularMarketChangePercent": { - "yahooFinanceType": "number" - }, - "regularMarketTime": { - "yahooFinanceType": "date" - }, - "regularMarketPrice": { - "yahooFinanceType": "number" - }, - "regularMarketDayHigh": { - "yahooFinanceType": "number" - }, - "regularMarketDayRange": { - "yahooFinanceType": "TwoNumberRange" - }, - "regularMarketDayLow": { - "yahooFinanceType": "number" - }, - "regularMarketVolume": { - "yahooFinanceType": "number" - }, - "regularMarketPreviousClose": { - "yahooFinanceType": "number" - }, - "preMarketChange": { - "yahooFinanceType": "number" - }, - "preMarketChangePercent": { - "yahooFinanceType": "number" - }, - "preMarketTime": { - "yahooFinanceType": "date" - }, - "preMarketPrice": { - "yahooFinanceType": "number" - }, - "bid": { - "yahooFinanceType": "number" - }, - "ask": { - "yahooFinanceType": "number" - }, - "bidSize": { - "yahooFinanceType": "number" - }, - "askSize": { - "yahooFinanceType": "number" - }, - "fullExchangeName": { - "type": "string" - }, - "financialCurrency": { - "type": "string" - }, - "regularMarketOpen": { - "yahooFinanceType": "number" - }, - "averageDailyVolume3Month": { - "yahooFinanceType": "number" - }, - "averageDailyVolume10Day": { - "yahooFinanceType": "number" - }, - "displayName": { - "type": "string" - }, - "symbol": { - "type": "string" - }, - "underlyingSymbol": { - "type": "string" - }, - "ytdReturn": { - "yahooFinanceType": "number" - }, - "trailingThreeMonthReturns": { - "yahooFinanceType": "number" - }, - "trailingThreeMonthNavReturns": { - "yahooFinanceType": "number" - }, - "ipoExpectedDate": { - "yahooFinanceType": "date" - }, - "newListingDate": { - "yahooFinanceType": "date" - }, - "nameChangeDate": { - "yahooFinanceType": "date" - }, - "prevName": { - "type": "string" - }, - "averageAnalystRating": { - "type": "string" - }, - "pageViewGrowthWeekly": { - "yahooFinanceType": "number" - }, - "openInterest": { - "yahooFinanceType": "number" - }, - "beta": { - "yahooFinanceType": "number" - }, - "headSymbolAsString": { - "type": "string" - }, - "contractSymbol": { - "type": "boolean" - }, - "underlyingExchangeSymbol": { - "type": "string" - }, - "expireDate": { - "yahooFinanceType": "date" - }, - "expireIsoDate": { - "yahooFinanceType": "number" - } - }, - "required": [ - "contractSymbol", - "esgPopulated", - "exchange", - "exchangeDataDelayedBy", - "exchangeTimezoneName", - "exchangeTimezoneShortName", - "expireDate", - "expireIsoDate", - "fullExchangeName", - "gmtOffSetMilliseconds", - "headSymbolAsString", - "language", - "market", - "marketState", - "priceHint", - "quoteType", - "region", - "sourceInterval", - "symbol", - "tradeable", - "triggerable", - "underlyingExchangeSymbol" - ] - }, - "QuoteIndex": { - "type": "object", - "properties": { - "language": { - "type": "string" - }, - "region": { - "type": "string" - }, - "quoteType": { - "type": "string", - "const": "INDEX" - }, - "typeDisp": { - "type": "string" - }, - "quoteSourceName": { - "type": "string" - }, - "triggerable": { - "type": "boolean" - }, - "currency": { - "type": "string" - }, - "customPriceAlertConfidence": { - "type": "string" - }, - "marketState": { - "type": "string", - "enum": [ - "REGULAR", - "CLOSED", - "PRE", - "PREPRE", - "POST", - "POSTPOST" - ] - }, - "tradeable": { - "type": "boolean" - }, - "cryptoTradeable": { - "type": "boolean" - }, - "exchange": { - "type": "string" - }, - "shortName": { - "type": "string" - }, - "longName": { - "type": "string" - }, - "messageBoardId": { - "type": "string" - }, - "exchangeTimezoneName": { - "type": "string" - }, - "exchangeTimezoneShortName": { - "type": "string" - }, - "gmtOffSetMilliseconds": { - "yahooFinanceType": "number" - }, - "market": { - "type": "string" - }, - "esgPopulated": { - "type": "boolean" - }, - "fiftyTwoWeekLowChange": { - "yahooFinanceType": "number" - }, - "fiftyTwoWeekLowChangePercent": { - "yahooFinanceType": "number" - }, - "fiftyTwoWeekRange": { - "yahooFinanceType": "TwoNumberRange" - }, - "fiftyTwoWeekHighChange": { - "yahooFinanceType": "number" - }, - "fiftyTwoWeekHighChangePercent": { - "yahooFinanceType": "number" - }, - "fiftyTwoWeekLow": { - "yahooFinanceType": "number" - }, - "fiftyTwoWeekHigh": { - "yahooFinanceType": "number" - }, - "fiftyTwoWeekChangePercent": { - "yahooFinanceType": "number" - }, - "dividendDate": { - "yahooFinanceType": "date" - }, - "earningsTimestamp": { - "yahooFinanceType": "date" - }, - "earningsTimestampStart": { - "yahooFinanceType": "date" - }, - "earningsTimestampEnd": { - "yahooFinanceType": "date" - }, - "trailingAnnualDividendRate": { - "yahooFinanceType": "number" - }, - "trailingPE": { - "yahooFinanceType": "number" - }, - "trailingAnnualDividendYield": { - "yahooFinanceType": "number" - }, - "epsTrailingTwelveMonths": { - "yahooFinanceType": "number" - }, - "epsForward": { - "yahooFinanceType": "number" - }, - "epsCurrentYear": { - "yahooFinanceType": "number" - }, - "priceEpsCurrentYear": { - "yahooFinanceType": "number" - }, - "sharesOutstanding": { - "yahooFinanceType": "number" - }, - "bookValue": { - "yahooFinanceType": "number" - }, - "fiftyDayAverage": { - "yahooFinanceType": "number" - }, - "fiftyDayAverageChange": { - "yahooFinanceType": "number" - }, - "fiftyDayAverageChangePercent": { - "yahooFinanceType": "number" - }, - "twoHundredDayAverage": { - "yahooFinanceType": "number" - }, - "twoHundredDayAverageChange": { - "yahooFinanceType": "number" - }, - "twoHundredDayAverageChangePercent": { - "yahooFinanceType": "number" - }, - "marketCap": { - "yahooFinanceType": "number" - }, - "forwardPE": { - "yahooFinanceType": "number" - }, - "priceToBook": { - "yahooFinanceType": "number" - }, - "sourceInterval": { - "yahooFinanceType": "number" - }, - "exchangeDataDelayedBy": { - "yahooFinanceType": "number" - }, - "firstTradeDateMilliseconds": { - "yahooFinanceType": "DateInMs" - }, - "priceHint": { - "yahooFinanceType": "number" - }, - "postMarketChangePercent": { - "yahooFinanceType": "number" - }, - "postMarketTime": { - "yahooFinanceType": "date" - }, - "postMarketPrice": { - "yahooFinanceType": "number" - }, - "postMarketChange": { - "yahooFinanceType": "number" - }, - "regularMarketChange": { - "yahooFinanceType": "number" - }, - "regularMarketChangePercent": { - "yahooFinanceType": "number" - }, - "regularMarketTime": { - "yahooFinanceType": "date" - }, - "regularMarketPrice": { - "yahooFinanceType": "number" - }, - "regularMarketDayHigh": { - "yahooFinanceType": "number" - }, - "regularMarketDayRange": { - "yahooFinanceType": "TwoNumberRange" - }, - "regularMarketDayLow": { - "yahooFinanceType": "number" - }, - "regularMarketVolume": { - "yahooFinanceType": "number" - }, - "regularMarketPreviousClose": { - "yahooFinanceType": "number" - }, - "preMarketChange": { - "yahooFinanceType": "number" - }, - "preMarketChangePercent": { - "yahooFinanceType": "number" - }, - "preMarketTime": { - "yahooFinanceType": "date" - }, - "preMarketPrice": { - "yahooFinanceType": "number" - }, - "bid": { - "yahooFinanceType": "number" - }, - "ask": { - "yahooFinanceType": "number" - }, - "bidSize": { - "yahooFinanceType": "number" - }, - "askSize": { - "yahooFinanceType": "number" - }, - "fullExchangeName": { - "type": "string" - }, - "financialCurrency": { - "type": "string" - }, - "regularMarketOpen": { - "yahooFinanceType": "number" - }, - "averageDailyVolume3Month": { - "yahooFinanceType": "number" - }, - "averageDailyVolume10Day": { - "yahooFinanceType": "number" - }, - "displayName": { - "type": "string" - }, - "symbol": { - "type": "string" - }, - "underlyingSymbol": { - "type": "string" - }, - "ytdReturn": { - "yahooFinanceType": "number" - }, - "trailingThreeMonthReturns": { - "yahooFinanceType": "number" - }, - "trailingThreeMonthNavReturns": { - "yahooFinanceType": "number" - }, - "ipoExpectedDate": { - "yahooFinanceType": "date" - }, - "newListingDate": { - "yahooFinanceType": "date" - }, - "nameChangeDate": { - "yahooFinanceType": "date" - }, - "prevName": { - "type": "string" - }, - "averageAnalystRating": { - "type": "string" - }, - "pageViewGrowthWeekly": { - "yahooFinanceType": "number" - }, - "openInterest": { - "yahooFinanceType": "number" - }, - "beta": { - "yahooFinanceType": "number" - } - }, - "required": [ - "esgPopulated", - "exchange", - "exchangeDataDelayedBy", - "exchangeTimezoneName", - "exchangeTimezoneShortName", - "fullExchangeName", - "gmtOffSetMilliseconds", - "language", - "market", - "marketState", - "priceHint", - "quoteType", - "region", - "sourceInterval", - "symbol", - "tradeable", - "triggerable" - ] - }, - "QuoteOption": { - "type": "object", - "properties": { - "language": { - "type": "string" - }, - "region": { - "type": "string" - }, - "quoteType": { - "type": "string", - "const": "OPTION" - }, - "typeDisp": { - "type": "string" - }, - "quoteSourceName": { - "type": "string" - }, - "triggerable": { - "type": "boolean" - }, - "currency": { - "type": "string" - }, - "customPriceAlertConfidence": { - "type": "string" - }, - "marketState": { - "type": "string", - "enum": [ - "REGULAR", - "CLOSED", - "PRE", - "PREPRE", - "POST", - "POSTPOST" - ] - }, - "tradeable": { - "type": "boolean" - }, - "cryptoTradeable": { - "type": "boolean" - }, - "exchange": { - "type": "string" - }, - "shortName": { - "type": "string" - }, - "longName": { - "type": "string" - }, - "messageBoardId": { - "type": "string" - }, - "exchangeTimezoneName": { - "type": "string" - }, - "exchangeTimezoneShortName": { - "type": "string" - }, - "gmtOffSetMilliseconds": { - "yahooFinanceType": "number" - }, - "market": { - "type": "string" - }, - "esgPopulated": { - "type": "boolean" - }, - "fiftyTwoWeekLowChange": { - "yahooFinanceType": "number" - }, - "fiftyTwoWeekLowChangePercent": { - "yahooFinanceType": "number" - }, - "fiftyTwoWeekRange": { - "yahooFinanceType": "TwoNumberRange" - }, - "fiftyTwoWeekHighChange": { - "yahooFinanceType": "number" - }, - "fiftyTwoWeekHighChangePercent": { - "yahooFinanceType": "number" - }, - "fiftyTwoWeekLow": { - "yahooFinanceType": "number" - }, - "fiftyTwoWeekHigh": { - "yahooFinanceType": "number" - }, - "fiftyTwoWeekChangePercent": { - "yahooFinanceType": "number" - }, - "dividendDate": { - "yahooFinanceType": "date" - }, - "earningsTimestamp": { - "yahooFinanceType": "date" - }, - "earningsTimestampStart": { - "yahooFinanceType": "date" - }, - "earningsTimestampEnd": { - "yahooFinanceType": "date" - }, - "trailingAnnualDividendRate": { - "yahooFinanceType": "number" - }, - "trailingPE": { - "yahooFinanceType": "number" - }, - "trailingAnnualDividendYield": { - "yahooFinanceType": "number" - }, - "epsTrailingTwelveMonths": { - "yahooFinanceType": "number" - }, - "epsForward": { - "yahooFinanceType": "number" - }, - "epsCurrentYear": { - "yahooFinanceType": "number" - }, - "priceEpsCurrentYear": { - "yahooFinanceType": "number" - }, - "sharesOutstanding": { - "yahooFinanceType": "number" - }, - "bookValue": { - "yahooFinanceType": "number" - }, - "fiftyDayAverage": { - "yahooFinanceType": "number" - }, - "fiftyDayAverageChange": { - "yahooFinanceType": "number" - }, - "fiftyDayAverageChangePercent": { - "yahooFinanceType": "number" - }, - "twoHundredDayAverage": { - "yahooFinanceType": "number" - }, - "twoHundredDayAverageChange": { - "yahooFinanceType": "number" - }, - "twoHundredDayAverageChangePercent": { - "yahooFinanceType": "number" - }, - "marketCap": { - "yahooFinanceType": "number" - }, - "forwardPE": { - "yahooFinanceType": "number" - }, - "priceToBook": { - "yahooFinanceType": "number" - }, - "sourceInterval": { - "yahooFinanceType": "number" - }, - "exchangeDataDelayedBy": { - "yahooFinanceType": "number" - }, - "firstTradeDateMilliseconds": { - "yahooFinanceType": "DateInMs" - }, - "priceHint": { - "yahooFinanceType": "number" - }, - "postMarketChangePercent": { - "yahooFinanceType": "number" - }, - "postMarketTime": { - "yahooFinanceType": "date" - }, - "postMarketPrice": { - "yahooFinanceType": "number" - }, - "postMarketChange": { - "yahooFinanceType": "number" - }, - "regularMarketChange": { - "yahooFinanceType": "number" - }, - "regularMarketChangePercent": { - "yahooFinanceType": "number" - }, - "regularMarketTime": { - "yahooFinanceType": "date" - }, - "regularMarketPrice": { - "yahooFinanceType": "number" - }, - "regularMarketDayHigh": { - "yahooFinanceType": "number" - }, - "regularMarketDayRange": { - "yahooFinanceType": "TwoNumberRange" - }, - "regularMarketDayLow": { - "yahooFinanceType": "number" - }, - "regularMarketVolume": { - "yahooFinanceType": "number" - }, - "regularMarketPreviousClose": { - "yahooFinanceType": "number" - }, - "preMarketChange": { - "yahooFinanceType": "number" - }, - "preMarketChangePercent": { - "yahooFinanceType": "number" - }, - "preMarketTime": { - "yahooFinanceType": "date" - }, - "preMarketPrice": { - "yahooFinanceType": "number" - }, - "bid": { - "yahooFinanceType": "number" - }, - "ask": { - "yahooFinanceType": "number" - }, - "bidSize": { - "yahooFinanceType": "number" - }, - "askSize": { - "yahooFinanceType": "number" - }, - "fullExchangeName": { - "type": "string" - }, - "financialCurrency": { - "type": "string" - }, - "regularMarketOpen": { - "yahooFinanceType": "number" - }, - "averageDailyVolume3Month": { - "yahooFinanceType": "number" - }, - "averageDailyVolume10Day": { - "yahooFinanceType": "number" - }, - "displayName": { - "type": "string" - }, - "symbol": { - "type": "string" - }, - "underlyingSymbol": { - "type": "string" - }, - "ytdReturn": { - "yahooFinanceType": "number" - }, - "trailingThreeMonthReturns": { - "yahooFinanceType": "number" - }, - "trailingThreeMonthNavReturns": { - "yahooFinanceType": "number" - }, - "ipoExpectedDate": { - "yahooFinanceType": "date" - }, - "newListingDate": { - "yahooFinanceType": "date" - }, - "nameChangeDate": { - "yahooFinanceType": "date" - }, - "prevName": { - "type": "string" - }, - "averageAnalystRating": { - "type": "string" - }, - "pageViewGrowthWeekly": { - "yahooFinanceType": "number" - }, - "openInterest": { - "yahooFinanceType": "number" - }, - "beta": { - "yahooFinanceType": "number" - }, - "strike": { - "yahooFinanceType": "number" - }, - "expireDate": { - "yahooFinanceType": "number" - }, - "expireIsoDate": { - "yahooFinanceType": "number" - } - }, - "required": [ - "esgPopulated", - "exchange", - "exchangeDataDelayedBy", - "exchangeTimezoneName", - "exchangeTimezoneShortName", - "expireDate", - "expireIsoDate", - "fullExchangeName", - "gmtOffSetMilliseconds", - "language", - "market", - "marketState", - "openInterest", - "priceHint", - "quoteType", - "region", - "sourceInterval", - "strike", - "symbol", - "tradeable", - "triggerable", - "underlyingSymbol" - ] - }, - "QuoteMutualfund": { - "type": "object", - "properties": { - "language": { - "type": "string" - }, - "region": { - "type": "string" - }, - "quoteType": { - "type": "string", - "const": "MUTUALFUND" - }, - "typeDisp": { - "type": "string" - }, - "quoteSourceName": { - "type": "string" - }, - "triggerable": { - "type": "boolean" - }, - "currency": { - "type": "string" - }, - "customPriceAlertConfidence": { - "type": "string" - }, - "marketState": { - "type": "string", - "enum": [ - "REGULAR", - "CLOSED", - "PRE", - "PREPRE", - "POST", - "POSTPOST" - ] - }, - "tradeable": { - "type": "boolean" - }, - "cryptoTradeable": { - "type": "boolean" - }, - "exchange": { - "type": "string" - }, - "shortName": { - "type": "string" - }, - "longName": { - "type": "string" - }, - "messageBoardId": { - "type": "string" - }, - "exchangeTimezoneName": { - "type": "string" - }, - "exchangeTimezoneShortName": { - "type": "string" - }, - "gmtOffSetMilliseconds": { - "yahooFinanceType": "number" - }, - "market": { - "type": "string" - }, - "esgPopulated": { - "type": "boolean" - }, - "fiftyTwoWeekLowChange": { - "yahooFinanceType": "number" - }, - "fiftyTwoWeekLowChangePercent": { - "yahooFinanceType": "number" - }, - "fiftyTwoWeekRange": { - "yahooFinanceType": "TwoNumberRange" - }, - "fiftyTwoWeekHighChange": { - "yahooFinanceType": "number" - }, - "fiftyTwoWeekHighChangePercent": { - "yahooFinanceType": "number" - }, - "fiftyTwoWeekLow": { - "yahooFinanceType": "number" - }, - "fiftyTwoWeekHigh": { - "yahooFinanceType": "number" - }, - "fiftyTwoWeekChangePercent": { - "yahooFinanceType": "number" - }, - "dividendDate": { - "yahooFinanceType": "date" - }, - "earningsTimestamp": { - "yahooFinanceType": "date" - }, - "earningsTimestampStart": { - "yahooFinanceType": "date" - }, - "earningsTimestampEnd": { - "yahooFinanceType": "date" - }, - "trailingAnnualDividendRate": { - "yahooFinanceType": "number" - }, - "trailingPE": { - "yahooFinanceType": "number" - }, - "trailingAnnualDividendYield": { - "yahooFinanceType": "number" - }, - "epsTrailingTwelveMonths": { - "yahooFinanceType": "number" - }, - "epsForward": { - "yahooFinanceType": "number" - }, - "epsCurrentYear": { - "yahooFinanceType": "number" - }, - "priceEpsCurrentYear": { - "yahooFinanceType": "number" - }, - "sharesOutstanding": { - "yahooFinanceType": "number" - }, - "bookValue": { - "yahooFinanceType": "number" - }, - "fiftyDayAverage": { - "yahooFinanceType": "number" - }, - "fiftyDayAverageChange": { - "yahooFinanceType": "number" - }, - "fiftyDayAverageChangePercent": { - "yahooFinanceType": "number" - }, - "twoHundredDayAverage": { - "yahooFinanceType": "number" - }, - "twoHundredDayAverageChange": { - "yahooFinanceType": "number" - }, - "twoHundredDayAverageChangePercent": { - "yahooFinanceType": "number" - }, - "marketCap": { - "yahooFinanceType": "number" - }, - "forwardPE": { - "yahooFinanceType": "number" - }, - "priceToBook": { - "yahooFinanceType": "number" - }, - "sourceInterval": { - "yahooFinanceType": "number" - }, - "exchangeDataDelayedBy": { - "yahooFinanceType": "number" - }, - "firstTradeDateMilliseconds": { - "yahooFinanceType": "DateInMs" - }, - "priceHint": { - "yahooFinanceType": "number" - }, - "postMarketChangePercent": { - "yahooFinanceType": "number" - }, - "postMarketTime": { - "yahooFinanceType": "date" - }, - "postMarketPrice": { - "yahooFinanceType": "number" - }, - "postMarketChange": { - "yahooFinanceType": "number" - }, - "regularMarketChange": { - "yahooFinanceType": "number" - }, - "regularMarketChangePercent": { - "yahooFinanceType": "number" - }, - "regularMarketTime": { - "yahooFinanceType": "date" - }, - "regularMarketPrice": { - "yahooFinanceType": "number" - }, - "regularMarketDayHigh": { - "yahooFinanceType": "number" - }, - "regularMarketDayRange": { - "yahooFinanceType": "TwoNumberRange" - }, - "regularMarketDayLow": { - "yahooFinanceType": "number" - }, - "regularMarketVolume": { - "yahooFinanceType": "number" - }, - "regularMarketPreviousClose": { - "yahooFinanceType": "number" - }, - "preMarketChange": { - "yahooFinanceType": "number" - }, - "preMarketChangePercent": { - "yahooFinanceType": "number" - }, - "preMarketTime": { - "yahooFinanceType": "date" - }, - "preMarketPrice": { - "yahooFinanceType": "number" - }, - "bid": { - "yahooFinanceType": "number" - }, - "ask": { - "yahooFinanceType": "number" - }, - "bidSize": { - "yahooFinanceType": "number" - }, - "askSize": { - "yahooFinanceType": "number" - }, - "fullExchangeName": { - "type": "string" - }, - "financialCurrency": { - "type": "string" - }, - "regularMarketOpen": { - "yahooFinanceType": "number" - }, - "averageDailyVolume3Month": { - "yahooFinanceType": "number" - }, - "averageDailyVolume10Day": { - "yahooFinanceType": "number" - }, - "displayName": { - "type": "string" - }, - "symbol": { - "type": "string" - }, - "underlyingSymbol": { - "type": "string" - }, - "ytdReturn": { - "yahooFinanceType": "number" - }, - "trailingThreeMonthReturns": { - "yahooFinanceType": "number" - }, - "trailingThreeMonthNavReturns": { - "yahooFinanceType": "number" - }, - "ipoExpectedDate": { - "yahooFinanceType": "date" - }, - "newListingDate": { - "yahooFinanceType": "date" - }, - "nameChangeDate": { - "yahooFinanceType": "date" - }, - "prevName": { - "type": "string" - }, - "averageAnalystRating": { - "type": "string" - }, - "pageViewGrowthWeekly": { - "yahooFinanceType": "number" - }, - "openInterest": { - "yahooFinanceType": "number" - }, - "beta": { - "yahooFinanceType": "number" - } - }, - "required": [ - "esgPopulated", - "exchange", - "exchangeDataDelayedBy", - "exchangeTimezoneName", - "exchangeTimezoneShortName", - "fullExchangeName", - "gmtOffSetMilliseconds", - "language", - "market", - "marketState", - "priceHint", - "quoteType", - "region", - "sourceInterval", - "symbol", - "tradeable", - "triggerable" - ] - }, - "Quote": { - "anyOf": [ - { - "$ref": "#/definitions/QuoteCryptoCurrency" - }, - { - "$ref": "#/definitions/QuoteCurrency" - }, - { - "$ref": "#/definitions/QuoteEtf" - }, - { - "$ref": "#/definitions/QuoteEquity" - }, - { - "$ref": "#/definitions/QuoteFuture" - }, - { - "$ref": "#/definitions/QuoteIndex" - }, - { - "$ref": "#/definitions/QuoteMutualfund" - }, - { - "$ref": "#/definitions/QuoteOption" - } - ] - }, - "QuoteField": { - "type": "string", - "enum": [ - "quoteType", - "circulatingSupply", - "fromCurrency", - "toCurrency", - "lastMarket", - "coinImageUrl", - "volume24Hr", - "volumeAllCurrencies", - "startDate", - "language", - "region", - "typeDisp", - "quoteSourceName", - "triggerable", - "currency", - "customPriceAlertConfidence", - "marketState", - "tradeable", - "cryptoTradeable", - "exchange", - "shortName", - "longName", - "messageBoardId", - "exchangeTimezoneName", - "exchangeTimezoneShortName", - "gmtOffSetMilliseconds", - "market", - "esgPopulated", - "fiftyTwoWeekLowChange", - "fiftyTwoWeekLowChangePercent", - "fiftyTwoWeekRange", - "fiftyTwoWeekHighChange", - "fiftyTwoWeekHighChangePercent", - "fiftyTwoWeekLow", - "fiftyTwoWeekHigh", - "fiftyTwoWeekChangePercent", - "dividendDate", - "earningsTimestamp", - "earningsTimestampStart", - "earningsTimestampEnd", - "trailingAnnualDividendRate", - "trailingPE", - "trailingAnnualDividendYield", - "epsTrailingTwelveMonths", - "epsForward", - "epsCurrentYear", - "priceEpsCurrentYear", - "sharesOutstanding", - "bookValue", - "fiftyDayAverage", - "fiftyDayAverageChange", - "fiftyDayAverageChangePercent", - "twoHundredDayAverage", - "twoHundredDayAverageChange", - "twoHundredDayAverageChangePercent", - "marketCap", - "forwardPE", - "priceToBook", - "sourceInterval", - "exchangeDataDelayedBy", - "firstTradeDateMilliseconds", - "priceHint", - "postMarketChangePercent", - "postMarketTime", - "postMarketPrice", - "postMarketChange", - "regularMarketChange", - "regularMarketChangePercent", - "regularMarketTime", - "regularMarketPrice", - "regularMarketDayHigh", - "regularMarketDayRange", - "regularMarketDayLow", - "regularMarketVolume", - "regularMarketPreviousClose", - "preMarketChange", - "preMarketChangePercent", - "preMarketTime", - "preMarketPrice", - "bid", - "ask", - "bidSize", - "askSize", - "fullExchangeName", - "financialCurrency", - "regularMarketOpen", - "averageDailyVolume3Month", - "averageDailyVolume10Day", - "displayName", - "symbol", - "underlyingSymbol", - "ytdReturn", - "trailingThreeMonthReturns", - "trailingThreeMonthNavReturns", - "ipoExpectedDate", - "newListingDate", - "nameChangeDate", - "prevName", - "averageAnalystRating", - "pageViewGrowthWeekly", - "openInterest", - "beta", - "dividendRate", - "dividendYield", - "headSymbolAsString", - "contractSymbol", - "underlyingExchangeSymbol", - "expireDate", - "expireIsoDate", - "strike" - ] - }, - "ResultType": { - "type": "string", - "enum": [ - "array", - "object", - "map" - ] - }, - "QuoteResponseArray": { - "type": "array", - "items": { - "$ref": "#/definitions/Quote" - } - }, - "QuoteResponseMap": { - "type": "object", - "properties": { - "size": { - "yahooFinanceType": "number" - } - }, - "required": [ - "size" - ], - "additionalProperties": false - }, - "QuoteResponseObject": { - "type": "object", - "additionalProperties": { - "$ref": "#/definitions/Quote" - } - }, - "QuoteOptions": { - "type": "object", - "properties": { - "fields": { - "type": "array", - "items": { - "$ref": "#/definitions/QuoteField" - } - }, - "return": { - "$ref": "#/definitions/ResultType" - } - }, - "additionalProperties": false - }, - "QuoteOptionsWithReturnArray": { - "type": "object", - "properties": { - "fields": { - "type": "array", - "items": { - "$ref": "#/definitions/QuoteField" - } - }, - "return": { - "type": "string", - "const": "array" - } - }, - "additionalProperties": false - }, - "QuoteOptionsWithReturnMap": { - "type": "object", - "properties": { - "fields": { - "type": "array", - "items": { - "$ref": "#/definitions/QuoteField" - } - }, - "return": { - "type": "string", - "const": "map" - } - }, - "required": [ - "return" - ], - "additionalProperties": false - }, - "QuoteOptionsWithReturnObject": { - "type": "object", - "properties": { - "fields": { - "type": "array", - "items": { - "$ref": "#/definitions/QuoteField" - } - }, - "return": { - "type": "string", - "const": "object" - } - }, - "required": [ - "return" - ], - "additionalProperties": false - }, - "NamedParameters": { - "type": "object", - "properties": { - "this": { - "$ref": "#/definitions/ModuleThis" - }, - "query": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ] - }, - "queryOptionsOverrides": { - "$ref": "#/definitions/QuoteOptions" - }, - "moduleOptions": { - "$ref": "#/definitions/ModuleOptions" - } - }, - "required": [ - "this", - "query" - ], - "additionalProperties": false - }, - "OptionsResult": { - "type": "object", - "properties": { - "underlyingSymbol": { - "type": "string" - }, - "expirationDates": { - "type": "array", - "items": { - "yahooFinanceType": "date" - } - }, - "strikes": { - "type": "array", - "items": { - "yahooFinanceType": "number" - } - }, - "hasMiniOptions": { - "type": "boolean" - }, - "quote": { - "$ref": "#/definitions/Quote" - }, - "options": { - "type": "array", - "items": { - "$ref": "#/definitions/Option" - } - } - }, - "required": [ - "underlyingSymbol", - "expirationDates", - "strikes", - "hasMiniOptions", - "quote", - "options" - ] - }, - "Option": { - "type": "object", - "properties": { - "expirationDate": { - "yahooFinanceType": "date" - }, - "hasMiniOptions": { - "type": "boolean" - }, - "calls": { - "type": "array", - "items": { - "$ref": "#/definitions/CallOrPut" - } - }, - "puts": { - "type": "array", - "items": { - "$ref": "#/definitions/CallOrPut" - } - } - }, - "required": [ - "expirationDate", - "hasMiniOptions", - "calls", - "puts" - ] - }, - "CallOrPut": { - "type": "object", - "properties": { - "contractSymbol": { - "type": "string" - }, - "strike": { - "yahooFinanceType": "number" - }, - "currency": { - "type": "string" - }, - "lastPrice": { - "yahooFinanceType": "number" - }, - "change": { - "yahooFinanceType": "number" - }, - "percentChange": { - "yahooFinanceType": "number" - }, - "volume": { - "yahooFinanceType": "number" - }, - "openInterest": { - "yahooFinanceType": "number" - }, - "bid": { - "yahooFinanceType": "number" - }, - "ask": { - "yahooFinanceType": "number" - }, - "contractSize": { - "type": "string", - "const": "REGULAR" - }, - "expiration": { - "yahooFinanceType": "date" - }, - "lastTradeDate": { - "yahooFinanceType": "date" - }, - "impliedVolatility": { - "yahooFinanceType": "number" - }, - "inTheMoney": { - "type": "boolean" - } - }, - "required": [ - "contractSymbol", - "strike", - "lastPrice", - "change", - "contractSize", - "expiration", - "lastTradeDate", - "impliedVolatility", - "inTheMoney" - ] - }, - "EnumGrade": { - "type": "string", - "enum": [ - "Accumulate", - "Add", - "Average", - "Below Average", - "Buy", - "Conviction Buy", - "", - "Equal-Weight", - "Fair Value", - "Equal-weight", - "Long-term Buy", - "Hold", - "Long-Term Buy", - "Market Outperform", - "Market Perform", - "Mixed", - "Negative", - "Neutral", - "In-Line", - "Outperform", - "Overweight", - "Peer Perform", - "Perform", - "Positive", - "Reduce", - "Sector Outperform", - "Sector Perform", - "Sector Weight", - "Sell", - "Strong Buy", - "Top Pick", - "Underperform", - "Underperformer", - "Underweight", - "Trim", - "Above Average", - "In-line", - "Outperformer", - "OVerweight", - "Cautious", - "Market Weight", - "Sector Underperform", - "Market Underperform", - "Peer perform", - "Gradually Accumulate", - "Action List Buy", - "Performer", - "Sector Performer", - "Speculative Buy", - "Strong Sell", - "Speculative Hold", - "Not Rated", - "Hold Neutral", - "Developing", - "buy", - "HOld", - "Trading Sell", - "Tender", - "market perform", - "BUy" - ] - }, - "QuoteSummaryResult": { - "type": "object", - "properties": { - "assetProfile": { - "$ref": "#/definitions/AssetProfile" - }, - "balanceSheetHistory": { - "$ref": "#/definitions/BalanceSheetHistory" - }, - "balanceSheetHistoryQuarterly": { - "$ref": "#/definitions/BalanceSheetHistory" - }, - "calendarEvents": { - "$ref": "#/definitions/CalendarEvents" - }, - "cashflowStatementHistory": { - "$ref": "#/definitions/CashflowStatementHistory" - }, - "cashflowStatementHistoryQuarterly": { - "$ref": "#/definitions/CashflowStatementHistory" - }, - "defaultKeyStatistics": { - "$ref": "#/definitions/DefaultKeyStatistics" - }, - "earnings": { - "$ref": "#/definitions/QuoteSummaryEarnings" - }, - "earningsHistory": { - "$ref": "#/definitions/EarningsHistory" - }, - "earningsTrend": { - "$ref": "#/definitions/EarningsTrend" - }, - "financialData": { - "$ref": "#/definitions/FinancialData" - }, - "fundOwnership": { - "$ref": "#/definitions/Ownership" - }, - "fundPerformance": { - "$ref": "#/definitions/FundPerformance" - }, - "fundProfile": { - "$ref": "#/definitions/FundProfile" - }, - "incomeStatementHistory": { - "$ref": "#/definitions/IncomeStatementHistory" - }, - "incomeStatementHistoryQuarterly": { - "$ref": "#/definitions/IncomeStatementHistory" - }, - "indexTrend": { - "$ref": "#/definitions/IndexTrend" - }, - "industryTrend": { - "$ref": "#/definitions/Trend" - }, - "insiderHolders": { - "$ref": "#/definitions/Holders" - }, - "insiderTransactions": { - "$ref": "#/definitions/InsiderTransactions" - }, - "institutionOwnership": { - "$ref": "#/definitions/Ownership" - }, - "majorDirectHolders": { - "$ref": "#/definitions/Holders" - }, - "majorHoldersBreakdown": { - "$ref": "#/definitions/MajorHoldersBreakdown" - }, - "netSharePurchaseActivity": { - "$ref": "#/definitions/NetSharePurchaseActivity" - }, - "price": { - "$ref": "#/definitions/Price" - }, - "quoteType": { - "$ref": "#/definitions/QuoteType" - }, - "recommendationTrend": { - "$ref": "#/definitions/RecommendationTrend" - }, - "secFilings": { - "$ref": "#/definitions/SECFilings" - }, - "sectorTrend": { - "$ref": "#/definitions/Trend" - }, - "summaryDetail": { - "$ref": "#/definitions/SummaryDetail" - }, - "summaryProfile": { - "$ref": "#/definitions/SummaryProfile" - }, - "topHoldings": { - "$ref": "#/definitions/TopHoldings" - }, - "upgradeDowngradeHistory": { - "$ref": "#/definitions/UpgradeDowngradeHistory" - } - } - }, - "AssetProfile": { - "type": "object", - "properties": { - "maxAge": { - "yahooFinanceType": "number" - }, - "address1": { - "type": "string" - }, - "address2": { - "type": "string" - }, - "address3": { - "type": "string" - }, - "city": { - "type": "string" - }, - "state": { - "type": "string" - }, - "zip": { - "type": "string" - }, - "country": { - "type": "string" - }, - "phone": { - "type": "string" - }, - "fax": { - "type": "string" - }, - "website": { - "type": "string" - }, - "industry": { - "type": "string" - }, - "industryDisp": { - "type": "string" - }, - "industryKey": { - "type": "string" - }, - "industrySymbol": { - "type": "string" - }, - "sector": { - "type": "string" - }, - "sectorDisp": { - "type": "string" - }, - "sectorKey": { - "type": "string" - }, - "longBusinessSummary": { - "type": "string" - }, - "fullTimeEmployees": { - "yahooFinanceType": "number" - }, - "companyOfficers": { - "type": "array", - "items": { - "$ref": "#/definitions/CompanyOfficer" - } - }, - "auditRisk": { - "yahooFinanceType": "number" - }, - "boardRisk": { - "yahooFinanceType": "number" - }, - "compensationRisk": { - "yahooFinanceType": "number" - }, - "shareHolderRightsRisk": { - "yahooFinanceType": "number" - }, - "overallRisk": { - "yahooFinanceType": "number" - }, - "governanceEpochDate": { - "yahooFinanceType": "date" - }, - "compensationAsOfEpochDate": { - "yahooFinanceType": "date" - }, - "name": { - "type": "string" - }, - "startDate": { - "yahooFinanceType": "date" - }, - "description": { - "type": "string" - }, - "twitter": { - "type": "string" - } - }, - "required": [ - "maxAge", - "companyOfficers" - ] - }, - "CompanyOfficer": { - "type": "object", - "properties": { - "maxAge": { - "yahooFinanceType": "number" - }, - "name": { - "type": "string" - }, - "age": { - "yahooFinanceType": "number" - }, - "title": { - "type": "string" - }, - "yearBorn": { - "yahooFinanceType": "number" - }, - "fiscalYear": { - "yahooFinanceType": "number" - }, - "totalPay": { - "yahooFinanceType": "number" - }, - "exercisedValue": { - "yahooFinanceType": "number" - }, - "unexercisedValue": { - "yahooFinanceType": "number" - } - }, - "required": [ - "maxAge", - "name", - "title" - ] - }, - "BalanceSheetHistory": { - "type": "object", - "properties": { - "balanceSheetStatements": { - "type": "array", - "items": { - "$ref": "#/definitions/BalanceSheetStatement" - } - }, - "maxAge": { - "yahooFinanceType": "number" - } - }, - "required": [ - "balanceSheetStatements", - "maxAge" - ] - }, - "BalanceSheetStatement": { - "type": "object", - "properties": { - "maxAge": { - "yahooFinanceType": "number" - }, - "endDate": { - "yahooFinanceType": "date" - }, - "cash": { - "yahooFinanceType": "number" - }, - "shortTermInvestments": { - "yahooFinanceType": "number" - }, - "netReceivables": { - "yahooFinanceType": "number" - }, - "inventory": { - "yahooFinanceType": "number" - }, - "otherCurrentAssets": { - "yahooFinanceType": "number" - }, - "totalCurrentAssets": { - "yahooFinanceType": "number" - }, - "longTermInvestments": { - "yahooFinanceType": "number" - }, - "propertyPlantEquipment": { - "yahooFinanceType": "number" - }, - "otherAssets": { - "yahooFinanceType": "number" - }, - "totalAssets": { - "yahooFinanceType": "number" - }, - "accountsPayable": { - "yahooFinanceType": "number" - }, - "shortLongTermDebt": { - "yahooFinanceType": "number" - }, - "otherCurrentLiab": { - "yahooFinanceType": "number" - }, - "longTermDebt": { - "yahooFinanceType": "number" - }, - "otherLiab": { - "yahooFinanceType": "number" - }, - "totalCurrentLiabilities": { - "yahooFinanceType": "number" - }, - "totalLiab": { - "yahooFinanceType": "number" - }, - "commonStock": { - "yahooFinanceType": "number" - }, - "retainedEarnings": { - "yahooFinanceType": "number" - }, - "treasuryStock": { - "yahooFinanceType": "number" - }, - "otherStockholderEquity": { - "yahooFinanceType": "number" - }, - "totalStockholderEquity": { - "yahooFinanceType": "number" - }, - "netTangibleAssets": { - "yahooFinanceType": "number" - }, - "goodWill": { - "yahooFinanceType": "number" - }, - "intangibleAssets": { - "yahooFinanceType": "number" - }, - "deferredLongTermAssetCharges": { - "yahooFinanceType": "number" - }, - "deferredLongTermLiab": { - "yahooFinanceType": "number" - }, - "minorityInterest": { - "yahooFinanceType": "number|null" - }, - "capitalSurplus": { - "yahooFinanceType": "number" - } - }, - "required": [ - "maxAge", - "endDate" - ] - }, - "CalendarEvents": { - "type": "object", - "properties": { - "maxAge": { - "yahooFinanceType": "number" - }, - "earnings": { - "$ref": "#/definitions/CalendarEventsEarnings" - }, - "exDividendDate": { - "yahooFinanceType": "date" - }, - "dividendDate": { - "yahooFinanceType": "date" - } - }, - "required": [ - "maxAge", - "earnings" - ] - }, - "CalendarEventsEarnings": { - "type": "object", - "properties": { - "earningsDate": { - "type": "array", - "items": { - "yahooFinanceType": "date" - } - }, - "earningsAverage": { - "yahooFinanceType": "number" - }, - "earningsLow": { - "yahooFinanceType": "number" - }, - "earningsHigh": { - "yahooFinanceType": "number" - }, - "revenueAverage": { - "yahooFinanceType": "number" - }, - "revenueLow": { - "yahooFinanceType": "number" - }, - "revenueHigh": { - "yahooFinanceType": "number" - } - }, - "required": [ - "earningsDate" - ] - }, - "CashflowStatementHistory": { - "type": "object", - "properties": { - "cashflowStatements": { - "type": "array", - "items": { - "$ref": "#/definitions/CashflowStatement" - } - }, - "maxAge": { - "yahooFinanceType": "number" - } - }, - "required": [ - "cashflowStatements", - "maxAge" - ] - }, - "CashflowStatement": { - "type": "object", - "properties": { - "maxAge": { - "yahooFinanceType": "number" - }, - "endDate": { - "yahooFinanceType": "date" - }, - "netIncome": { - "yahooFinanceType": "number" - }, - "depreciation": { - "yahooFinanceType": "number" - }, - "changeToNetincome": { - "yahooFinanceType": "number" - }, - "changeToAccountReceivables": { - "yahooFinanceType": "number" - }, - "changeToLiabilities": { - "yahooFinanceType": "number" - }, - "changeToInventory": { - "yahooFinanceType": "number" - }, - "changeToOperatingActivities": { - "yahooFinanceType": "number" - }, - "totalCashFromOperatingActivities": { - "yahooFinanceType": "number" - }, - "capitalExpenditures": { - "yahooFinanceType": "number" - }, - "investments": { - "yahooFinanceType": "number" - }, - "otherCashflowsFromInvestingActivities": { - "yahooFinanceType": "number" - }, - "totalCashflowsFromInvestingActivities": { - "yahooFinanceType": "number" - }, - "dividendsPaid": { - "yahooFinanceType": "number" - }, - "netBorrowings": { - "yahooFinanceType": "number" - }, - "otherCashflowsFromFinancingActivities": { - "yahooFinanceType": "number" - }, - "totalCashFromFinancingActivities": { - "yahooFinanceType": "number" - }, - "changeInCash": { - "yahooFinanceType": "number" - }, - "repurchaseOfStock": { - "yahooFinanceType": "number" - }, - "issuanceOfStock": { - "yahooFinanceType": "number" - }, - "effectOfExchangeRate": { - "yahooFinanceType": "number" - } - }, - "required": [ - "maxAge", - "endDate", - "netIncome" - ] - }, - "DefaultKeyStatistics": { - "type": "object", - "properties": { - "maxAge": { - "yahooFinanceType": "number" - }, - "priceHint": { - "yahooFinanceType": "number" - }, - "enterpriseValue": { - "yahooFinanceType": "number" - }, - "forwardPE": { - "yahooFinanceType": "number" - }, - "profitMargins": { - "yahooFinanceType": "number" - }, - "floatShares": { - "yahooFinanceType": "number" - }, - "sharesOutstanding": { - "yahooFinanceType": "number" - }, - "sharesShort": { - "yahooFinanceType": "number" - }, - "sharesShortPriorMonth": { - "yahooFinanceType": "date" - }, - "sharesShortPreviousMonthDate": { - "yahooFinanceType": "date" - }, - "dateShortInterest": { - "yahooFinanceType": "date" - }, - "sharesPercentSharesOut": { - "yahooFinanceType": "number" - }, - "heldPercentInsiders": { - "yahooFinanceType": "number" - }, - "heldPercentInstitutions": { - "yahooFinanceType": "number" - }, - "shortRatio": { - "yahooFinanceType": "number" - }, - "shortPercentOfFloat": { - "yahooFinanceType": "number" - }, - "beta": { - "yahooFinanceType": "number" - }, - "impliedSharesOutstanding": { - "yahooFinanceType": "number" - }, - "category": { - "type": [ - "null", - "string" - ] - }, - "bookValue": { - "yahooFinanceType": "number" - }, - "priceToBook": { - "yahooFinanceType": "number" - }, - "fundFamily": { - "type": [ - "null", - "string" - ] - }, - "legalType": { - "type": [ - "null", - "string" - ] - }, - "lastFiscalYearEnd": { - "yahooFinanceType": "date" - }, - "nextFiscalYearEnd": { - "yahooFinanceType": "date" - }, - "mostRecentQuarter": { - "yahooFinanceType": "date" - }, - "earningsQuarterlyGrowth": { - "yahooFinanceType": "number" - }, - "netIncomeToCommon": { - "yahooFinanceType": "number" - }, - "trailingEps": { - "yahooFinanceType": "number" - }, - "forwardEps": { - "yahooFinanceType": "number" - }, - "pegRatio": { - "yahooFinanceType": "number" - }, - "lastSplitFactor": { - "type": [ - "null", - "string" - ] - }, - "lastSplitDate": { - "yahooFinanceType": "number" - }, - "enterpriseToRevenue": { - "yahooFinanceType": "number" - }, - "enterpriseToEbitda": { - "yahooFinanceType": "number" - }, - "52WeekChange": { - "yahooFinanceType": "number" - }, - "SandP52WeekChange": { - "yahooFinanceType": "number" - }, - "lastDividendValue": { - "yahooFinanceType": "number" - }, - "lastDividendDate": { - "yahooFinanceType": "date" - }, - "ytdReturn": { - "yahooFinanceType": "number" - }, - "beta3Year": { - "yahooFinanceType": "number" - }, - "totalAssets": { - "yahooFinanceType": "number" - }, - "yield": { - "yahooFinanceType": "number" - }, - "fundInceptionDate": { - "yahooFinanceType": "date" - }, - "threeYearAverageReturn": { - "yahooFinanceType": "number" - }, - "fiveYearAverageReturn": { - "yahooFinanceType": "number" - }, - "morningStarOverallRating": { - "yahooFinanceType": "number" - }, - "morningStarRiskRating": { - "yahooFinanceType": "number" - }, - "annualReportExpenseRatio": { - "yahooFinanceType": "number" - }, - "lastCapGain": { - "yahooFinanceType": "number" - }, - "annualHoldingsTurnover": { - "yahooFinanceType": "number" - } - }, - "required": [ - "maxAge", - "priceHint", - "category", - "fundFamily", - "legalType", - "lastSplitFactor" - ] - }, - "QuoteSummaryEarnings": { - "type": "object", - "properties": { - "maxAge": { - "yahooFinanceType": "number" - }, - "earningsChart": { - "$ref": "#/definitions/EarningsChart" - }, - "financialsChart": { - "$ref": "#/definitions/FinancialsChart" - }, - "financialCurrency": { - "type": "string" - } - }, - "required": [ - "maxAge", - "earningsChart", - "financialsChart" - ] - }, - "EarningsChart": { - "type": "object", - "properties": { - "quarterly": { - "type": "array", - "items": { - "$ref": "#/definitions/EarningsChartQuarterly" - } - }, - "currentQuarterEstimate": { - "yahooFinanceType": "number" - }, - "currentQuarterEstimateDate": { - "type": "string" - }, - "currentQuarterEstimateYear": { - "yahooFinanceType": "number" - }, - "earningsDate": { - "type": "array", - "items": { - "yahooFinanceType": "date" - } - } - }, - "required": [ - "quarterly", - "earningsDate" - ] - }, - "EarningsChartQuarterly": { - "type": "object", - "properties": { - "date": { - "type": "string" - }, - "actual": { - "yahooFinanceType": "number" - }, - "estimate": { - "yahooFinanceType": "number" - } - }, - "required": [ - "date", - "actual", - "estimate" - ] - }, - "FinancialsChart": { - "type": "object", - "properties": { - "yearly": { - "type": "array", - "items": { - "$ref": "#/definitions/Yearly" - } - }, - "quarterly": { - "type": "array", - "items": { - "$ref": "#/definitions/FinancialsChartQuarterly" - } - } - }, - "required": [ - "yearly", - "quarterly" - ] - }, - "Yearly": { - "type": "object", - "properties": { - "date": { - "yahooFinanceType": "number" - }, - "revenue": { - "yahooFinanceType": "number" - }, - "earnings": { - "yahooFinanceType": "number" - } - }, - "required": [ - "date", - "revenue", - "earnings" - ] - }, - "FinancialsChartQuarterly": { - "type": "object", - "properties": { - "date": { - "type": "string" - }, - "revenue": { - "yahooFinanceType": "number" - }, - "earnings": { - "yahooFinanceType": "number" - } - }, - "required": [ - "date", - "revenue", - "earnings" - ] - }, - "EarningsHistory": { - "type": "object", - "properties": { - "history": { - "type": "array", - "items": { - "$ref": "#/definitions/EarningsHistoryHistory" - } - }, - "maxAge": { - "yahooFinanceType": "number" - } - }, - "required": [ - "history", - "maxAge" - ] - }, - "EarningsHistoryHistory": { - "type": "object", - "properties": { - "maxAge": { - "yahooFinanceType": "number" - }, - "epsActual": { - "yahooFinanceType": "number|null" - }, - "epsEstimate": { - "yahooFinanceType": "number|null" - }, - "epsDifference": { - "yahooFinanceType": "number|null" - }, - "surprisePercent": { - "yahooFinanceType": "number|null" - }, - "quarter": { - "yahooFinanceType": "date|null" - }, - "period": { - "type": "string" - } - }, - "required": [ - "maxAge", - "epsActual", - "epsEstimate", - "epsDifference", - "surprisePercent", - "quarter", - "period" - ] - }, - "EarningsTrend": { - "type": "object", - "properties": { - "trend": { - "type": "array", - "items": { - "$ref": "#/definitions/EarningsTrendTrend" - } - }, - "maxAge": { - "yahooFinanceType": "number" - } - }, - "required": [ - "trend", - "maxAge" - ] - }, - "EarningsTrendTrend": { - "type": "object", - "properties": { - "maxAge": { - "yahooFinanceType": "number" - }, - "period": { - "type": "string" - }, - "endDate": { - "yahooFinanceType": "date|null" - }, - "growth": { - "yahooFinanceType": "number|null" - }, - "earningsEstimate": { - "$ref": "#/definitions/EarningsEstimate" - }, - "revenueEstimate": { - "$ref": "#/definitions/RevenueEstimate" - }, - "epsTrend": { - "$ref": "#/definitions/EpsTrend" - }, - "epsRevisions": { - "$ref": "#/definitions/EpsRevisions" - } - }, - "required": [ - "maxAge", - "period", - "endDate", - "growth", - "earningsEstimate", - "revenueEstimate", - "epsTrend", - "epsRevisions" - ] - }, - "EarningsEstimate": { - "type": "object", - "properties": { - "avg": { - "yahooFinanceType": "number|null" - }, - "low": { - "yahooFinanceType": "number|null" - }, - "high": { - "yahooFinanceType": "number|null" - }, - "yearAgoEps": { - "yahooFinanceType": "number|null" - }, - "numberOfAnalysts": { - "yahooFinanceType": "number|null" - }, - "growth": { - "yahooFinanceType": "number|null" - } - }, - "required": [ - "avg", - "low", - "high", - "yearAgoEps", - "numberOfAnalysts", - "growth" - ] - }, - "RevenueEstimate": { - "type": "object", - "properties": { - "avg": { - "yahooFinanceType": "number|null" - }, - "low": { - "yahooFinanceType": "number|null" - }, - "high": { - "yahooFinanceType": "number|null" - }, - "numberOfAnalysts": { - "yahooFinanceType": "number|null" - }, - "yearAgoRevenue": { - "yahooFinanceType": "number|null" - }, - "growth": { - "yahooFinanceType": "number|null" - } - }, - "required": [ - "avg", - "low", - "high", - "numberOfAnalysts", - "yearAgoRevenue", - "growth" - ] - }, - "EpsTrend": { - "type": "object", - "properties": { - "current": { - "yahooFinanceType": "number|null" - }, - "7daysAgo": { - "yahooFinanceType": "number|null" - }, - "30daysAgo": { - "yahooFinanceType": "number|null" - }, - "60daysAgo": { - "yahooFinanceType": "number|null" - }, - "90daysAgo": { - "yahooFinanceType": "number|null" - } - }, - "required": [ - "current", - "7daysAgo", - "30daysAgo", - "60daysAgo", - "90daysAgo" - ] - }, - "EpsRevisions": { - "type": "object", - "properties": { - "upLast7days": { - "yahooFinanceType": "number|null" - }, - "upLast30days": { - "yahooFinanceType": "number|null" - }, - "downLast30days": { - "yahooFinanceType": "number|null" - }, - "downLast90days": { - "yahooFinanceType": "number|null" - } - }, - "required": [ - "upLast7days", - "upLast30days", - "downLast30days", - "downLast90days" - ] - }, - "FinancialData": { - "type": "object", - "properties": { - "maxAge": { - "yahooFinanceType": "number" - }, - "currentPrice": { - "yahooFinanceType": "number" - }, - "targetHighPrice": { - "yahooFinanceType": "number" - }, - "targetLowPrice": { - "yahooFinanceType": "number" - }, - "targetMeanPrice": { - "yahooFinanceType": "number" - }, - "targetMedianPrice": { - "yahooFinanceType": "number" - }, - "recommendationMean": { - "yahooFinanceType": "number" - }, - "recommendationKey": { - "type": "string" - }, - "numberOfAnalystOpinions": { - "yahooFinanceType": "number" - }, - "totalCash": { - "yahooFinanceType": "number" - }, - "totalCashPerShare": { - "yahooFinanceType": "number" - }, - "ebitda": { - "yahooFinanceType": "number" - }, - "totalDebt": { - "yahooFinanceType": "number" - }, - "quickRatio": { - "yahooFinanceType": "number" - }, - "currentRatio": { - "yahooFinanceType": "number" - }, - "totalRevenue": { - "yahooFinanceType": "number" - }, - "debtToEquity": { - "yahooFinanceType": "number" - }, - "revenuePerShare": { - "yahooFinanceType": "number" - }, - "returnOnAssets": { - "yahooFinanceType": "number" - }, - "returnOnEquity": { - "yahooFinanceType": "number" - }, - "grossProfits": { - "yahooFinanceType": "number" - }, - "freeCashflow": { - "yahooFinanceType": "number" - }, - "operatingCashflow": { - "yahooFinanceType": "number" - }, - "earningsGrowth": { - "yahooFinanceType": "number" - }, - "revenueGrowth": { - "yahooFinanceType": "number" - }, - "grossMargins": { - "yahooFinanceType": "number" - }, - "ebitdaMargins": { - "yahooFinanceType": "number" - }, - "operatingMargins": { - "yahooFinanceType": "number" - }, - "profitMargins": { - "yahooFinanceType": "number" - }, - "financialCurrency": { - "type": [ - "string", - "null" - ] - } - }, - "required": [ - "maxAge", - "recommendationKey", - "financialCurrency" - ] - }, - "Ownership": { - "type": "object", - "properties": { - "maxAge": { - "yahooFinanceType": "number" - }, - "ownershipList": { - "type": "array", - "items": { - "$ref": "#/definitions/OwnershipList" - } - } - }, - "required": [ - "maxAge", - "ownershipList" - ] - }, - "OwnershipList": { - "type": "object", - "properties": { - "maxAge": { - "yahooFinanceType": "number" - }, - "reportDate": { - "yahooFinanceType": "date" - }, - "organization": { - "type": "string" - }, - "pctHeld": { - "yahooFinanceType": "number" - }, - "position": { - "yahooFinanceType": "number" - }, - "value": { - "yahooFinanceType": "number" - }, - "pctChange": { - "yahooFinanceType": "number" - } - }, - "required": [ - "maxAge", - "reportDate", - "organization", - "pctHeld", - "position", - "value" - ] - }, - "FundPerformance": { - "type": "object", - "properties": { - "maxAge": { - "yahooFinanceType": "number" - }, - "loadAdjustedReturns": { - "$ref": "#/definitions/PeriodRange" - }, - "rankInCategory": { - "$ref": "#/definitions/PeriodRange" - }, - "performanceOverview": { - "$ref": "#/definitions/FundPerformancePerformanceOverview" - }, - "performanceOverviewCat": { - "$ref": "#/definitions/FundPerformancePerformanceOverviewCat" - }, - "trailingReturns": { - "$ref": "#/definitions/FundPerformanceTrailingReturns" - }, - "trailingReturnsNav": { - "$ref": "#/definitions/FundPerformanceTrailingReturns" - }, - "trailingReturnsCat": { - "$ref": "#/definitions/FundPerformanceTrailingReturns" - }, - "annualTotalReturns": { - "$ref": "#/definitions/FundPerformanceReturns" - }, - "pastQuarterlyReturns": { - "$ref": "#/definitions/FundPerformanceReturns" - }, - "riskOverviewStatistics": { - "$ref": "#/definitions/FundPerformanceRiskOverviewStats" - }, - "riskOverviewStatisticsCat": { - "$ref": "#/definitions/FundPerformanceRiskOverviewStatsCat" - } - }, - "required": [ - "maxAge", - "performanceOverview", - "performanceOverviewCat", - "trailingReturns", - "trailingReturnsNav", - "trailingReturnsCat", - "annualTotalReturns", - "pastQuarterlyReturns", - "riskOverviewStatistics", - "riskOverviewStatisticsCat" - ] - }, - "PeriodRange": { - "type": "object", - "properties": { - "asOfDate": { - "yahooFinanceType": "date" - }, - "ytd": { - "yahooFinanceType": "number" - }, - "oneMonth": { - "yahooFinanceType": "number" - }, - "threeMonth": { - "yahooFinanceType": "number" - }, - "oneYear": { - "yahooFinanceType": "number" - }, - "threeYear": { - "yahooFinanceType": "number" - }, - "fiveYear": { - "yahooFinanceType": "number" - }, - "tenYear": { - "yahooFinanceType": "number" - } - } - }, - "FundPerformancePerformanceOverview": { - "type": "object", - "properties": { - "asOfDate": { - "yahooFinanceType": "date" - }, - "ytdReturnPct": { - "yahooFinanceType": "number" - }, - "oneYearTotalReturn": { - "yahooFinanceType": "number" - }, - "threeYearTotalReturn": { - "yahooFinanceType": "number" - }, - "fiveYrAvgReturnPct": { - "yahooFinanceType": "number" - }, - "morningStarReturnRating": { - "yahooFinanceType": "number" - }, - "numYearsUp": { - "yahooFinanceType": "number" - }, - "numYearsDown": { - "yahooFinanceType": "number" - }, - "bestOneYrTotalReturn": { - "yahooFinanceType": "number" - }, - "worstOneYrTotalReturn": { - "yahooFinanceType": "number" - }, - "bestThreeYrTotalReturn": { - "yahooFinanceType": "number" - }, - "worstThreeYrTotalReturn": { - "yahooFinanceType": "number" - } - } - }, - "FundPerformancePerformanceOverviewCat": { - "type": "object", - "properties": { - "ytdReturnPct": { - "yahooFinanceType": "number" - }, - "fiveYrAvgReturnPct": { - "yahooFinanceType": "number" - } - } - }, - "FundPerformanceTrailingReturns": { - "type": "object", - "properties": { - "asOfDate": { - "yahooFinanceType": "date" - }, - "ytd": { - "yahooFinanceType": "number" - }, - "oneMonth": { - "yahooFinanceType": "number" - }, - "threeMonth": { - "yahooFinanceType": "number" - }, - "oneYear": { - "yahooFinanceType": "number" - }, - "threeYear": { - "yahooFinanceType": "number" - }, - "fiveYear": { - "yahooFinanceType": "number" - }, - "tenYear": { - "yahooFinanceType": "number" - }, - "lastBullMkt": { - "yahooFinanceType": "number" - }, - "lastBearMkt": { - "yahooFinanceType": "number" - } - } - }, - "FundPerformanceReturns": { - "type": "object", - "properties": { - "returns": { - "type": "array", - "items": { - "$ref": "#/definitions/FundPerformanceReturnsRow" - } - }, - "returnsCat": { - "type": "array", - "items": { - "$ref": "#/definitions/FundPerformanceReturnsRow" - } - } - }, - "required": [ - "returns" - ] - }, - "FundPerformanceReturnsRow": { - "type": "object", - "properties": { - "year": { - "yahooFinanceType": "number" - }, - "annualValue": { - "yahooFinanceType": "number" - }, - "q1": { - "yahooFinanceType": "number" - }, - "q2": { - "yahooFinanceType": "number" - }, - "q3": { - "yahooFinanceType": "number" - }, - "q4": { - "yahooFinanceType": "number" - } - }, - "required": [ - "year" - ] - }, - "FundPerformanceRiskOverviewStats": { - "type": "object", - "properties": { - "riskStatistics": { - "type": "array", - "items": { - "$ref": "#/definitions/FundPerformanceRiskOverviewStatsRow" - } - }, - "riskRating": { - "yahooFinanceType": "number" - } - }, - "required": [ - "riskStatistics" - ] - }, - "FundPerformanceRiskOverviewStatsRow": { - "type": "object", - "properties": { - "year": { - "type": "string" - }, - "alpha": { - "yahooFinanceType": "number" - }, - "beta": { - "yahooFinanceType": "number" - }, - "meanAnnualReturn": { - "yahooFinanceType": "number" - }, - "rSquared": { - "yahooFinanceType": "number" - }, - "stdDev": { - "yahooFinanceType": "number" - }, - "sharpeRatio": { - "yahooFinanceType": "number" - }, - "treynorRatio": { - "yahooFinanceType": "number" - } - }, - "required": [ - "year", - "alpha", - "beta", - "meanAnnualReturn", - "rSquared", - "sharpeRatio", - "treynorRatio" - ] - }, - "FundPerformanceRiskOverviewStatsCat": { - "type": "object", - "properties": { - "riskStatisticsCat": { - "type": "array", - "items": { - "$ref": "#/definitions/FundPerformanceRiskOverviewStatsRow" - } - } - }, - "required": [ - "riskStatisticsCat" - ] - }, - "FundProfile": { - "type": "object", - "properties": { - "maxAge": { - "yahooFinanceType": "number" - }, - "styleBoxUrl": { - "type": [ - "null", - "string" - ] - }, - "family": { - "type": [ - "null", - "string" - ] - }, - "categoryName": { - "type": [ - "null", - "string" - ] - }, - "legalType": { - "type": [ - "null", - "string" - ] - }, - "managementInfo": { - "$ref": "#/definitions/FundProfileManagementInfo" - }, - "feesExpensesInvestment": { - "$ref": "#/definitions/FundProfileFeesExpensesInvestment" - }, - "feesExpensesInvestmentCat": { - "$ref": "#/definitions/FundProfileFeesExpensesInvestmentCat" - }, - "brokerages": { - "type": "array", - "items": { - "$ref": "#/definitions/FundProfileBrokerage" - } - }, - "initInvestment": { - "yahooFinanceType": "number" - }, - "initIraInvestment": { - "yahooFinanceType": "number" - }, - "initAipInvestment": { - "yahooFinanceType": "number" - }, - "subseqInvestment": { - "yahooFinanceType": "number" - }, - "subseqIraInvestment": { - "yahooFinanceType": "number" - }, - "subseqAipInvestment": { - "yahooFinanceType": "number" - } - }, - "required": [ - "maxAge", - "family", - "categoryName", - "legalType" - ] - }, - "FundProfileManagementInfo": { - "type": "object", - "properties": { - "managerName": { - "type": [ - "null", - "string" - ] - }, - "managerBio": { - "type": [ - "null", - "string" - ] - }, - "startdate": { - "yahooFinanceType": "date" - } - }, - "required": [ - "managerName", - "managerBio" - ] - }, - "FundProfileFeesExpensesInvestment": { - "type": "object", - "properties": { - "annualHoldingsTurnover": { - "yahooFinanceType": "number" - }, - "annualReportExpenseRatio": { - "yahooFinanceType": "number" - }, - "grossExpRatio": { - "yahooFinanceType": "number" - }, - "netExpRatio": { - "yahooFinanceType": "number" - }, - "projectionValues": { - "type": "object" - }, - "totalNetAssets": { - "yahooFinanceType": "number" - } - }, - "required": [ - "projectionValues" - ] - }, - "FundProfileFeesExpensesInvestmentCat": { - "type": "object", - "properties": { - "annualHoldingsTurnover": { - "yahooFinanceType": "number" - }, - "annualReportExpenseRatio": { - "yahooFinanceType": "number" - }, - "grossExpRatio": { - "yahooFinanceType": "number" - }, - "netExpRatio": { - "yahooFinanceType": "number" - }, - "totalNetAssets": { - "yahooFinanceType": "number" - }, - "projectionValuesCat": { - "type": "object" - } - }, - "required": [ - "projectionValuesCat" - ] - }, - "FundProfileBrokerage": { - "type": "object", - "additionalProperties": false - }, - "IncomeStatementHistory": { - "type": "object", - "properties": { - "incomeStatementHistory": { - "type": "array", - "items": { - "$ref": "#/definitions/IncomeStatementHistoryElement" - } - }, - "maxAge": { - "yahooFinanceType": "number" - } - }, - "required": [ - "incomeStatementHistory", - "maxAge" - ] - }, - "IncomeStatementHistoryElement": { - "type": "object", - "properties": { - "maxAge": { - "yahooFinanceType": "number" - }, - "endDate": { - "yahooFinanceType": "date" - }, - "totalRevenue": { - "yahooFinanceType": "number" - }, - "costOfRevenue": { - "yahooFinanceType": "number" - }, - "grossProfit": { - "yahooFinanceType": "number" - }, - "researchDevelopment": { - "yahooFinanceType": "number|null" - }, - "sellingGeneralAdministrative": { - "yahooFinanceType": "number|null" - }, - "nonRecurring": { - "yahooFinanceType": "number|null" - }, - "otherOperatingExpenses": { - "yahooFinanceType": "number|null" - }, - "totalOperatingExpenses": { - "yahooFinanceType": "number" - }, - "operatingIncome": { - "yahooFinanceType": "number|null" - }, - "totalOtherIncomeExpenseNet": { - "yahooFinanceType": "number|null" - }, - "ebit": { - "yahooFinanceType": "number" - }, - "interestExpense": { - "yahooFinanceType": "number|null" - }, - "incomeBeforeTax": { - "yahooFinanceType": "number|null" - }, - "incomeTaxExpense": { - "yahooFinanceType": "number" - }, - "minorityInterest": { - "yahooFinanceType": "number|null" - }, - "netIncomeFromContinuingOps": { - "yahooFinanceType": "number|null" - }, - "discontinuedOperations": { - "yahooFinanceType": "number|null" - }, - "extraordinaryItems": { - "yahooFinanceType": "number|null" - }, - "effectOfAccountingCharges": { - "yahooFinanceType": "number|null" - }, - "otherItems": { - "yahooFinanceType": "number|null" - }, - "netIncome": { - "yahooFinanceType": "number" - }, - "netIncomeApplicableToCommonShares": { - "yahooFinanceType": "number|null" - } - }, - "required": [ - "maxAge", - "endDate", - "totalRevenue", - "costOfRevenue", - "grossProfit", - "researchDevelopment", - "sellingGeneralAdministrative", - "nonRecurring", - "otherOperatingExpenses", - "totalOperatingExpenses", - "operatingIncome", - "totalOtherIncomeExpenseNet", - "ebit", - "interestExpense", - "incomeBeforeTax", - "incomeTaxExpense", - "minorityInterest", - "netIncomeFromContinuingOps", - "discontinuedOperations", - "extraordinaryItems", - "effectOfAccountingCharges", - "otherItems", - "netIncome", - "netIncomeApplicableToCommonShares" - ] - }, - "IndexTrend": { - "type": "object", - "properties": { - "maxAge": { - "yahooFinanceType": "number" - }, - "symbol": { - "type": "string" - }, - "peRatio": { - "yahooFinanceType": "number" - }, - "pegRatio": { - "yahooFinanceType": "number" - }, - "estimates": { - "type": "array", - "items": { - "$ref": "#/definitions/Estimate" - } - } - }, - "required": [ - "maxAge", - "symbol", - "peRatio", - "pegRatio", - "estimates" - ] - }, - "Estimate": { - "type": "object", - "properties": { - "period": { - "type": "string" - }, - "growth": { - "yahooFinanceType": "number" - } - }, - "required": [ - "period" - ] - }, - "Trend": { - "type": "object", - "properties": { - "maxAge": { - "yahooFinanceType": "number" - }, - "symbol": { - "type": "null" - }, - "estimates": { - "type": "array", - "items": {} - } - }, - "required": [ - "maxAge", - "symbol", - "estimates" - ] - }, - "Holders": { - "type": "object", - "properties": { - "holders": { - "type": "array", - "items": { - "$ref": "#/definitions/Holder" - } - }, - "maxAge": { - "yahooFinanceType": "number" - } - }, - "required": [ - "holders", - "maxAge" - ] - }, - "Holder": { - "type": "object", - "properties": { - "maxAge": { - "yahooFinanceType": "number" - }, - "name": { - "type": "string" - }, - "relation": { - "anyOf": [ - { - "$ref": "#/definitions/Relation" - }, - { - "type": "string" - } - ] - }, - "url": { - "type": "string" - }, - "transactionDescription": { - "type": "string" - }, - "latestTransDate": { - "yahooFinanceType": "date" - }, - "positionDirect": { - "yahooFinanceType": "number" - }, - "positionDirectDate": { - "yahooFinanceType": "date" - }, - "positionIndirect": { - "yahooFinanceType": "number" - }, - "positionIndirectDate": { - "yahooFinanceType": "date" - }, - "positionSummaryDate": { - "yahooFinanceType": "date" - } - }, - "required": [ - "maxAge", - "name", - "relation", - "url", - "transactionDescription", - "latestTransDate" - ] - }, - "Relation": { - "type": "string", - "enum": [ - "Chairman of the Board", - "Chief Executive Officer", - "Chief Financial Officer", - "Chief Operating Officer", - "Chief Technology Officer", - "Director", - "Director (Independent)", - "", - "General Counsel", - "Independent Non-Executive Director", - "Officer", - "President" - ] - }, - "InsiderTransactions": { - "type": "object", - "properties": { - "transactions": { - "type": "array", - "items": { - "$ref": "#/definitions/Transaction" - } - }, - "maxAge": { - "yahooFinanceType": "number" - } - }, - "required": [ - "transactions", - "maxAge" - ] - }, - "Transaction": { - "type": "object", - "properties": { - "maxAge": { - "yahooFinanceType": "number" - }, - "shares": { - "yahooFinanceType": "number" - }, - "filerUrl": { - "type": "string" - }, - "transactionText": { - "type": "string" - }, - "filerName": { - "type": "string" - }, - "filerRelation": { - "anyOf": [ - { - "$ref": "#/definitions/Relation" - }, - { - "type": "string" - } - ] - }, - "moneyText": { - "type": "string" - }, - "startDate": { - "yahooFinanceType": "date" - }, - "ownership": { - "anyOf": [ - { - "$ref": "#/definitions/OwnershipEnum" - }, - { - "type": "string" - } - ] - }, - "value": { - "yahooFinanceType": "number" - } - }, - "required": [ - "maxAge", - "shares", - "filerUrl", - "transactionText", - "filerName", - "filerRelation", - "moneyText", - "startDate", - "ownership" - ] - }, - "OwnershipEnum": { - "type": "string", - "enum": [ - "D", - "I" - ] - }, - "MajorHoldersBreakdown": { - "type": "object", - "properties": { - "maxAge": { - "yahooFinanceType": "number" - }, - "insidersPercentHeld": { - "yahooFinanceType": "number" - }, - "institutionsPercentHeld": { - "yahooFinanceType": "number" - }, - "institutionsFloatPercentHeld": { - "yahooFinanceType": "number" - }, - "institutionsCount": { - "yahooFinanceType": "number" - } - }, - "required": [ - "maxAge" - ] - }, - "NetSharePurchaseActivity": { - "type": "object", - "properties": { - "maxAge": { - "yahooFinanceType": "number" - }, - "period": { - "type": "string" - }, - "buyInfoCount": { - "yahooFinanceType": "number" - }, - "buyInfoShares": { - "yahooFinanceType": "number" - }, - "buyPercentInsiderShares": { - "yahooFinanceType": "number" - }, - "sellInfoCount": { - "yahooFinanceType": "number" - }, - "sellInfoShares": { - "yahooFinanceType": "number" - }, - "sellPercentInsiderShares": { - "yahooFinanceType": "number" - }, - "netInfoCount": { - "yahooFinanceType": "number" - }, - "netInfoShares": { - "yahooFinanceType": "number" - }, - "netPercentInsiderShares": { - "yahooFinanceType": "number" - }, - "totalInsiderShares": { - "yahooFinanceType": "number" - } - }, - "required": [ - "maxAge", - "period", - "buyInfoCount", - "buyInfoShares", - "sellInfoCount", - "netInfoCount", - "netInfoShares", - "totalInsiderShares" - ] - }, - "Price": { - "type": "object", - "properties": { - "averageDailyVolume10Day": { - "yahooFinanceType": "number" - }, - "averageDailyVolume3Month": { - "yahooFinanceType": "number" - }, - "exchange": { - "type": "string" - }, - "exchangeName": { - "type": "string" - }, - "exchangeDataDelayedBy": { - "yahooFinanceType": "number" - }, - "maxAge": { - "yahooFinanceType": "number" - }, - "postMarketChangePercent": { - "yahooFinanceType": "number" - }, - "postMarketChange": { - "yahooFinanceType": "number" - }, - "postMarketTime": { - "yahooFinanceType": "date" - }, - "postMarketPrice": { - "yahooFinanceType": "number" - }, - "postMarketSource": { - "type": "string" - }, - "preMarketChangePercent": { - "yahooFinanceType": "number" - }, - "preMarketChange": { - "yahooFinanceType": "number" - }, - "preMarketTime": { - "yahooFinanceType": "date" - }, - "preMarketPrice": { - "yahooFinanceType": "number" - }, - "preMarketSource": { - "type": "string" - }, - "priceHint": { - "yahooFinanceType": "number" - }, - "regularMarketChangePercent": { - "yahooFinanceType": "number" - }, - "regularMarketChange": { - "yahooFinanceType": "number" - }, - "regularMarketTime": { - "yahooFinanceType": "date" - }, - "regularMarketPrice": { - "yahooFinanceType": "number" - }, - "regularMarketDayHigh": { - "yahooFinanceType": "number" - }, - "regularMarketDayLow": { - "yahooFinanceType": "number" - }, - "regularMarketVolume": { - "yahooFinanceType": "number" - }, - "regularMarketPreviousClose": { - "yahooFinanceType": "number" - }, - "regularMarketSource": { - "type": "string" - }, - "regularMarketOpen": { - "yahooFinanceType": "number" - }, - "quoteSourceName": { - "type": "string" - }, - "quoteType": { - "type": "string" - }, - "symbol": { - "type": "string" - }, - "underlyingSymbol": { - "type": [ - "null", - "string" - ] - }, - "shortName": { - "type": [ - "null", - "string" - ] - }, - "longName": { - "type": [ - "null", - "string" - ] - }, - "lastMarket": { - "type": [ - "null", - "string" - ] - }, - "marketState": { - "type": "string" - }, - "marketCap": { - "yahooFinanceType": "number" - }, - "currency": { - "type": "string" - }, - "currencySymbol": { - "type": "string" - }, - "fromCurrency": { - "type": [ - "string", - "null" - ] - }, - "toCurrency": { - "type": [ - "string", - "null" - ] - }, - "volume24Hr": { - "yahooFinanceType": "number" - }, - "volumeAllCurrencies": { - "yahooFinanceType": "number" - }, - "circulatingSupply": { - "yahooFinanceType": "number" - }, - "expireDate": { - "yahooFinanceType": "date" - }, - "openInterest": { - "yahooFinanceType": "number" - } - }, - "required": [ - "maxAge", - "priceHint", - "quoteType", - "symbol", - "underlyingSymbol", - "shortName", - "longName", - "lastMarket", - "fromCurrency" - ] - }, - "QuoteType": { - "type": "object", - "properties": { - "exchange": { - "type": "string" - }, - "quoteType": { - "type": "string" - }, - "symbol": { - "type": "string" - }, - "underlyingSymbol": { - "type": "string" - }, - "shortName": { - "type": [ - "null", - "string" - ] - }, - "longName": { - "type": [ - "null", - "string" - ] - }, - "firstTradeDateEpochUtc": { - "yahooFinanceType": "date|null" - }, - "timeZoneFullName": { - "type": "string" - }, - "timeZoneShortName": { - "type": "string" - }, - "uuid": { - "type": "string" - }, - "messageBoardId": { - "type": [ - "null", - "string" - ] - }, - "gmtOffSetMilliseconds": { - "yahooFinanceType": "number" - }, - "maxAge": { - "yahooFinanceType": "number" - } - }, - "required": [ - "exchange", - "quoteType", - "symbol", - "underlyingSymbol", - "shortName", - "longName", - "firstTradeDateEpochUtc", - "timeZoneFullName", - "timeZoneShortName", - "uuid", - "gmtOffSetMilliseconds", - "maxAge" - ] - }, - "RecommendationTrend": { - "type": "object", - "properties": { - "trend": { - "type": "array", - "items": { - "$ref": "#/definitions/RecommendationTrendTrend" - } - }, - "maxAge": { - "yahooFinanceType": "number" - } - }, - "required": [ - "trend", - "maxAge" - ] - }, - "RecommendationTrendTrend": { - "type": "object", - "properties": { - "period": { - "type": "string" - }, - "strongBuy": { - "yahooFinanceType": "number" - }, - "buy": { - "yahooFinanceType": "number" - }, - "hold": { - "yahooFinanceType": "number" - }, - "sell": { - "yahooFinanceType": "number" - }, - "strongSell": { - "yahooFinanceType": "number" - } - }, - "required": [ - "period", - "strongBuy", - "buy", - "hold", - "sell", - "strongSell" - ] - }, - "SECFilings": { - "type": "object", - "properties": { - "filings": { - "type": "array", - "items": { - "$ref": "#/definitions/Filing" - } - }, - "maxAge": { - "yahooFinanceType": "number" - } - }, - "required": [ - "filings", - "maxAge" - ] - }, - "Filing": { - "type": "object", - "properties": { - "date": { - "type": "string" - }, - "epochDate": { - "yahooFinanceType": "date" - }, - "type": { - "type": "string", - "enum": [ - "10-K", - "10-Q", - "8-K", - "8-K/A", - "10-K/A", - "10-Q/A", - "SD", - "PX14A6G", - "SC 13G/A", - "DEFA14A", - "25-NSE", - "S-8 POS", - "6-K", - "F-3ASR", - "SC 13D/A", - "20-F", - "425", - "SC14D9C", - "SC 13G", - "S-8", - "DEF 14A", - "F-10" - ] - }, - "title": { - "type": "string" - }, - "edgarUrl": { - "type": "string" - }, - "maxAge": { - "yahooFinanceType": "number" - }, - "url": { - "type": "string" - }, - "exhibits": { - "type": "array", - "items": { - "type": "object", - "properties": { - "type": { - "type": "string" - }, - "url": { - "type": "string" - }, - "downloadUrl": { - "type": "string" - } - }, - "required": [ - "type", - "url" - ], - "additionalProperties": false - } - } - }, - "required": [ - "date", - "epochDate", - "type", - "title", - "edgarUrl", - "maxAge" - ] - }, - "SummaryDetail": { - "type": "object", - "properties": { - "maxAge": { - "yahooFinanceType": "number" - }, - "priceHint": { - "yahooFinanceType": "number" - }, - "previousClose": { - "yahooFinanceType": "number" - }, - "open": { - "yahooFinanceType": "number" - }, - "dayLow": { - "yahooFinanceType": "number" - }, - "dayHigh": { - "yahooFinanceType": "number" - }, - "regularMarketPreviousClose": { - "yahooFinanceType": "number" - }, - "regularMarketOpen": { - "yahooFinanceType": "number" - }, - "regularMarketDayLow": { - "yahooFinanceType": "number" - }, - "regularMarketDayHigh": { - "yahooFinanceType": "number" - }, - "regularMarketVolume": { - "yahooFinanceType": "number" - }, - "dividendRate": { - "yahooFinanceType": "number" - }, - "dividendYield": { - "yahooFinanceType": "number" - }, - "exDividendDate": { - "yahooFinanceType": "date" - }, - "payoutRatio": { - "yahooFinanceType": "number" - }, - "fiveYearAvgDividendYield": { - "yahooFinanceType": "number" - }, - "beta": { - "yahooFinanceType": "number" - }, - "trailingPE": { - "yahooFinanceType": "number" - }, - "forwardPE": { - "yahooFinanceType": "number" - }, - "volume": { - "yahooFinanceType": "number" - }, - "averageVolume": { - "yahooFinanceType": "number" - }, - "averageVolume10days": { - "yahooFinanceType": "number" - }, - "averageDailyVolume10Day": { - "yahooFinanceType": "number" - }, - "bid": { - "yahooFinanceType": "number" - }, - "ask": { - "yahooFinanceType": "number" - }, - "bidSize": { - "yahooFinanceType": "number" - }, - "askSize": { - "yahooFinanceType": "number" - }, - "marketCap": { - "yahooFinanceType": "number" - }, - "fiftyDayAverage": { - "yahooFinanceType": "number" - }, - "fiftyTwoWeekLow": { - "yahooFinanceType": "number" - }, - "fiftyTwoWeekHigh": { - "yahooFinanceType": "number" - }, - "twoHundredDayAverage": { - "yahooFinanceType": "number" - }, - "priceToSalesTrailing12Months": { - "yahooFinanceType": "number" - }, - "trailingAnnualDividendRate": { - "yahooFinanceType": "number" - }, - "trailingAnnualDividendYield": { - "yahooFinanceType": "number" - }, - "currency": { - "type": "string" - }, - "algorithm": { - "type": "null" - }, - "tradeable": { - "type": "boolean" - }, - "yield": { - "yahooFinanceType": "number" - }, - "totalAssets": { - "yahooFinanceType": "number" - }, - "navPrice": { - "yahooFinanceType": "number" - }, - "ytdReturn": { - "yahooFinanceType": "number" - }, - "fromCurrency": { - "type": [ - "string", - "null" - ] - }, - "toCurrency": { - "type": [ - "string", - "null" - ] - }, - "lastMarket": { - "type": [ - "string", - "null" - ] - }, - "volume24Hr": { - "yahooFinanceType": "number" - }, - "volumeAllCurrencies": { - "yahooFinanceType": "number" - }, - "circulatingSupply": { - "yahooFinanceType": "number" - }, - "startDate": { - "yahooFinanceType": "date" - }, - "coinMarketCapLink": { - "type": [ - "string", - "null" - ] - }, - "expireDate": { - "yahooFinanceType": "date" - }, - "openInterest": { - "yahooFinanceType": "number" - } - }, - "required": [ - "maxAge", - "priceHint", - "currency", - "algorithm", - "tradeable", - "fromCurrency", - "lastMarket" - ] - }, - "SummaryProfile": { - "type": "object", - "properties": { - "address1": { - "type": "string" - }, - "address2": { - "type": "string" - }, - "address3": { - "type": "string" - }, - "city": { - "type": "string" - }, - "state": { - "type": "string" - }, - "zip": { - "type": "string" - }, - "country": { - "type": "string" - }, - "phone": { - "type": "string" - }, - "fax": { - "type": "string" - }, - "website": { - "type": "string" - }, - "industry": { - "type": "string" - }, - "industryDisp": { - "type": "string" - }, - "sector": { - "type": "string" - }, - "sectorDisp": { - "type": "string" - }, - "longBusinessSummary": { - "type": "string" - }, - "fullTimeEmployees": { - "yahooFinanceType": "number" - }, - "companyOfficers": { - "type": "array", - "items": {} - }, - "maxAge": { - "yahooFinanceType": "number" - }, - "twitter": { - "type": "string" - }, - "name": { - "type": "string" - }, - "startDate": { - "yahooFinanceType": "date" - }, - "description": { - "type": "string" - } - }, - "required": [ - "companyOfficers", - "maxAge" - ] - }, - "TopHoldings": { - "type": "object", - "properties": { - "maxAge": { - "yahooFinanceType": "number" - }, - "stockPosition": { - "yahooFinanceType": "number" - }, - "bondPosition": { - "yahooFinanceType": "number" - }, - "holdings": { - "type": "array", - "items": { - "$ref": "#/definitions/TopHoldingsHolding" - } - }, - "equityHoldings": { - "$ref": "#/definitions/TopHoldingsEquityHoldings" - }, - "bondHoldings": { - "type": "object" - }, - "bondRatings": { - "type": "array", - "items": { - "$ref": "#/definitions/TopHoldingsBondRating" - } - }, - "sectorWeightings": { - "type": "array", - "items": { - "$ref": "#/definitions/TopHoldingsSectorWeighting" - } - }, - "cashPosition": { - "yahooFinanceType": "number" - }, - "otherPosition": { - "yahooFinanceType": "number" - }, - "preferredPosition": { - "yahooFinanceType": "number" - }, - "convertiblePosition": { - "yahooFinanceType": "number" - } - }, - "required": [ - "maxAge", - "holdings", - "equityHoldings", - "bondHoldings", - "bondRatings", - "sectorWeightings" - ] - }, - "TopHoldingsHolding": { - "type": "object", - "properties": { - "symbol": { - "type": "string" - }, - "holdingName": { - "type": "string" - }, - "holdingPercent": { - "yahooFinanceType": "number" - } - }, - "required": [ - "symbol", - "holdingName", - "holdingPercent" - ] - }, - "TopHoldingsEquityHoldings": { - "type": "object", - "properties": { - "medianMarketCap": { - "yahooFinanceType": "number" - }, - "medianMarketCapCat": { - "yahooFinanceType": "number" - }, - "priceToBook": { - "yahooFinanceType": "number" - }, - "priceToBookCat": { - "yahooFinanceType": "number" - }, - "priceToCashflow": { - "yahooFinanceType": "number" - }, - "priceToCashflowCat": { - "yahooFinanceType": "number" - }, - "priceToEarnings": { - "yahooFinanceType": "number" - }, - "priceToEarningsCat": { - "yahooFinanceType": "number" - }, - "priceToSales": { - "yahooFinanceType": "number" - }, - "priceToSalesCat": { - "yahooFinanceType": "number" - }, - "threeYearEarningsGrowth": { - "yahooFinanceType": "number" - }, - "threeYearEarningsGrowthCat": { - "yahooFinanceType": "number" - } - }, - "required": [ - "priceToBook", - "priceToCashflow", - "priceToEarnings", - "priceToSales" - ] - }, - "TopHoldingsBondRating": { - "type": "object", - "properties": { - "a": { - "yahooFinanceType": "number" - }, - "aa": { - "yahooFinanceType": "number" - }, - "aaa": { - "yahooFinanceType": "number" - }, - "other": { - "yahooFinanceType": "number" - }, - "b": { - "yahooFinanceType": "number" - }, - "bb": { - "yahooFinanceType": "number" - }, - "bbb": { - "yahooFinanceType": "number" - }, - "below_b": { - "yahooFinanceType": "number" - }, - "us_government": { - "yahooFinanceType": "number" - } - } - }, - "TopHoldingsSectorWeighting": { - "type": "object", - "properties": { - "realestate": { - "yahooFinanceType": "number" - }, - "consumer_cyclical": { - "yahooFinanceType": "number" - }, - "basic_materials": { - "yahooFinanceType": "number" - }, - "consumer_defensive": { - "yahooFinanceType": "number" - }, - "technology": { - "yahooFinanceType": "number" - }, - "communication_services": { - "yahooFinanceType": "number" - }, - "financial_services": { - "yahooFinanceType": "number" - }, - "utilities": { - "yahooFinanceType": "number" - }, - "industrials": { - "yahooFinanceType": "number" - }, - "energy": { - "yahooFinanceType": "number" - }, - "healthcare": { - "yahooFinanceType": "number" - } - } - }, - "UpgradeDowngradeHistory": { - "type": "object", - "properties": { - "history": { - "type": "array", - "items": { - "$ref": "#/definitions/UpgradeDowngradeHistoryHistory" - } - }, - "maxAge": { - "yahooFinanceType": "number" - } - }, - "required": [ - "history", - "maxAge" - ] - }, - "UpgradeDowngradeHistoryHistory": { - "type": "object", - "properties": { - "epochGradeDate": { - "yahooFinanceType": "date" - }, - "firm": { - "type": "string" - }, - "toGrade": { - "$ref": "#/definitions/Grade" - }, - "fromGrade": { - "$ref": "#/definitions/Grade" - }, - "action": { - "$ref": "#/definitions/Action" - } - }, - "required": [ - "epochGradeDate", - "firm", - "toGrade", - "action" - ] - }, - "Grade": { - "type": "string", - "enum": [ - "Accumulate", - "Add", - "Average", - "Below Average", - "Buy", - "Conviction Buy", - "", - "Equal-Weight", - "Fair Value", - "Equal-weight", - "Long-term Buy", - "Hold", - "Long-Term Buy", - "Market Outperform", - "Market Perform", - "Mixed", - "Negative", - "Neutral", - "In-Line", - "Outperform", - "Overweight", - "Peer Perform", - "Perform", - "Positive", - "Reduce", - "Sector Outperform", - "Sector Perform", - "Sector Weight", - "Sell", - "Strong Buy", - "Top Pick", - "Underperform", - "Underperformer", - "Underweight", - "Trim", - "Above Average", - "In-line", - "Outperformer", - "OVerweight", - "Cautious", - "Market Weight", - "Sector Underperform", - "Market Underperform", - "Peer perform", - "Gradually Accumulate", - "Action List Buy", - "Performer", - "Sector Performer", - "Speculative Buy", - "Strong Sell", - "Speculative Hold", - "Not Rated", - "Hold Neutral", - "Developing", - "buy", - "HOld", - "Trading Sell", - "Tender", - "market perform", - "BUy" - ] - }, - "Action": { - "type": "string", - "enum": [ - "down", - "init", - "main", - "reit", - "up" - ] - }, - "NamedParameters": { - "type": "object", - "properties": { - "this": { - "$ref": "#/definitions/ModuleThis" - }, - "symbol": { - "type": "string" - }, - "queryOptionsOverrides": { - "$ref": "#/definitions/QuoteSummaryOptions" - }, - "moduleOptions": { - "$ref": "#/definitions/ModuleOptions" - } - }, - "required": [ - "this", - "symbol" - ], - "additionalProperties": false - }, - "QuoteSummaryOptions": { - "type": "object", - "properties": { - "formatted": { - "type": "boolean" - }, - "modules": { - "anyOf": [ - { - "type": "array", - "items": { - "$ref": "#/definitions/QuoteSummaryModules" - } - }, - { - "type": "string", - "const": "all" - } - ] - } - }, - "additionalProperties": false - }, - "QuoteSummaryModules": { - "type": "string", - "enum": [ - "assetProfile", - "balanceSheetHistory", - "balanceSheetHistoryQuarterly", - "calendarEvents", - "cashflowStatementHistory", - "cashflowStatementHistoryQuarterly", - "defaultKeyStatistics", - "earnings", - "earningsHistory", - "earningsTrend", - "financialData", - "fundOwnership", - "fundPerformance", - "fundProfile", - "incomeStatementHistory", - "incomeStatementHistoryQuarterly", - "indexTrend", - "industryTrend", - "insiderHolders", - "insiderTransactions", - "institutionOwnership", - "majorDirectHolders", - "majorHoldersBreakdown", - "netSharePurchaseActivity", - "price", - "quoteType", - "recommendationTrend", - "secFilings", - "sectorTrend", - "summaryDetail", - "summaryProfile", - "topHoldings", - "upgradeDowngradeHistory" - ] - }, - "NamedParameters": { - "type": "object", - "properties": { - "this": { - "$ref": "#/definitions/ModuleThis" - }, - "query": { - "anyOf": [ - { - "type": "string" - }, - { - "type": "array", - "items": { - "type": "string" - } - } - ] - }, - "queryOptionsOverrides": { - "$ref": "#/definitions/RecommendationsBySymbolOptions" - }, - "moduleOptions": { - "$ref": "#/definitions/ModuleOptions" - } - }, - "required": [ - "this", - "query" - ], - "additionalProperties": false - }, - "RecommendationsBySymbolOptions": { - "type": "object", - "additionalProperties": false - }, - "RecommendationsBySymbolResponse": { - "type": "object", - "properties": { - "recommendedSymbols": { - "type": "array", - "items": { - "type": "object", - "properties": { - "score": { - "yahooFinanceType": "number" - }, - "symbol": { - "type": "string" - } - }, - "required": [ - "score", - "symbol" - ] - } - }, - "symbol": { - "type": "string" - } - }, - "required": [ - "recommendedSymbols", - "symbol" - ] - }, - "RecommendationsBySymbolResponseArray": { - "type": "array", - "items": { - "$ref": "#/definitions/RecommendationsBySymbolResponse" - } - }, - "NamedParameters": { - "type": "object", - "properties": { - "this": { - "$ref": "#/definitions/ModuleThis" - }, - "queryOptionsOverrides": { - "$ref": "#/definitions/ScreenerOptions" - }, - "moduleOptions": { - "$ref": "#/definitions/ModuleOptions" - } - }, - "required": [ - "this" - ], - "additionalProperties": false - }, - "ScreenerOptions": { - "type": "object", - "properties": { - "lang": { - "type": "string" - }, - "region": { - "type": "string" - }, - "scrIds": { - "$ref": "#/definitions/PredefinedScreenerModules" - }, - "count": { - "yahooFinanceType": "number" - } - }, - "required": [ - "scrIds" - ], - "additionalProperties": false - }, - "PredefinedScreenerModules": { - "type": "string", - "enum": [ - "aggressive_small_caps", - "conservative_foreign_funds", - "day_gainers", - "day_losers", - "growth_technology_stocks", - "high_yield_bond", - "most_actives", - "most_shorted_stocks", - "portfolio_anchors", - "small_cap_gainers", - "solid_large_growth_funds", - "solid_midcap_growth_funds", - "top_mutual_funds", - "undervalued_growth_stocks", - "undervalued_large_caps" - ] - }, - "ScreenerResult": { - "type": "object", - "properties": { - "id": { - "type": "string" - }, - "title": { - "type": "string" - }, - "description": { - "type": "string" - }, - "canonicalName": { - "type": "string" - }, - "criteriaMeta": { - "$ref": "#/definitions/ScreenerCriteriaMeta" - }, - "rawCriteria": { - "type": "string" - }, - "start": { - "yahooFinanceType": "number" - }, - "count": { - "yahooFinanceType": "number" - }, - "total": { - "yahooFinanceType": "number" - }, - "quotes": { - "type": "array", - "items": { - "$ref": "#/definitions/ScreenerQuote" - } - }, - "useRecords": { - "type": "boolean" - }, - "predefinedScr": { - "type": "boolean" - }, - "versionId": { - "yahooFinanceType": "number" - }, - "creationDate": { - "yahooFinanceType": "number" - }, - "lastUpdated": { - "yahooFinanceType": "number" - }, - "isPremium": { - "type": "boolean" - }, - "iconUrl": { - "type": "string" - } - }, - "required": [ - "id", - "title", - "description", - "canonicalName", - "criteriaMeta", - "rawCriteria", - "start", - "count", - "total", - "quotes", - "useRecords", - "predefinedScr", - "versionId", - "creationDate", - "lastUpdated", - "isPremium", - "iconUrl" - ], - "additionalProperties": false - }, - "ScreenerCriteriaMeta": { - "type": "object", - "properties": { - "size": { - "yahooFinanceType": "number" - }, - "offset": { - "yahooFinanceType": "number" - }, - "sortField": { - "type": "string" - }, - "sortType": { - "type": "string" - }, - "quoteType": { - "type": "string" - }, - "criteria": { - "type": "array", - "items": { - "$ref": "#/definitions/ScreenerCriterum" - } - }, - "topOperator": { - "type": "string" - } - }, - "required": [ - "size", - "offset", - "sortField", - "sortType", - "quoteType", - "criteria", - "topOperator" - ], - "additionalProperties": false - }, - "ScreenerCriterum": { - "type": "object", - "properties": { - "field": { - "type": "string" - }, - "operators": { - "type": "array", - "items": { - "type": "string" - } - }, - "values": { - "type": "array", - "items": { - "yahooFinanceType": "number" - } - }, - "labelsSelected": { - "type": "array", - "items": { - "yahooFinanceType": "number" - } - }, - "dependentValues": { - "type": "array", - "items": {} - } - }, - "required": [ - "field", - "operators", - "values", - "labelsSelected", - "dependentValues" - ], - "additionalProperties": false - }, - "ScreenerQuote": { - "type": "object", - "properties": { - "language": { - "type": "string" - }, - "region": { - "type": "string" - }, - "quoteType": { - "type": "string" - }, - "typeDisp": { - "type": "string" - }, - "quoteSourceName": { - "type": "string" - }, - "triggerable": { - "type": "boolean" - }, - "customPriceAlertConfidence": { - "type": "string" - }, - "lastCloseTevEbitLtm": { - "yahooFinanceType": "number" - }, - "lastClosePriceToNNWCPerShare": { - "yahooFinanceType": "number" - }, - "firstTradeDateMilliseconds": { - "yahooFinanceType": "number" - }, - "priceHint": { - "yahooFinanceType": "number" - }, - "postMarketChangePercent": { - "yahooFinanceType": "number" - }, - "postMarketTime": { - "yahooFinanceType": "number" - }, - "postMarketPrice": { - "yahooFinanceType": "number" - }, - "postMarketChange": { - "yahooFinanceType": "number" - }, - "regularMarketChange": { - "yahooFinanceType": "number" - }, - "regularMarketTime": { - "yahooFinanceType": "number" - }, - "regularMarketPrice": { - "yahooFinanceType": "number" - }, - "regularMarketDayHigh": { - "yahooFinanceType": "number" - }, - "regularMarketDayRange": { - "type": "string" - }, - "currency": { - "type": "string" - }, - "regularMarketDayLow": { - "yahooFinanceType": "number" - }, - "regularMarketVolume": { - "yahooFinanceType": "number" - }, - "regularMarketPreviousClose": { - "yahooFinanceType": "number" - }, - "bid": { - "yahooFinanceType": "number" - }, - "ask": { - "yahooFinanceType": "number" - }, - "bidSize": { - "yahooFinanceType": "number" - }, - "askSize": { - "yahooFinanceType": "number" - }, - "market": { - "type": "string" - }, - "messageBoardId": { - "type": "string" - }, - "fullExchangeName": { - "type": "string" - }, - "longName": { - "type": "string" - }, - "financialCurrency": { - "type": "string" - }, - "regularMarketOpen": { - "yahooFinanceType": "number" - }, - "averageDailyVolume3Month": { - "yahooFinanceType": "number" - }, - "averageDailyVolume10Day": { - "yahooFinanceType": "number" - }, - "fiftyTwoWeekLowChange": { - "yahooFinanceType": "number" - }, - "fiftyTwoWeekLowChangePercent": { - "yahooFinanceType": "number" - }, - "fiftyTwoWeekRange": { - "type": "string" - }, - "fiftyTwoWeekHighChange": { - "yahooFinanceType": "number" - }, - "fiftyTwoWeekHighChangePercent": { - "yahooFinanceType": "number" - }, - "fiftyTwoWeekChangePercent": { - "yahooFinanceType": "number" - }, - "earningsTimestamp": { - "yahooFinanceType": "number" - }, - "earningsTimestampStart": { - "yahooFinanceType": "number" - }, - "earningsTimestampEnd": { - "yahooFinanceType": "number" - }, - "trailingAnnualDividendRate": { - "yahooFinanceType": "number" - }, - "trailingAnnualDividendYield": { - "yahooFinanceType": "number" - }, - "marketState": { - "type": "string" - }, - "epsTrailingTwelveMonths": { - "yahooFinanceType": "number" - }, - "epsForward": { - "yahooFinanceType": "number" - }, - "epsCurrentYear": { - "yahooFinanceType": "number" - }, - "priceEpsCurrentYear": { - "yahooFinanceType": "number" - }, - "sharesOutstanding": { - "yahooFinanceType": "number" - }, - "bookValue": { - "yahooFinanceType": "number" - }, - "fiftyDayAverage": { - "yahooFinanceType": "number" - }, - "fiftyDayAverageChange": { - "yahooFinanceType": "number" - }, - "fiftyDayAverageChangePercent": { - "yahooFinanceType": "number" - }, - "twoHundredDayAverage": { - "yahooFinanceType": "number" - }, - "twoHundredDayAverageChange": { - "yahooFinanceType": "number" - }, - "twoHundredDayAverageChangePercent": { - "yahooFinanceType": "number" - }, - "marketCap": { - "yahooFinanceType": "number" - }, - "forwardPE": { - "yahooFinanceType": "number" - }, - "priceToBook": { - "yahooFinanceType": "number" - }, - "sourceInterval": { - "yahooFinanceType": "number" - }, - "exchangeDataDelayedBy": { - "yahooFinanceType": "number" - }, - "exchangeTimezoneName": { - "type": "string" - }, - "exchangeTimezoneShortName": { - "type": "string" - }, - "gmtOffSetMilliseconds": { - "yahooFinanceType": "number" - }, - "esgPopulated": { - "type": "boolean" - }, - "tradeable": { - "type": "boolean" - }, - "cryptoTradeable": { - "type": "boolean" - }, - "exchange": { - "type": "string" - }, - "fiftyTwoWeekLow": { - "yahooFinanceType": "number" - }, - "fiftyTwoWeekHigh": { - "yahooFinanceType": "number" - }, - "shortName": { - "type": "string" - }, - "averageAnalystRating": { - "type": "string" - }, - "regularMarketChangePercent": { - "yahooFinanceType": "number" - }, - "symbol": { - "type": "string" - }, - "dividendDate": { - "yahooFinanceType": "number" - }, - "displayName": { - "type": "string" - }, - "trailingPE": { - "yahooFinanceType": "number" - }, - "prevName": { - "type": "string" - }, - "nameChangeDate": { - "yahooFinanceType": "number" - }, - "ipoExpectedDate": { - "yahooFinanceType": "number" - }, - "dividendYield": { - "yahooFinanceType": "number" - }, - "dividendRate": { - "yahooFinanceType": "number" - }, - "yieldTTM": { - "yahooFinanceType": "number" - }, - "peTTM": { - "yahooFinanceType": "number" - }, - "annualReturnNavY3": { - "yahooFinanceType": "number" - }, - "annualReturnNavY5": { - "yahooFinanceType": "number" - }, - "ytdReturn": { - "yahooFinanceType": "number" - }, - "trailingThreeMonthReturns": { - "yahooFinanceType": "number" - }, - "netAssets": { - "yahooFinanceType": "number" - }, - "netExpenseRatio": { - "yahooFinanceType": "number" - } - }, - "required": [ - "language", - "region", - "quoteType", - "typeDisp", - "quoteSourceName", - "triggerable", - "customPriceAlertConfidence", - "firstTradeDateMilliseconds", - "priceHint", - "regularMarketChange", - "regularMarketTime", - "regularMarketPrice", - "currency", - "regularMarketPreviousClose", - "market", - "messageBoardId", - "fullExchangeName", - "longName", - "averageDailyVolume3Month", - "averageDailyVolume10Day", - "fiftyTwoWeekLowChange", - "fiftyTwoWeekLowChangePercent", - "fiftyTwoWeekRange", - "fiftyTwoWeekHighChange", - "fiftyTwoWeekHighChangePercent", - "fiftyTwoWeekChangePercent", - "marketState", - "fiftyDayAverage", - "fiftyDayAverageChange", - "fiftyDayAverageChangePercent", - "twoHundredDayAverage", - "twoHundredDayAverageChange", - "twoHundredDayAverageChangePercent", - "sourceInterval", - "exchangeDataDelayedBy", - "exchangeTimezoneName", - "exchangeTimezoneShortName", - "gmtOffSetMilliseconds", - "esgPopulated", - "tradeable", - "cryptoTradeable", - "exchange", - "fiftyTwoWeekLow", - "fiftyTwoWeekHigh", - "shortName", - "regularMarketChangePercent", - "symbol" - ], - "additionalProperties": false - }, - "NamedParameters": { - "type": "object", - "properties": { - "this": { - "$ref": "#/definitions/ModuleThis" - }, - "query": { - "type": "string" - }, - "queryOptionsOverrides": { - "$ref": "#/definitions/SearchOptions" - }, - "moduleOptions": { - "$ref": "#/definitions/ModuleOptions" - } - }, - "required": [ - "this", - "query" - ], - "additionalProperties": false - }, - "SearchOptions": { - "type": "object", - "properties": { - "lang": { - "type": "string" - }, - "region": { - "type": "string" - }, - "quotesCount": { - "yahooFinanceType": "number" - }, - "newsCount": { - "yahooFinanceType": "number" - }, - "enableFuzzyQuery": { - "type": "boolean" - }, - "quotesQueryId": { - "type": "string" - }, - "multiQuoteQueryId": { - "type": "string" - }, - "newsQueryId": { - "type": "string" - }, - "enableCb": { - "type": "boolean" - }, - "enableNavLinks": { - "type": "boolean" - }, - "enableEnhancedTrivialQuery": { - "type": "boolean" - } - }, - "additionalProperties": false - }, - "SearchQuoteYahoo": { - "type": "object", - "properties": { - "symbol": { - "type": "string" - }, - "isYahooFinance": { - "type": "boolean", - "const": true - }, - "exchange": { - "type": "string" - }, - "exchDisp": { - "type": "string" - }, - "shortname": { - "type": "string" - }, - "longname": { - "type": "string" - }, - "index": { - "type": "string", - "const": "quotes" - }, - "score": { - "yahooFinanceType": "number" - }, - "newListingDate": { - "yahooFinanceType": "date" - }, - "prevName": { - "type": "string" - }, - "nameChangeDate": { - "yahooFinanceType": "date" - }, - "sector": { - "type": "string" - }, - "industry": { - "type": "string" - }, - "dispSecIndFlag": { - "type": "boolean" - } - }, - "required": [ - "symbol", - "isYahooFinance", - "exchange", - "index", - "score" - ] - }, - "SearchQuoteYahooEquity": { - "type": "object", - "properties": { - "symbol": { - "type": "string" - }, - "isYahooFinance": { - "type": "boolean", - "const": true - }, - "exchange": { - "type": "string" - }, - "exchDisp": { - "type": "string" - }, - "shortname": { - "type": "string" - }, - "longname": { - "type": "string" - }, - "index": { - "type": "string", - "const": "quotes" - }, - "score": { - "yahooFinanceType": "number" - }, - "newListingDate": { - "yahooFinanceType": "date" - }, - "prevName": { - "type": "string" - }, - "nameChangeDate": { - "yahooFinanceType": "date" - }, - "sector": { - "type": "string" - }, - "industry": { - "type": "string" - }, - "dispSecIndFlag": { - "type": "boolean" - }, - "quoteType": { - "type": "string", - "const": "EQUITY" - }, - "typeDisp": { - "type": "string", - "const": "Equity" - } - }, - "required": [ - "exchange", - "index", - "isYahooFinance", - "quoteType", - "score", - "symbol", - "typeDisp" - ] - }, - "SearchQuoteYahooOption": { - "type": "object", - "properties": { - "symbol": { - "type": "string" - }, - "isYahooFinance": { - "type": "boolean", - "const": true - }, - "exchange": { - "type": "string" - }, - "exchDisp": { - "type": "string" - }, - "shortname": { - "type": "string" - }, - "longname": { - "type": "string" - }, - "index": { - "type": "string", - "const": "quotes" - }, - "score": { - "yahooFinanceType": "number" - }, - "newListingDate": { - "yahooFinanceType": "date" - }, - "prevName": { - "type": "string" - }, - "nameChangeDate": { - "yahooFinanceType": "date" - }, - "sector": { - "type": "string" - }, - "industry": { - "type": "string" - }, - "dispSecIndFlag": { - "type": "boolean" - }, - "quoteType": { - "type": "string", - "const": "OPTION" - }, - "typeDisp": { - "type": "string", - "const": "Option" - } - }, - "required": [ - "exchange", - "index", - "isYahooFinance", - "quoteType", - "score", - "symbol", - "typeDisp" - ] - }, - "SearchQuoteYahooETF": { - "type": "object", - "properties": { - "symbol": { - "type": "string" - }, - "isYahooFinance": { - "type": "boolean", - "const": true - }, - "exchange": { - "type": "string" - }, - "exchDisp": { - "type": "string" - }, - "shortname": { - "type": "string" - }, - "longname": { - "type": "string" - }, - "index": { - "type": "string", - "const": "quotes" - }, - "score": { - "yahooFinanceType": "number" - }, - "newListingDate": { - "yahooFinanceType": "date" - }, - "prevName": { - "type": "string" - }, - "nameChangeDate": { - "yahooFinanceType": "date" - }, - "sector": { - "type": "string" - }, - "industry": { - "type": "string" - }, - "dispSecIndFlag": { - "type": "boolean" - }, - "quoteType": { - "type": "string", - "const": "ETF" - }, - "typeDisp": { - "type": "string", - "const": "ETF" - } - }, - "required": [ - "exchange", - "index", - "isYahooFinance", - "quoteType", - "score", - "symbol", - "typeDisp" - ] - }, - "SearchQuoteYahooFund": { - "type": "object", - "properties": { - "symbol": { - "type": "string" - }, - "isYahooFinance": { - "type": "boolean", - "const": true - }, - "exchange": { - "type": "string" - }, - "exchDisp": { - "type": "string" - }, - "shortname": { - "type": "string" - }, - "longname": { - "type": "string" - }, - "index": { - "type": "string", - "const": "quotes" - }, - "score": { - "yahooFinanceType": "number" - }, - "newListingDate": { - "yahooFinanceType": "date" - }, - "prevName": { - "type": "string" - }, - "nameChangeDate": { - "yahooFinanceType": "date" - }, - "sector": { - "type": "string" - }, - "industry": { - "type": "string" - }, - "dispSecIndFlag": { - "type": "boolean" - }, - "quoteType": { - "type": "string", - "const": "MUTUALFUND" - }, - "typeDisp": { - "type": "string", - "const": "Fund" - } - }, - "required": [ - "exchange", - "index", - "isYahooFinance", - "quoteType", - "score", - "symbol", - "typeDisp" - ] - }, - "SearchQuoteYahooIndex": { - "type": "object", - "properties": { - "symbol": { - "type": "string" - }, - "isYahooFinance": { - "type": "boolean", - "const": true - }, - "exchange": { - "type": "string" - }, - "exchDisp": { - "type": "string" - }, - "shortname": { - "type": "string" - }, - "longname": { - "type": "string" - }, - "index": { - "type": "string", - "const": "quotes" - }, - "score": { - "yahooFinanceType": "number" - }, - "newListingDate": { - "yahooFinanceType": "date" - }, - "prevName": { - "type": "string" - }, - "nameChangeDate": { - "yahooFinanceType": "date" - }, - "sector": { - "type": "string" - }, - "industry": { - "type": "string" - }, - "dispSecIndFlag": { - "type": "boolean" - }, - "quoteType": { - "type": "string", - "const": "INDEX" - }, - "typeDisp": { - "type": "string", - "const": "Index" - } - }, - "required": [ - "exchange", - "index", - "isYahooFinance", - "quoteType", - "score", - "symbol", - "typeDisp" - ] - }, - "SearchQuoteYahooCurrency": { - "type": "object", - "properties": { - "symbol": { - "type": "string" - }, - "isYahooFinance": { - "type": "boolean", - "const": true - }, - "exchange": { - "type": "string" - }, - "exchDisp": { - "type": "string" - }, - "shortname": { - "type": "string" - }, - "longname": { - "type": "string" - }, - "index": { - "type": "string", - "const": "quotes" - }, - "score": { - "yahooFinanceType": "number" - }, - "newListingDate": { - "yahooFinanceType": "date" - }, - "prevName": { - "type": "string" - }, - "nameChangeDate": { - "yahooFinanceType": "date" - }, - "sector": { - "type": "string" - }, - "industry": { - "type": "string" - }, - "dispSecIndFlag": { - "type": "boolean" - }, - "quoteType": { - "type": "string", - "const": "CURRENCY" - }, - "typeDisp": { - "type": "string", - "const": "Currency" - } - }, - "required": [ - "exchange", - "index", - "isYahooFinance", - "quoteType", - "score", - "symbol", - "typeDisp" - ] - }, - "SearchQuoteYahooCryptocurrency": { - "type": "object", - "properties": { - "symbol": { - "type": "string" - }, - "isYahooFinance": { - "type": "boolean", - "const": true - }, - "exchange": { - "type": "string" - }, - "exchDisp": { - "type": "string" - }, - "shortname": { - "type": "string" - }, - "longname": { - "type": "string" - }, - "index": { - "type": "string", - "const": "quotes" - }, - "score": { - "yahooFinanceType": "number" - }, - "newListingDate": { - "yahooFinanceType": "date" - }, - "prevName": { - "type": "string" - }, - "nameChangeDate": { - "yahooFinanceType": "date" - }, - "sector": { - "type": "string" - }, - "industry": { - "type": "string" - }, - "dispSecIndFlag": { - "type": "boolean" - }, - "quoteType": { - "type": "string", - "const": "CRYPTOCURRENCY" - }, - "typeDisp": { - "type": "string", - "const": "Cryptocurrency" - } - }, - "required": [ - "exchange", - "index", - "isYahooFinance", - "quoteType", - "score", - "symbol", - "typeDisp" - ] - }, - "SearchQuoteYahooFuture": { - "type": "object", - "properties": { - "symbol": { - "type": "string" - }, - "isYahooFinance": { - "type": "boolean", - "const": true - }, - "exchange": { - "type": "string" - }, - "exchDisp": { - "type": "string" - }, - "shortname": { - "type": "string" - }, - "longname": { - "type": "string" - }, - "index": { - "type": "string", - "const": "quotes" - }, - "score": { - "yahooFinanceType": "number" - }, - "newListingDate": { - "yahooFinanceType": "date" - }, - "prevName": { - "type": "string" - }, - "nameChangeDate": { - "yahooFinanceType": "date" - }, - "sector": { - "type": "string" - }, - "industry": { - "type": "string" - }, - "dispSecIndFlag": { - "type": "boolean" - }, - "quoteType": { - "type": "string", - "const": "FUTURE" - }, - "typeDisp": { - "type": "string", - "enum": [ - "Future", - "Futures" - ] - } - }, - "required": [ - "exchange", - "index", - "isYahooFinance", - "quoteType", - "score", - "symbol", - "typeDisp" - ] - }, - "SearchQuoteNonYahoo": { - "type": "object", - "properties": { - "index": { - "type": "string" - }, - "name": { - "type": "string" - }, - "permalink": { - "type": "string" - }, - "isYahooFinance": { - "type": "boolean", - "const": false - } - }, - "required": [ - "index", - "name", - "permalink", - "isYahooFinance" - ] - }, - "SearchNews": { - "type": "object", - "properties": { - "uuid": { - "type": "string" - }, - "title": { - "type": "string" - }, - "publisher": { - "type": "string" - }, - "link": { - "type": "string" - }, - "providerPublishTime": { - "yahooFinanceType": "date" - }, - "type": { - "type": "string" - }, - "thumbnail": { - "type": "object", - "properties": { - "resolutions": { - "type": "array", - "items": { - "$ref": "#/definitions/SearchNewsThumbnailResolution" - } - } - }, - "required": [ - "resolutions" - ], - "additionalProperties": false - }, - "relatedTickers": { - "type": "array", - "items": { - "type": "string" - } - } - }, - "required": [ - "uuid", - "title", - "publisher", - "link", - "providerPublishTime", - "type" - ] - }, - "SearchNewsThumbnailResolution": { - "type": "object", - "properties": { - "url": { - "type": "string" - }, - "width": { - "yahooFinanceType": "number" - }, - "height": { - "yahooFinanceType": "number" - }, - "tag": { - "type": "string" - } - }, - "required": [ - "url", - "width", - "height", - "tag" - ], - "additionalProperties": false - }, - "SearchResult": { - "type": "object", - "properties": { - "explains": { - "type": "array", - "items": {} - }, - "count": { - "yahooFinanceType": "number" - }, - "quotes": { - "type": "array", - "items": { - "anyOf": [ - { - "$ref": "#/definitions/SearchQuoteYahooEquity" - }, - { - "$ref": "#/definitions/SearchQuoteYahooOption" - }, - { - "$ref": "#/definitions/SearchQuoteYahooETF" - }, - { - "$ref": "#/definitions/SearchQuoteYahooFund" - }, - { - "$ref": "#/definitions/SearchQuoteYahooIndex" - }, - { - "$ref": "#/definitions/SearchQuoteYahooCurrency" - }, - { - "$ref": "#/definitions/SearchQuoteYahooCryptocurrency" - }, - { - "$ref": "#/definitions/SearchQuoteNonYahoo" - }, - { - "$ref": "#/definitions/SearchQuoteYahooFuture" - } - ] - } - }, - "news": { - "type": "array", - "items": { - "$ref": "#/definitions/SearchNews" - } - }, - "nav": { - "type": "array", - "items": {} - }, - "lists": { - "type": "array", - "items": {} - }, - "researchReports": { - "type": "array", - "items": {} - }, - "totalTime": { - "yahooFinanceType": "number" - }, - "screenerFieldResults": { - "type": "array", - "items": {} - }, - "culturalAssets": { - "type": "array", - "items": {} - }, - "timeTakenForQuotes": { - "yahooFinanceType": "number" - }, - "timeTakenForNews": { - "yahooFinanceType": "number" - }, - "timeTakenForAlgowatchlist": { - "yahooFinanceType": "number" - }, - "timeTakenForPredefinedScreener": { - "yahooFinanceType": "number" - }, - "timeTakenForCrunchbase": { - "yahooFinanceType": "number" - }, - "timeTakenForNav": { - "yahooFinanceType": "number" - }, - "timeTakenForResearchReports": { - "yahooFinanceType": "number" - }, - "timeTakenForScreenerField": { - "yahooFinanceType": "number" - }, - "timeTakenForCulturalAssets": { - "yahooFinanceType": "number" - } - }, - "required": [ - "explains", - "count", - "quotes", - "news", - "nav", - "lists", - "researchReports", - "totalTime", - "timeTakenForQuotes", - "timeTakenForNews", - "timeTakenForAlgowatchlist", - "timeTakenForPredefinedScreener", - "timeTakenForCrunchbase", - "timeTakenForNav", - "timeTakenForResearchReports" - ] - }, - "TrendingSymbol": { - "type": "object", - "properties": { - "symbol": { - "type": "string" - } - }, - "required": [ - "symbol" - ] - }, - "TrendingSymbolsResult": { - "type": "object", - "properties": { - "count": { - "yahooFinanceType": "number" - }, - "quotes": { - "type": "array", - "items": { - "$ref": "#/definitions/TrendingSymbol" - } - }, - "jobTimestamp": { - "yahooFinanceType": "number" - }, - "startInterval": { - "yahooFinanceType": "number" - } - }, - "required": [ - "count", - "quotes", - "jobTimestamp", - "startInterval" - ] - } - } -} \ No newline at end of file diff --git a/scripts/json-transform.sh b/scripts/json-transform.sh deleted file mode 100755 index 2d3f3e50..00000000 --- a/scripts/json-transform.sh +++ /dev/null @@ -1,51 +0,0 @@ -#!/bin/sh - -echo "json-transform.sh" -echo "=================" -echo - -echo "ESM" -echo "---" - -cd dist/esm - -for FILE in $(find -name \*.json) ; do - echo "Converting \"$FILE\" to ESM module \"$FILE.js\""; - echo -n "export default " > $FILE.js - cat $FILE >> $FILE.js -done - -for FILE in $(find -name \*js) ; do - # Lines that start with 'import' and end with '.json";'. - if grep -qE '^(import .*)\.json";$' $FILE; then - echo - echo "Modifying imports in \"$FILE\" (backup saved to .orig)" - grep -E '^(import .*)\.json";$' $FILE - sed -Ei.orig 's/^(import .*)\.json";$/\1.json.js";/' $FILE - fi -done - -echo -echo "CJS" -echo "---" - -cd ../cjs - -for FILE in $(find -name \*.json) ; do - echo "Converting \"$FILE\" to ESM module \"$FILE.js\""; - echo -n "module.exports = " > $FILE.js - cat $FILE >> $FILE.js -done - -for FILE in $(find -name \*js) ; do - # Lines that start with 'import' and end with '.json";'. - if grep -qE '^(const .*)\.json"\)\);$' $FILE; then - echo - echo "Modifying imports in \"$FILE\" (backup saved to .orig)" - grep -E '^(const .*)\.json"\)\);$' $FILE - sed -Ei.orig 's/^(const .*)\.json"\)\);$/\1.json.js"));/' $FILE - fi -done - -echo -echo "json-transform.sh finished." diff --git a/scripts/schema-check.sh b/scripts/schema-check.sh deleted file mode 100755 index ac7750e2..00000000 --- a/scripts/schema-check.sh +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/sh - -cp schema.json schema.json.bak -yarn schema - -MD5SUM_OLD=$(md5sum schema.json.bak | awk '{print $1}') -MD5SUM_NEW=$(md5sum schema.json | awk '{print $1}') - -if [ "$MD5SUM_OLD" = "$MD5SUM_NEW" ] ; then - echo "[OK] schema.json is up to date - good to go!"; -else - echo "[FAIL] Please commit updated schema.json."; - exit 1; -fi diff --git a/scripts/schema.ts b/scripts/schema.ts deleted file mode 100644 index 8b2d5bd9..00000000 --- a/scripts/schema.ts +++ /dev/null @@ -1,75 +0,0 @@ -import { writeFile } from "fs"; - -import { - createProgram, - createParser, - SchemaGenerator, - createFormatter, - Config, -} from "ts-json-schema-generator"; - -// @ts-expect-error: no types -import schemaWalker from "oas-schema-walker"; -import walkerCallback from "./schema/postWalker.js"; - -import yfNumberTypeFormatter from "./schema/TypeFormatter/yfNumberTypeFormatter.js"; -import yfReferenceTypeFormatter from "./schema/TypeFormatter/yfReferenceTypeFormatter.js"; -import yfFunctionIgnorer from "./schema/TypeFormatter/yfFunctionIgnorer.js"; - -//const OUTPUT_PATH = "schema.json"; -const OUTPUT_PATH = process.stdout; - -const config: Config = { - path: "src/{modules/**/!(*spec.ts),lib/options.ts}", - tsconfig: "tsconfig.json", - type: "*", -}; - -const formatter = createFormatter( - config, - (chainTypeFormatter, circularReferenceTypeFormatter) => { - chainTypeFormatter - .addTypeFormatter( - new yfReferenceTypeFormatter( - circularReferenceTypeFormatter, - config.encodeRefs ?? true - ) - ) - .addTypeFormatter(new yfNumberTypeFormatter()) - .addTypeFormatter(new yfFunctionIgnorer()); - } -); - -const program = createProgram(config); -const parser = createParser(program, config); -const generator = new SchemaGenerator(program, parser, formatter, config); -const _schema = generator.createSchema(config.type); - -const schema = { - $schema: _schema.$schema, - $comment: - "DO NOT EDIT THIS FILE. It is generated automatically " + - "from typescript interfaces in the project. To update, run " + - "`yarn schema`.", - ..._schema, -}; - -// @ts-expect-error: no types -for (const key of Object.keys(schema.definitions)) { - // @ts-expect-error: no types - schemaWalker.walkSchema(schema.definitions[key], {}, {}, walkerCallback); -} - -const schemaString = JSON.stringify(schema, null, 2); - -function throwErr(err?: Error | null): void { - if (err) throw err; -} - -if (OUTPUT_PATH === process.stdout) { - process.stdout.write(schemaString, throwErr); -} else if (typeof OUTPUT_PATH === "string") { - writeFile(OUTPUT_PATH, schemaString, throwErr); -} else { - throw new Error("Unsupported output path"); -} diff --git a/scripts/schema/TypeFormatter/yfFunctionIgnorer.ts b/scripts/schema/TypeFormatter/yfFunctionIgnorer.ts deleted file mode 100644 index 8dc04f65..00000000 --- a/scripts/schema/TypeFormatter/yfFunctionIgnorer.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { - BaseType, - FunctionType, - Definition, - SubTypeFormatter, -} from "ts-json-schema-generator"; - -export default class yfNumberTypeFormatter implements SubTypeFormatter { - public supportsType(type: FunctionType): boolean { - return type instanceof FunctionType; - } - - public getDefinition(): Definition { - return {}; - } - - public getChildren(): BaseType[] { - return []; - } -} diff --git a/scripts/schema/TypeFormatter/yfNumberTypeFormatter.ts b/scripts/schema/TypeFormatter/yfNumberTypeFormatter.ts deleted file mode 100644 index d87a851f..00000000 --- a/scripts/schema/TypeFormatter/yfNumberTypeFormatter.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { - BaseType, - Definition, - NumberType, - SubTypeFormatter, -} from "ts-json-schema-generator"; - -export default class yfNumberTypeFormatter implements SubTypeFormatter { - public supportsType(type: NumberType): boolean { - return type instanceof NumberType; - } - - public getDefinition(_type: NumberType): Definition { - return { - // @ts-ignore - yahooFinanceType: "number", - }; - } - - public getChildren(_type: NumberType): BaseType[] { - return []; - } -} diff --git a/scripts/schema/TypeFormatter/yfReferenceTypeFormatter.ts b/scripts/schema/TypeFormatter/yfReferenceTypeFormatter.ts deleted file mode 100644 index 7c44ac64..00000000 --- a/scripts/schema/TypeFormatter/yfReferenceTypeFormatter.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { - Definition, - DefinitionTypeFormatter, - DefinitionType, -} from "ts-json-schema-generator"; - -export default class yfReferenceTypeFormatter extends DefinitionTypeFormatter { - public getDefinition(type: DefinitionType): Definition { - const ref = type.getName(); - - const types = ["TwoNumberRange", "DateInMs"]; - - if (types.includes(ref)) - return { - // @ts-ignore - yahooFinanceType: ref, - }; - else return super.getDefinition(type); - } -} diff --git a/scripts/schema/postWalker.js b/scripts/schema/postWalker.js deleted file mode 100644 index 4a9b207b..00000000 --- a/scripts/schema/postWalker.js +++ /dev/null @@ -1,74 +0,0 @@ -const isDate = (schema) => - schema.type === "string" && schema.format === "date-time"; - -const funcs = [ - /* - - // Now handled in TypeFormatter/yfReferenceTypeFormatter.ts - function TwoNumberRange(schema, parent, state) { - if (schema.$ref === "#/definitions/TwoNumberRange") { - const key = state.property.split("/").pop(); - parent.properties[key] = { yahooFinanceType: "TwoNumberRange" }; - return true; - } - }, - - // Now handled in TypeFormatter/yfReferenceTypeFormatter.ts - function DateInMs(schema, parent, state) { - if (schema.$ref === "#/definitions/DateInMs") { - const key = state.property.split("/").pop(); - parent.properties[key] = { yahooFinanceType: "DateInMs" }; - return true; - } - }, - - // Now handled in TypeFormatter/yfNumberTypeFormatter.ts - function Number(schema, parent, state) { - if (schema.type === "number") { - delete schema.type; - schema.yahooFinanceType = "number"; - return true; - } - }, - - */ - - function NumberNull(schema, parent, state) { - if (Array.isArray(schema.type)) { - if ( - schema.type.length === 2 && - schema.type.includes("number") && - schema.type.includes("null") - ) { - delete schema.type; - schema.yahooFinanceType = "number|null"; - return true; - } - } - }, - - function Date(schema, parent, state) { - const anyOf = schema.anyOf; - if ( - anyOf && - anyOf.length === 2 && - ((isDate(anyOf[0]) && anyOf[1].type === "null") || - (isDate(anyOf[1]) && anyOf[0].type === "null")) - ) { - delete schema.anyOf; - schema.yahooFinanceType = "date|null"; - return true; - } - - if (isDate(schema)) { - delete schema.format; - delete schema.type; - schema.yahooFinanceType = "date"; - return true; - } - }, -]; - -export default function callback(schema, parent, state) { - for (let func of funcs) if (func(schema, parent, state)) break; -} diff --git a/src/index-common.ts b/src/index-common.ts index 0cbc8bde..e0696154 100644 --- a/src/index-common.ts +++ b/src/index-common.ts @@ -1,10 +1,9 @@ // libs import yahooFinanceFetch from "./lib/yahooFinanceFetch.js"; -import moduleExec from "./lib/moduleExec.js"; import options from "./lib/options.js"; import errors from "./lib/errors.js"; import setGlobalConfig from "./lib/setGlobalConfig.js"; -import { disallowAdditionalProps } from "./lib/validateAndCoerceTypes.js"; +import moduleExec from "./lib/moduleExec.js"; // modules import autoc from "./modules/autoc.js"; @@ -30,7 +29,6 @@ export default { _fetch: yahooFinanceFetch, _moduleExec: moduleExec, _opts: options, - _disallowAdditionalProps: disallowAdditionalProps, // common errors, diff --git a/src/lib/errors.ts b/src/lib/errors.ts index 91a8b663..89f1f26c 100644 --- a/src/lib/errors.ts +++ b/src/lib/errors.ts @@ -1,10 +1,15 @@ -import type { ErrorObject } from "ajv/dist/types"; +import { + TransformDecodeError, + TransformDecodeCheckError, +} from "@sinclair/typebox/build/cjs/value"; // Yahoo's servers returned an HTTP 400 for this request. export class BadRequestError extends Error { name = "BadRequestError"; } +type ValidationError = TransformDecodeError | TransformDecodeCheckError; + // Yahoo's servers returned a 'not-ok' status for this request. // https://developer.mozilla.org/en-US/docs/Web/API/Response/ok export class HTTPError extends Error { @@ -24,11 +29,11 @@ export class NoEnvironmentError extends Error { export class FailedYahooValidationError extends Error { name = "FailedYahooValidationError"; result: any; - errors?: null | ErrorObject[]; + errors?: null | ValidationError[]; constructor( message: string, - { result, errors }: { result: any; errors?: null | ErrorObject[] } + { result, errors }: { result: any; errors?: null | ValidationError[] } ) { super(message); this.result = result; diff --git a/src/lib/moduleCommon.ts b/src/lib/moduleCommon.ts index e5b18f9a..9eb99dae 100644 --- a/src/lib/moduleCommon.ts +++ b/src/lib/moduleCommon.ts @@ -1,5 +1,4 @@ -//import ModuleExec from "./moduleExec.js"; -import moduleExecTypebox from "./moduleExecTypebox"; +import moduleExec from "./moduleExec"; export interface ModuleOptions { validateResult?: boolean; @@ -17,8 +16,5 @@ export interface ModuleOptionsWithValidateTrue extends ModuleOptions { export interface ModuleThis { [key: string]: any; - // TODO: should be ModuleExec function but requiring functions breaks - // schema generation because json-schema does not support functions. - _moduleExec: any; - _moduleExecTypebox: typeof moduleExecTypebox; + _moduleExec: typeof moduleExec; } diff --git a/src/lib/moduleExec.spec.ts b/src/lib/moduleExec.spec.ts index 3e3a29f8..5343f4cd 100644 --- a/src/lib/moduleExec.spec.ts +++ b/src/lib/moduleExec.spec.ts @@ -2,12 +2,13 @@ import { jest } from "@jest/globals"; import search from "../modules/search.js"; import chart from "../modules/chart.js"; -import { InvalidOptionsError } from "./errors.js"; +import { FailedYahooValidationError, InvalidOptionsError } from "./errors.js"; import testYf from "../../tests/testYf.js"; -import { TransformDecodeCheckError } from "@sinclair/typebox/value"; +import { Type } from "@sinclair/typebox"; const yf = testYf({ search, chart }); yf._opts.validation.logOptionsErrors = false; +yf._opts.validation.logErrors = false; describe("moduleExecTypebox", () => { describe("assertSymbol", () => { @@ -69,7 +70,6 @@ describe("moduleExecTypebox", () => { const rwo = (options: any) => yf.search("symbol", options); await expect(rwo({ invalid: true })).rejects.toThrow(InvalidOptionsError); console = realConsole; - expect( fakeConsole.log.mock.calls.length + fakeConsole.error.mock.calls.length + @@ -84,7 +84,7 @@ describe("moduleExecTypebox", () => { yf._opts.validation.logErrors = false; await expect( yf.search("AAPL", {}, { devel: "search-badResult.fake.json" }) - ).rejects.toThrow(TransformDecodeCheckError); + ).rejects.toThrow(FailedYahooValidationError); yf._opts.validation.logErrors = true; }); @@ -113,4 +113,113 @@ describe("moduleExecTypebox", () => { expect(fakeConsole.dir).not.toHaveBeenCalled(); }); }); + describe("correctly invokes callbacks when provided", () => { + it("Should invoke the query options transformWith function when one is provided", async () => { + const yf = testYf({ _fetch: jest.fn() }); + const overrides = { overrideKey: "thingy" }; + const optionsTransformWith = jest.fn((v: Record) => ({ + ...v, + overrideKey: "bobby", + })); + + await yf._moduleExec({ + query: { + transformWith: optionsTransformWith, + assertSymbol: false, + schema: Type.Any(), + overrides, + }, + result: { + schema: Type.Any(), + }, + }); + expect(optionsTransformWith).toHaveBeenCalledTimes(1); + expect(optionsTransformWith).toMatchInlineSnapshot(` + [MockFunction] { + "calls": [ + [ + { + "overrideKey": "thingy", + }, + ], + ], + "results": [ + { + "type": "return", + "value": { + "overrideKey": "bobby", + }, + }, + ], + } + `); + }); + it("Should invoke the result transformWith function when one is provided", async () => { + const yf = testYf({ _fetch: jest.fn(() => ({ statusCode: 200 })) }); + const resultTransformedWith = jest.fn((v: Record) => { + return { overrideKey: "bobby" }; + }); + + await yf._moduleExec({ + query: { + assertSymbol: false, + schema: Type.Any(), + }, + result: { + schema: Type.Any(), + transformWith: resultTransformedWith, + }, + }); + expect(resultTransformedWith).toHaveBeenCalledTimes(1); + expect(resultTransformedWith).toMatchInlineSnapshot(` + [MockFunction] { + "calls": [ + [ + { + "statusCode": 200, + }, + ], + ], + "results": [ + { + "type": "return", + "value": { + "overrideKey": "bobby", + }, + }, + ], + } + `); + }); + it("should throw when symbol assertion is enabled but a non-string symbol is provided", () => { + const yf = testYf({ _fetch: jest.fn() }); + expect( + async () => + await yf._moduleExec({ + query: { + assertSymbol: true, + schema: Type.Any(), + }, + result: { + schema: Type.Any(), + }, + }) + ).rejects.toThrow(); + }); + it("should pass a string symbol when symbol assertion is enabled", () => { + const yf = testYf({ _fetch: jest.fn() }); + expect( + async () => + await yf._moduleExec({ + query: { + assertSymbol: "AAPL", + schema: Type.Any(), + }, + result: { + schema: Type.Any(), + }, + }) + ).not.toThrow(); + }); + }); }); diff --git a/src/lib/moduleExec.ts b/src/lib/moduleExec.ts index f7cb6747..60f51463 100644 --- a/src/lib/moduleExec.ts +++ b/src/lib/moduleExec.ts @@ -15,18 +15,17 @@ * Further info below, inline. */ -import validateAndCoerceTypes from "./validateAndCoerceTypes.js"; +import { validateAndCoerceTypebox } from "./validateAndCoerceTypes.js"; import csv2json from "./csv2json.js"; +import { TSchema } from "@sinclair/typebox"; -// The consuming module itself will have a stricter return type. -type TransformFunc = (arg: any) => any; /* interface TransformFunc { (result: { [key: string]: any }): { [key: string]: any }; } */ -interface ModuleExecOptions { +interface ModuleExecOptions { /** * Name of the module, e.g. "search", "quoteSummary", etc. Used in error * reporting. @@ -44,10 +43,9 @@ interface ModuleExecOptions { */ url: string; /** - * Key of schema used to validate user-provider query options. - * e.g. yf.search('AAPL', { isThisAValidOption: "maybe" }) + * The schema to use to validate the options overrides */ - schemaKey: string; + schema: TSchema; /** * Defaults for this query, e.g. { period: '1d' } in history, * and other required options that aren't often changed { locale: 'en' }. @@ -69,7 +67,7 @@ interface ModuleExecOptions { * the query. Useful to transform options we allow but not Yahoo, e.g. * allow a "2020-01-01" date but transform this to a UNIX epoch. */ - transformWith?: TransformFunc; + transformWith?: (opts: TOpts) => unknown; /** * Default: 'json'. Can be 'text' or 'csv' (augments fetch's "text"). */ @@ -77,19 +75,19 @@ interface ModuleExecOptions { /** * Default: false. This request requires Yahoo cookies & crumb. */ - needsCrumb: boolean; + needsCrumb?: boolean; }; result: { /** - * Key of schema to validate (and coerce) the retruned result from Yahoo. + * The schema to validate (and coerce) the retruned result from Yahoo. */ - schemaKey: string; + schema: TSchema; /** * Mutate the Yahoo result *before* validating and coercion. Mostly used * to e.g. throw if no (resault.returnField) and return result.returnField. */ - transformWith?: TransformFunc; + transformWith?: (result: unknown) => TResult; }; moduleOptions?: { @@ -104,9 +102,10 @@ interface ModuleExecOptions { }; } -type ThisWithModExec = { [key: string]: any; _moduleExec: typeof moduleExec }; - -async function moduleExec(this: ThisWithModExec, opts: ModuleExecOptions) { +async function moduleExec( + this: { [key: string]: any }, + opts: ModuleExecOptions +) { const queryOpts = opts.query; const moduleOpts = opts.moduleOptions; const moduleName = opts.moduleName; @@ -122,11 +121,10 @@ async function moduleExec(this: ThisWithModExec, opts: ModuleExecOptions) { } // Check that query options passed by the user are valid for this module - validateAndCoerceTypes({ - source: moduleName, + validateAndCoerceTypebox({ type: "options", - object: queryOpts.overrides ?? {}, - schemaKey: queryOpts.schemaKey, + data: queryOpts.overrides ?? {}, + schema: queryOpts.schema, options: this._opts.validation, }); @@ -141,8 +139,9 @@ async function moduleExec(this: ThisWithModExec, opts: ModuleExecOptions) { * the query. Useful to transform options we allow but not Yahoo, e.g. * allow a "2020-01-01" date but transform this to a UNIX epoch. */ - if (queryOpts.transformWith) + if (queryOpts.transformWith) { queryOptions = queryOpts.transformWith(queryOptions); + } // this._fetch is lib/yahooFinanceFetch let result = await this._fetch( @@ -150,16 +149,20 @@ async function moduleExec(this: ThisWithModExec, opts: ModuleExecOptions) { queryOptions, moduleOpts, queryOpts.fetchType, - queryOpts.needsCrumb + queryOpts.needsCrumb ?? false ); - if (queryOpts.fetchType === "csv") result = csv2json(result); + if (queryOpts.fetchType === "csv") { + result = csv2json(result); + } /* * Mutate the Yahoo result *before* validating and coercion. Mostly used - * to e.g. throw if no (resault.returnField) and return result.returnField. + * to e.g. throw if no (result.returnField) and return result.returnField. */ - if (opts.result.transformWith) result = opts.result.transformWith(result); + if (resultOpts.transformWith) { + result = resultOpts.transformWith(result); + } const validateResult = !moduleOpts || @@ -190,11 +193,10 @@ async function moduleExec(this: ThisWithModExec, opts: ModuleExecOptions) { * database, etc. Otherwise you'll receive an error. */ try { - validateAndCoerceTypes({ - source: moduleName, + validateAndCoerceTypebox({ type: "result", - object: result, - schemaKey: resultOpts.schemaKey, + data: result, + schema: resultOpts.schema, options: validationOpts, }); } catch (error) { diff --git a/src/lib/moduleExecTypebox.spec.ts b/src/lib/moduleExecTypebox.spec.ts deleted file mode 100644 index 5e6630da..00000000 --- a/src/lib/moduleExecTypebox.spec.ts +++ /dev/null @@ -1,208 +0,0 @@ -import { jest } from "@jest/globals"; - -import search from "../modules/search.js"; -import { InvalidOptionsError } from "./errors.js"; -import testYf from "../../tests/testYf.js"; -import { TransformDecodeCheckError } from "@sinclair/typebox/value"; -import { Type } from "@sinclair/typebox"; - -const yf = testYf({ search }); -yf._opts.validation.logOptionsErrors = false; -yf._opts.validation.logErrors = false; - -describe("moduleExecTypebox", () => { - describe("options validation", () => { - it("throws InvalidOptions on invalid options", async () => { - const rwo = (options: any) => yf.search("symbol", options); - await expect(rwo({ invalid: true })).rejects.toThrow(InvalidOptionsError); - }); - - it("accepts empty queryOptions", async () => { - await expect( - yf.search("AAPL", undefined, { devel: "search-AAPL.json" }) - ).resolves.toBeDefined(); - }); - - it("logs errors on invalid options when logOptionsErrors = true", async () => { - yf._opts.validation.logOptionsErrors = true; - const realConsole = console; - const fakeConsole = { error: jest.fn(), log: jest.fn(), dir: jest.fn() }; - - /* @ts-ignore */ - console = fakeConsole; - const rwo = (options: any) => yf.search("symbol", options); - await expect(rwo({ invalid: true })).rejects.toThrow(InvalidOptionsError); - console = realConsole; - - expect( - fakeConsole.log.mock.calls.length + - fakeConsole.error.mock.calls.length + - fakeConsole.dir.mock.calls.length - ).toBe(1); - yf._opts.validation.logOptionsErrors = false; - }); - - it("does not log errors on invalid options when logOptionsErrors = false", async () => { - yf._opts.validation.logOptionsErrors = false; - console.log(yf._opts.validation); - const realConsole = console; - const fakeConsole = { error: jest.fn(), log: jest.fn(), dir: jest.fn() }; - - /* @ts-ignore */ - console = fakeConsole; - const rwo = (options: any) => yf.search("symbol", options); - await expect(rwo({ invalid: true })).rejects.toThrow(InvalidOptionsError); - console = realConsole; - expect( - fakeConsole.log.mock.calls.length + - fakeConsole.error.mock.calls.length + - fakeConsole.dir.mock.calls.length - ).toBe(0); - }); - }); - - describe("result validation", () => { - if (process.env.FETCH_DEVEL !== "nocache") - it("throws on unexpected input", async () => { - yf._opts.validation.logErrors = false; - await expect( - yf.search("AAPL", {}, { devel: "search-badResult.fake.json" }) - ).rejects.toThrow(TransformDecodeCheckError); - yf._opts.validation.logErrors = true; - }); - - it("dont throw or log on unexpected input with {validateResult: false}", async () => { - yf._opts.validation.logErrors = true; - const realConsole = console; - const fakeConsole = { error: jest.fn(), log: jest.fn(), dir: jest.fn() }; - - /* @ts-ignore */ - console = fakeConsole; - if (process.env.FETCH_DEVEL !== "nocache") - await expect( - yf.search( - "AAPL", - {}, - { - devel: "search-badResult.fake.json", - validateResult: false, - } - ) - ).resolves.toBeDefined(); - console = realConsole; - - expect(fakeConsole.log).not.toHaveBeenCalled(); - expect(fakeConsole.error).not.toHaveBeenCalled(); - expect(fakeConsole.dir).not.toHaveBeenCalled(); - }); - }); - describe("correctly invokes callbacks when provided", () => { - it("Should invoke the query options transformWith function when one is provided", async () => { - const yf = testYf({ _fetch: jest.fn() }); - const overrides = { overrideKey: "thingy" }; - const optionsTransformWith = jest.fn((v: Record) => ({ - ...v, - overrideKey: "bobby", - })); - - await yf._moduleExecTypebox({ - query: { - transformWith: optionsTransformWith, - assertSymbol: false, - schema: Type.Any(), - overrides, - }, - result: { - schema: Type.Any(), - }, - }); - expect(optionsTransformWith).toHaveBeenCalledTimes(1); - expect(optionsTransformWith).toMatchInlineSnapshot(` - [MockFunction] { - "calls": [ - [ - { - "overrideKey": "thingy", - }, - ], - ], - "results": [ - { - "type": "return", - "value": { - "overrideKey": "bobby", - }, - }, - ], - } - `); - }); - it("Should invoke the result transformWith function when one is provided", async () => { - const yf = testYf({ _fetch: jest.fn(() => ({ statusCode: 200 })) }); - const resultTransformedWith = jest.fn((v: Record) => { - return { overrideKey: "bobby" }; - }); - - await yf._moduleExecTypebox({ - query: { - assertSymbol: false, - schema: Type.Any(), - }, - result: { - schema: Type.Any(), - transformWith: resultTransformedWith, - }, - }); - expect(resultTransformedWith).toHaveBeenCalledTimes(1); - expect(resultTransformedWith).toMatchInlineSnapshot(` - [MockFunction] { - "calls": [ - [ - { - "statusCode": 200, - }, - ], - ], - "results": [ - { - "type": "return", - "value": { - "overrideKey": "bobby", - }, - }, - ], - } - `); - }); - it("should throw when symbol assertion is enabled but a non-string symbol is provided", () => { - const yf = testYf({ _fetch: jest.fn() }); - expect( - async () => - await yf._moduleExecTypebox({ - query: { - assertSymbol: true, - schema: Type.Any(), - }, - result: { - schema: Type.Any(), - }, - }) - ).rejects.toThrow(); - }); - it("should pass a string symbol when symbol assertion is enabled", () => { - const yf = testYf({ _fetch: jest.fn() }); - expect( - async () => - await yf._moduleExecTypebox({ - query: { - assertSymbol: "AAPL", - schema: Type.Any(), - }, - result: { - schema: Type.Any(), - }, - }) - ).not.toThrow(); - }); - }); -}); diff --git a/src/lib/moduleExecTypebox.ts b/src/lib/moduleExecTypebox.ts deleted file mode 100644 index 60f51463..00000000 --- a/src/lib/moduleExecTypebox.ts +++ /dev/null @@ -1,209 +0,0 @@ -/* - * moduleExec(options: ModuleExecOptions) - * - * 1. Query Stage - * 1. Validate user-supplied module params, e.g. { period: '1d' } - * 2. Merge query params: (module defaults, user-supplied overrides, etc) - * 3. Optionally transform query params - * - * 2. Call lib/yahooFinanceFetch - * - * 3. Result Stage - * 1. Optional transform the result - * 2. Validate the result and coerce types - * - * Further info below, inline. - */ - -import { validateAndCoerceTypebox } from "./validateAndCoerceTypes.js"; -import csv2json from "./csv2json.js"; -import { TSchema } from "@sinclair/typebox"; - -/* -interface TransformFunc { - (result: { [key: string]: any }): { [key: string]: any }; -} -*/ - -interface ModuleExecOptions { - /** - * Name of the module, e.g. "search", "quoteSummary", etc. Used in error - * reporting. - */ - moduleName: string; - - query: { - /** - * If given, a runtime assertion is performed to check that the given - * argument is a string. If not, a helpful error is thrown. - */ - assertSymbol?: string; - /** - * URL of the API to query, WITHOUT query params. - */ - url: string; - /** - * The schema to use to validate the options overrides - */ - schema: TSchema; - /** - * Defaults for this query, e.g. { period: '1d' } in history, - * and other required options that aren't often changed { locale: 'en' }. - */ - defaults: any; - /** - * Query parameters generated inside the module, most commonly something - * like { q: query } to take e.g. yf.search(query) and pass it how Yahoo - * expects it. - */ - runtime?: any; - /** - * Query options passed by the user that will override the default and - * runtime params. Will be validated with schemaKey. - */ - overrides: any; - /** - * Called with the merged (defaults,runtime,overrides) before running - * the query. Useful to transform options we allow but not Yahoo, e.g. - * allow a "2020-01-01" date but transform this to a UNIX epoch. - */ - transformWith?: (opts: TOpts) => unknown; - /** - * Default: 'json'. Can be 'text' or 'csv' (augments fetch's "text"). - */ - fetchType?: string; - /** - * Default: false. This request requires Yahoo cookies & crumb. - */ - needsCrumb?: boolean; - }; - - result: { - /** - * The schema to validate (and coerce) the retruned result from Yahoo. - */ - schema: TSchema; - /** - * Mutate the Yahoo result *before* validating and coercion. Mostly used - * to e.g. throw if no (resault.returnField) and return result.returnField. - */ - transformWith?: (result: unknown) => TResult; - }; - - moduleOptions?: { - /** - * Allow validation failures to pass if false; - */ - validateResult?: boolean; - /** - * Any options to pass to fetch() just for this request. - */ - fetchOptions?: any; - }; -} - -async function moduleExec( - this: { [key: string]: any }, - opts: ModuleExecOptions -) { - const queryOpts = opts.query; - const moduleOpts = opts.moduleOptions; - const moduleName = opts.moduleName; - const resultOpts = opts.result; - - if (queryOpts.assertSymbol) { - const symbol = queryOpts.assertSymbol; - if (typeof symbol !== "string") - throw new Error( - `yahooFinance.${moduleName}() expects a single string symbol as its ` + - `query, not a(n) ${typeof symbol}: ${JSON.stringify(symbol)}` - ); - } - - // Check that query options passed by the user are valid for this module - validateAndCoerceTypebox({ - type: "options", - data: queryOpts.overrides ?? {}, - schema: queryOpts.schema, - options: this._opts.validation, - }); - - let queryOptions = { - ...queryOpts.defaults, // Module defaults e.g. { period: '1wk', lang: 'en' } - ...queryOpts.runtime, // Runtime params e.g. { q: query } - ...queryOpts.overrides, // User supplied options that override above - }; - - /* - * Called with the merged (defaults,runtime,overrides) before running - * the query. Useful to transform options we allow but not Yahoo, e.g. - * allow a "2020-01-01" date but transform this to a UNIX epoch. - */ - if (queryOpts.transformWith) { - queryOptions = queryOpts.transformWith(queryOptions); - } - - // this._fetch is lib/yahooFinanceFetch - let result = await this._fetch( - queryOpts.url, - queryOptions, - moduleOpts, - queryOpts.fetchType, - queryOpts.needsCrumb ?? false - ); - - if (queryOpts.fetchType === "csv") { - result = csv2json(result); - } - - /* - * Mutate the Yahoo result *before* validating and coercion. Mostly used - * to e.g. throw if no (result.returnField) and return result.returnField. - */ - if (resultOpts.transformWith) { - result = resultOpts.transformWith(result); - } - - const validateResult = - !moduleOpts || - moduleOpts.validateResult === undefined || - moduleOpts.validateResult === true; - - const validationOpts = { - ...this._opts.validation, - // Set logErrors=false if validateResult=false - logErrors: validateResult ? this._opts.validation.logErrors : false, - }; - - /* - * Validate the returned result (after transforming, above) and coerce types. - * - * The coersion works as follows: if we're expecting a "Date" type, but Yahoo - * gives us { raw: 1231421524, fmt: "2020-01-01" }, we'll return that as - * `new Date(1231421524 * 1000)`. - * - * Beyond that, ensures that user won't process unexpected data, in two - * cases: - * - * a) Missing required properties or unexpected additional properties - * b) A total new change in format that we really have no idea what to do - * with, e.g. a new kind of Date that we've never seen before and - * - * The idea is that if you receive a result, it's safe to use / store in - * database, etc. Otherwise you'll receive an error. - */ - try { - validateAndCoerceTypebox({ - type: "result", - data: result, - schema: resultOpts.schema, - options: validationOpts, - }); - } catch (error) { - if (validateResult) throw error; - } - - return result as any; -} - -export default moduleExec; diff --git a/src/lib/options.ts b/src/lib/options.ts index 45454ee1..330f310b 100644 --- a/src/lib/options.ts +++ b/src/lib/options.ts @@ -1,22 +1,56 @@ -// TODO, keep defaults there too? -import type { ValidationOptions } from "./validateAndCoerceTypes.js"; -import type { QueueOptions } from "./queue.js"; import { ExtendedCookieJar } from "./cookieJar.js"; +import { Static, Type } from "@sinclair/typebox"; +import { QueueOptionsSchema } from "./queue.js"; -export interface Logger { +const LoggerSchema = Type.Object({ + info: Type.Function([], Type.Void()), + warn: Type.Function([], Type.Void()), + error: Type.Function([], Type.Void()), + debug: Type.Function([], Type.Void()), +}); + +export type Logger = { info: (...args: any[]) => void; warn: (...args: any[]) => void; error: (...args: any[]) => void; debug: (...args: any[]) => void; -} +}; + +const ValidationOptionsSchema = Type.Object({ + logErrors: Type.Optional(Type.Boolean()), + logOptionsErrors: Type.Optional(Type.Boolean()), + _internalThrowOnAdditionalProperties: Type.Optional( + Type.Boolean({ + default: process.env.NODE_ENV === "test", + description: + "Use this property to throw when properties beyond what is explicitly specified in the schema are provided. It is an internal option and subject to change, use at your own risk", + }) + ), +}); + +export type ValidationOptions = Static; -export interface YahooFinanceOptions { - YF_QUERY_HOST?: string; - cookieJar?: ExtendedCookieJar; - queue?: QueueOptions; - validation?: ValidationOptions; +export const YahooFinanceOptionsSchema = Type.Object( + { + YF_QUERY_HOST: Type.Optional(Type.String()), + cookieJar: Type.Optional(Type.Any()), + queue: Type.Optional(QueueOptionsSchema), + validation: Type.Optional(ValidationOptionsSchema), + logger: Type.Optional(LoggerSchema), + }, + { title: "YahooFinanceOptions" } +); + +/* +TODO: Ideally we'd have the typebox type be our source of truth for types here. +However, Typebox does not support type checking for instances of a particular class +in the case of the `cookieJar`, and for functions with variadic params in the case +of the `logger` (ref: https://github.com/sinclairzx81/typebox/issues/931) +*/ +export type YahooFinanceOptions = Static & { + cookieJar: ExtendedCookieJar; logger?: Logger; -} +}; const options: YahooFinanceOptions = { YF_QUERY_HOST: process.env.YF_QUERY_HOST || "query2.finance.yahoo.com", diff --git a/src/lib/queue.ts b/src/lib/queue.ts index 973e265b..f58f4547 100644 --- a/src/lib/queue.ts +++ b/src/lib/queue.ts @@ -1,15 +1,25 @@ +import { Static, Type } from "@sinclair/typebox"; + interface Job { func: () => Promise; resolve: (arg: any) => void; reject: (arg: any) => void; } -export interface QueueOptions { - // TODO: adds func type to json schema which is not supported - //_queue?: Queue; - concurrency?: number; - timeout?: number; // TODO -} +export const QueueOptionsSchema = Type.Object( + { + // TODO: adds func type to json schema which is not supported + //_queue?: Queue; + concurrency: Type.Optional(Type.Number()), + timeout: Type.Optional(Type.Number()), // TODO + }, + { + additionalProperties: false, + title: "QueueOptions", + } +); + +export type QueueOptions = Static; export default class Queue { concurrency = 1; diff --git a/src/lib/setGlobalConfig.spec.ts b/src/lib/setGlobalConfig.spec.ts index d90fb50a..42a412fe 100644 --- a/src/lib/setGlobalConfig.spec.ts +++ b/src/lib/setGlobalConfig.spec.ts @@ -28,10 +28,52 @@ describe("setGlobalConfig", () => { it("should throw on invalid config", () => { consoleSilent(); - expect(() => yf.setGlobalConfig({ queue: { abc: "" } })).toThrow( - /yahooFinance.setGlobalConfig called with invalid options\./ + expect(() => yf.setGlobalConfig({ queue: { concurrency: "" } })).toThrow( + /Validation called with invalid options/ ); consoleRestore(); }); + it("should throw on an invalid logger", () => { + consoleSilent(); + + expect(() => + yf.setGlobalConfig({ + logger: { + info() {}, + debug() {}, + error() {}, + warn: "yeh this won't work", + }, + }) + ).toThrow(/Validation called with invalid options/); + + expect(() => + yf.setGlobalConfig({ + logger: { + info() {}, + debug() {}, + error() {}, + }, + }) + ).toThrow(/Validation called with invalid options/); + + expect(() => + yf.setGlobalConfig({ + logger: {}, + }) + ).toThrow(/Validation called with invalid options/); + + consoleRestore(); + }); + it("should throw on an invalid cookie jar", () => { + consoleSilent(); + + expect(() => + yf.setGlobalConfig({ + cookieJar: "not a cookie jar", + }) + ).toThrow(/cookieJar must be an instance of ExtendedCookieJar/); + consoleRestore(); + }); }); diff --git a/src/lib/setGlobalConfig.ts b/src/lib/setGlobalConfig.ts index 8d023007..6882e310 100644 --- a/src/lib/setGlobalConfig.ts +++ b/src/lib/setGlobalConfig.ts @@ -1,4 +1,7 @@ -import type { YahooFinanceOptions } from "./options.js"; +import { + YahooFinanceOptionsSchema, + type YahooFinanceOptions, +} from "./options.js"; import type { ModuleThis } from "./moduleCommon.js"; import validateAndCoerceTypes from "./validateAndCoerceTypes.js"; import { ExtendedCookieJar } from "./cookieJar.js"; @@ -7,16 +10,16 @@ export default function setGlobalConfig( this: ModuleThis, _config: YahooFinanceOptions ): void { - // Instances (e.g. cookieJar) don't validate well :) - const { cookieJar, logger, ...config } = _config; - - validateAndCoerceTypes({ - object: config, - source: "setGlobalConfig", + const parsed = validateAndCoerceTypes({ + data: _config, type: "options", options: this._opts.validation, - schemaKey: "#/definitions/YahooFinanceOptions", + schema: YahooFinanceOptionsSchema, }); + + // Instances (e.g. cookieJar) don't validate well :) + const { cookieJar, ...config } = parsed; + mergeObjects(this._opts, config); if (cookieJar) { @@ -24,17 +27,6 @@ export default function setGlobalConfig( throw new Error("cookieJar must be an instance of ExtendedCookieJar"); this._opts.cookieJar = cookieJar; } - if (logger) { - if (typeof logger.info !== "function") - throw new Error("logger.info must be a function"); - if (typeof logger.warn !== "function") - throw new Error("logger.warn must be a function"); - if (typeof logger.error !== "function") - throw new Error("logger.error must be a function"); - if (typeof logger.debug !== "function") - throw new Error("logger.debug must be a function"); - this._opts.logger = logger; - } } type Obj = Record; diff --git a/src/lib/validateAndCoerceTypes.spec.ts b/src/lib/validateAndCoerceTypes.spec.ts index dc5efe01..b9e94b9a 100644 --- a/src/lib/validateAndCoerceTypes.spec.ts +++ b/src/lib/validateAndCoerceTypes.spec.ts @@ -1,412 +1,9 @@ import { jest } from "@jest/globals"; -import validateAndCoerceTypes, { ajv } from "./validateAndCoerceTypes.js"; import { validateAndCoerceTypebox } from "./validateAndCoerceTypes.js"; -import type { ValidateParams } from "./validateAndCoerceTypes.js"; -import { InvalidOptionsError, FailedYahooValidationError } from "./errors.js"; import { Type } from "@sinclair/typebox"; import { YahooFinanceDate, YahooNumber } from "./yahooFinanceTypes.js"; - -ajv.addSchema({ - $id: "testSchema", - $schema: "http://json-schema.org/draft-07/schema#", - properties: { - date: { yahooFinanceType: "date" }, - dateNull: { yahooFinanceType: "date|null" }, - dateInMs: { yahooFinanceType: "DateInMs" }, - twoNumberRange: { yahooFinanceType: "TwoNumberRange" }, - number: { yahooFinanceType: "number" }, - numberNull: { yahooFinanceType: "number|null" }, - requiredRequired: { - type: "object", - properties: { required: { type: "boolean" } }, - required: ["required"], - }, - noAdditional: { - type: "object", - additionalProperties: false, - properties: {}, - }, - }, - type: "object", -}); - -// Default. Use to show (unexpected) errors during tests. -const defLogParams: ValidateParams = { - source: "validateAndCoerceTypes.spec.js", - schemaKey: "testSchema", - //schemaKey: "#/definitions/QuoteSummaryResult", - type: "result", - object: {}, - options: { - logErrors: true, - logOptionsErrors: true, - }, -}; - -// If we're purposefully testing failed validation, don't log it. -// i.e. Use to hide (expected) errors during tests. -const defNoLogParams = { - ...defLogParams, - options: { - ...defLogParams.options, - logErrors: false, - }, -}; - -describe("validateAndCoerceTypes", () => { - describe("coersion", () => { - describe("numbers", () => { - it("passes regular numbers", () => { - const object = { number: 2 }; - validateAndCoerceTypes({ ...defLogParams, object }); - expect(object.number).toBe(2); - }); - - it("corerces rawNumberObjs", () => { - const object = { number: { raw: 0.006599537, fmt: "6.5%" } }; - validateAndCoerceTypes({ ...defLogParams, object }); - expect(object.number).toBe(0.006599537); - }); - - it("passes if data is null and type IS number|null", () => { - const object = { numberNull: null }; - expect(() => - validateAndCoerceTypes({ ...defLogParams, object }) - ).not.toThrow(); - }); - - it("fails if data is null and type IS NOT number|null", () => { - const object = { number: null }; - let error: FailedYahooValidationError | any; - try { - validateAndCoerceTypes({ ...defNoLogParams, object }); - } catch (e) { - error = e; - } - // @ts-ignore - expect(error).toBeDefined(); - expect(error.errors[0].message).toMatch(/Expecting number/); - }); - - it("passes and coerces {} to null if type IS number|null", () => { - const object = { numberNull: {} }; - expect(() => - validateAndCoerceTypes({ ...defLogParams, object }) - ).not.toThrow(); - expect(object.numberNull).toBe(null); - }); - - it("fails when receiving {} if type IS NOT number|null", () => { - const object = { number: {} }; - let error: FailedYahooValidationError | any; - try { - validateAndCoerceTypes({ ...defNoLogParams, object }); - } catch (e) { - error = e; - } - expect(error).toBeDefined(); - expect(error.errors[0].message).toMatch(/number \| null/); - }); - - it("fails if data is not a number nor object", () => { - const object = { number: true }; - expect(() => - validateAndCoerceTypes({ ...defNoLogParams, object }) - ).toThrow(/Failed Yahoo Schema/); - }); - - it("fails if data.raw is not a number", () => { - const object = { number: { raw: "a string" } }; - expect(() => - validateAndCoerceTypes({ ...defNoLogParams, object }) - ).toThrow(/Failed Yahoo Schema/); - }); - - it("fails if string returns a NaN", () => { - const object = { number: "not-a-number" }; - expect(() => - validateAndCoerceTypes({ ...defNoLogParams, object }) - ).toThrow(/Failed Yahoo Schema/); - }); - }); - - describe("dates", () => { - it("coerces rawNumberObjs", () => { - const dateInMs = 1612313997; - const object = { date: { raw: dateInMs } }; - validateAndCoerceTypes({ ...defLogParams, object }); - expect(object.date).toBeInstanceOf(Date); - // @ts-ignore - expect(object.date.getTime()).toBe(dateInMs * 1000); - }); - - it("coerces epochs", () => { - const dateInMs = 1612313997; - const object = { date: dateInMs }; - validateAndCoerceTypes({ ...defLogParams, object }); - // @ts-ignore - expect(object.date.getTime()).toBe(new Date(dateInMs * 1000).getTime()); - }); - - it("coerces recognizable date string", () => { - const dateStr = "2021-02-02T21:00:01.000Z"; - const object = { date: dateStr }; - validateAndCoerceTypes({ ...defLogParams, object }); - // @ts-ignore - expect(object.date.getTime()).toBe(new Date(dateStr).getTime()); - }); - - it("throws on non-matching strings", () => { - const object = { date: "clearly not a date" }; - expect(() => - validateAndCoerceTypes({ ...defNoLogParams, object }) - ).toThrow(/Failed Yahoo Schema/); - }); - - it("passes through Date objects", () => { - const date = new Date(); - const object = { date }; - validateAndCoerceTypes({ ...defLogParams, object }); - expect(object.date).toBe(date); - }); - - it("passes if data is null and type IS date|null", () => { - const object = { dateNull: null }; - expect(() => - validateAndCoerceTypes({ ...defLogParams, object }) - ).not.toThrow(); - }); - - it("fails if data is null and type IS NOT date|null", () => { - const object = { date: null }; - let error: FailedYahooValidationError | any; - try { - validateAndCoerceTypes({ ...defNoLogParams, object }); - } catch (e) { - error = e; - } - // @ts-ignore - expect(error).toBeDefined(); - expect(error.errors[0].message).toMatch(/Expecting date/); - }); - - it("passes and coerces {} to null if type IS Date|null", () => { - const object = { dateNull: {} }; - expect(() => - validateAndCoerceTypes({ ...defLogParams, object }) - ).not.toThrow(); - expect(object.dateNull).toBe(null); - }); - - it("fails when receiving {} if type IS NOT date|null", () => { - const object = { date: {} }; - let error: FailedYahooValidationError | any; - try { - validateAndCoerceTypes({ ...defNoLogParams, object }); - } catch (e) { - error = e; - } - expect(error).toBeDefined(); - expect(error.errors[0].message).toMatch(/date \| null/); - }); - }); - - describe("DateInMs", () => { - it("works with date in milliseconds", () => { - const object = { dateInMs: 917015400000 }; - validateAndCoerceTypes({ ...defLogParams, object }); - expect(object.dateInMs).toBeInstanceOf(Date); - }); - }); - - describe("TwoNumberRange", () => { - it("works with valid input", () => { - const object = { twoNumberRange: "541.867 - 549.19" }; - validateAndCoerceTypes({ ...defLogParams, object }); - expect(object.twoNumberRange).toMatchObject({ - low: 541.867, - high: 549.19, - }); - }); - - it("throws on invalid input", () => { - const object = { twoNumberRange: "X - 549.19" }; - expect(() => - validateAndCoerceTypes({ ...defNoLogParams, object }) - ).toThrow(/^Failed Yahoo/); - }); - - it("throws no matching type on weird input", () => { - const object = { twoNumberRange: 12 }; - expect(() => - validateAndCoerceTypes({ ...defNoLogParams, object }) - ).toThrow(/^Failed Yahoo/); - }); - }); - - describe("failures", () => { - it("fails on invalid options usage", () => { - const options = { period1: true }; - expect(() => - validateAndCoerceTypes({ - ...defNoLogParams, - object: options, - type: "options", - schemaKey: "#/definitions/HistoricalOptions", - source: "historical-in-validate.spec", - options: { ...defNoLogParams.options, logOptionsErrors: false }, - }) - ).toThrow(InvalidOptionsError); - }); - - it("fails on error", () => { - const object = { date: { weird: 123 } }; - let error: FailedYahooValidationError | any; - try { - validateAndCoerceTypes({ ...defNoLogParams, object }); - } catch (e) { - error = e; - } - - /* @ts-ignore */ - expect(error).toBeDefined(); - - /* @ts-ignore */ - if (!error) return; - expect(error.message).toMatch(/Failed Yahoo Schema/); - - /* @ts-ignore */ - const error0 = error.errors[0]; - expect(error0).toBeDefined(); - expect(error0.keyword).toBe("yahooFinanceType"); - expect(error0.message).toBe("No matching type"); - expect(error0.params).toBeDefined(); - - if (!error0.params) return; - expect(error0.params.schema).toBe("date"); - expect(error0.params.data).toBe(object.date); - expect(error0.instancePath).toBe("/date"); - expect(error0.schemaPath).toBe("#/properties/date/yahooFinanceType"); - }); - - it("fails on invalid schema key", () => { - expect(() => - validateAndCoerceTypes({ - ...defNoLogParams, - schemaKey: "SOME_MISSING_KEY", - }) - ).toThrow(/No such schema/); - }); - - // i.e. on output not from bin/modify-schema - it('fails when yahooFinanceType is not "date"|"number"', () => { - const schema = { yahooFinanceType: "impossible" }; - const validate = ajv.compile(schema); - expect(() => validate({})).toThrow(/No such yahooFinanceType/); - }); - - it("logs errors when logErrors=true", () => { - const origConsole = console; - const fakeConsole = { - error: jest.fn(), - log: jest.fn(), - dir: jest.fn(), - }; - - /* @ts-ignore */ - console = fakeConsole; - const object = { requiredRequired: {} }; - expect(() => - validateAndCoerceTypes({ - ...defLogParams, - object, - }) - ).toThrow("Failed Yahoo Schema validation"); - console = origConsole; - - expect(fakeConsole.log).toHaveBeenCalled(); - }); - - it("does not log errors when logErrors=false", () => { - const origConsole = console; - const fakeConsole = { - error: jest.fn(), - log: jest.fn(), - dir: jest.fn(), - }; - - /* @ts-ignore */ - console = fakeConsole; - const object = { requiredRequired: {} }; - expect(() => - validateAndCoerceTypes({ - ...defNoLogParams, - object, - }) - ).toThrow("Failed Yahoo Schema validation"); - console = origConsole; - - expect(fakeConsole.log).not.toHaveBeenCalled(); - expect(fakeConsole.error).not.toHaveBeenCalled(); - expect(fakeConsole.dir).not.toHaveBeenCalled(); - }); - - it("returns results/errors in error object", () => { - const object = { noAdditional: { additional: true } }; - - let error: FailedYahooValidationError | any; - try { - validateAndCoerceTypes({ - ...defNoLogParams, - object, - }); - } catch (e) { - error = e; - } - - expect(error).toBeDefined(); - expect(error.message).toMatch(/Failed Yahoo/); - expect(error.result).toBe(object); - expect(error.errors).toBeType("array"); - }); - - it("returns ref to problem data in error object", () => { - const object = { noAdditional: { additional: true }, number: "str" }; - - let error: FailedYahooValidationError | any; - try { - validateAndCoerceTypes({ - ...defNoLogParams, - object, - }); - } catch (e) { - error = e; - } - - expect(error).toBeDefined(); - expect(error.message).toMatch(/Failed Yahoo/); - - let e; - - e = error.errors[0]; - expect(e.params).toMatchObject({ - data: "str", - schema: "number", - }); - expect(e.instancePath).toBe("/number"); - expect(e.data).toBe("str"); - - e = error.errors[1]; - expect(e.instancePath).toBe("/noAdditional"); - expect(e.params).toMatchObject({ - additionalProperty: "additional", - }); - expect(e.data).toBe(object.noAdditional); - }); - }); - }); -}); +import { FailedYahooValidationError } from "./errors.js"; describe("validateAndCoerceTypebox", () => { afterEach(() => { @@ -419,7 +16,7 @@ describe("validateAndCoerceTypebox", () => { date: YahooFinanceDate, }); - let error; + let error: FailedYahooValidationError | undefined; try { validateAndCoerceTypebox({ type: "result", @@ -428,68 +25,121 @@ describe("validateAndCoerceTypebox", () => { options: {}, }); } catch (e) { - error = e; + error = e as unknown as FailedYahooValidationError; } expect(error).toMatchInlineSnapshot( - `[Error: Unable to decode value as it does not match the expected schema]` + `[FailedYahooValidationError: Failed Yahoo Schema validation]` ); - // TODO: Fix Jest types here - // @ts-ignore - expect(JSON.stringify(error?.error, null, 2)).toMatchInlineSnapshot(` + + expect(JSON.stringify(error?.errors?.[0], null, 2)).toMatchInlineSnapshot(` "{ - "type": 62, "schema": { - "title": "YahooFinanceDate", - "anyOf": [ - { - "type": "Date" - }, - { - "type": "number" - }, - { - "title": "RawDateObject", - "type": "object", - "properties": { - "raw": { - "type": "number" - } - }, - "required": [ - "raw" - ] - }, - { - "title": "ISOStringDate", + "type": "object", + "properties": { + "date": { + "title": "YahooFinanceDate", "anyOf": [ { - "format": "date", - "type": "string" + "type": "Date" }, { - "format": "year", - "type": "string" + "type": "number" }, { - "format": "date-time", - "type": "string" + "title": "RawDateObject", + "type": "object", + "properties": { + "raw": { + "type": "number" + } + }, + "required": [ + "raw" + ] + }, + { + "title": "ISOStringDate", + "anyOf": [ + { + "format": "date", + "type": "string" + }, + { + "format": "year", + "type": "string" + }, + { + "format": "date-time", + "type": "string" + } + ] } ] } + }, + "required": [ + "date" ] }, - "path": "/date", "value": { - "weird": 123 + "date": { + "weird": 123 + } }, - "message": "Expected union value" + "error": { + "type": 62, + "schema": { + "title": "YahooFinanceDate", + "anyOf": [ + { + "type": "Date" + }, + { + "type": "number" + }, + { + "title": "RawDateObject", + "type": "object", + "properties": { + "raw": { + "type": "number" + } + }, + "required": [ + "raw" + ] + }, + { + "title": "ISOStringDate", + "anyOf": [ + { + "format": "date", + "type": "string" + }, + { + "format": "year", + "type": "string" + }, + { + "format": "date-time", + "type": "string" + } + ] + } + ] + }, + "path": "/date", + "value": { + "weird": 123 + }, + "message": "Expected union value" + } }" `); - // TODO: Fix Jest types here - // @ts-ignore - expect(JSON.stringify(error?.value, null, 2)).toMatchInlineSnapshot(` + expect(JSON.stringify(error?.errors?.[0]?.value, null, 2)) + .toMatchInlineSnapshot(` "{ "date": { "weird": 123 @@ -765,3 +415,41 @@ describe("validateAndCoerceTypebox", () => { }).toThrow(TypeError); }); }); + +describe("_internalThrowOnAddtionalProperties", () => { + const schema = Type.Object( + { name: Type.String() }, + { additionalProperties: Type.Any() } + ); + + const testCase = { name: "Gadi", aTotallyUnrelatedKey: "foo" }; + it("Should allow additional properties if a schema does when _throwOnAdditionalProperties is false", () => { + const result = validateAndCoerceTypebox({ + type: "result", + data: testCase, + options: { + _internalThrowOnAdditionalProperties: false, + }, + schema, + }); + + expect(result).toMatchInlineSnapshot(` + { + "aTotallyUnrelatedKey": "foo", + "name": "Gadi", + } + `); + }); + it("Should not allow additional properties even if a schema does when _throwOnAdditionalProperties is true", () => { + expect(() => { + validateAndCoerceTypebox({ + type: "options", + data: testCase, + schema: schema, + options: { + _internalThrowOnAdditionalProperties: true, + }, + }); + }).toThrow(); + }); +}); diff --git a/src/lib/validateAndCoerceTypes.ts b/src/lib/validateAndCoerceTypes.ts index 99aa5ba1..b48105a5 100644 --- a/src/lib/validateAndCoerceTypes.ts +++ b/src/lib/validateAndCoerceTypes.ts @@ -1,235 +1,12 @@ -import Ajv from "ajv"; -import type { SchemaValidateFunction } from "ajv/dist/types"; -import addFormats from "ajv-formats"; - -//import schema from '../../schema.json'; -import schema from "../../schema.json"; import pkg from "../../package.json"; -import { InvalidOptionsError, FailedYahooValidationError } from "./errors.js"; +import { FailedYahooValidationError, InvalidOptionsError } from "./errors.js"; import { StaticDecode, type TSchema } from "@sinclair/typebox"; import { TransformDecodeCheckError, TransformDecodeError, Value, } from "@sinclair/typebox/value"; - -// https://ajv.js.org/docs/api.html#options -export const ajv = new Ajv({ - // All rules, all errors. Don't end early after first error. - allErrors: true, - // Allow multiple non-null types, like in TypeSript. - allowUnionTypes: true, -}); -addFormats(ajv); - -ajv.addKeyword({ - keyword: "yahooFinanceType", - modifying: true, - errors: true, - schema: true, - compile(schema /*, parentSchema, it */) { - const validate: SchemaValidateFunction = (data, dataCtx) => { - const { parentData, parentDataProperty } = dataCtx; - - function set(value: any) { - parentData[parentDataProperty] = value; - return true; - } - - if (schema === "number" || schema === "number|null") { - if (typeof data === "number") return true; - - if (typeof data === "string") { - let float = Number.parseFloat(data); - if (Number.isNaN(float)) { - validate.errors = validate.errors || []; - validate.errors.push({ - keyword: "yahooFinanceType", - message: "Number.parseFloat returned NaN", - params: { schema, data }, - }); - return false; - } - return set(float); - } - - if (data === null) { - if (schema === "number|null") { - return true; - } else { - validate.errors = validate.errors || []; - validate.errors.push({ - keyword: "yahooFinanceType", - message: "Expecting number'ish but got null", - params: { schema, data }, - }); - return false; - } - } - - if (typeof data === "object") { - if (Object.keys(data).length === 0) { - // Value of {} becomes null - // Note, TypeScript types should be "number | null" - if (schema === "number|null") { - return set(null); - } else { - validate.errors = validate.errors || []; - validate.errors.push({ - keyword: "yahooFinanceType", - message: - "Got {}->null for 'number', did you want 'number | null' ?", - params: { schema, data }, - }); - return false; - } - } - if (typeof data.raw === "number") return set(data.raw); - } - } else if (schema === "date" || schema === "date|null") { - if (data instanceof Date) { - // Validate existing date objects. - // Generally we receive JSON but in the case of "historical", the - // csv parser does the date conversion, and we want to validate - // afterwards. - return true; - } - - if (typeof data === "number") return set(new Date(data * 1000)); - - if (data === null) { - if (schema === "date|null") { - return true; - } else { - validate.errors = validate.errors || []; - validate.errors.push({ - keyword: "yahooFinanceType", - message: "Expecting date'ish but got null", - params: { schema, data }, - }); - return false; - } - } - - if (typeof data === "object") { - if (Object.keys(data).length === 0) { - // Value of {} becomes null - // Note, TypeScript types should be "data | null" - if (schema === "date|null") { - return set(null); - } else { - validate.errors = validate.errors || []; - validate.errors.push({ - keyword: "yahooFinanceType", - message: - "Got {}->null for 'date', did you want 'date | null' ?", - params: { schema, data }, - }); - return false; - } - } - if (typeof data.raw === "number") - return set(new Date(data.raw * 1000)); - } - - if (typeof data === "string") { - if ( - data.match(/^\d{4,4}-\d{2,2}-\d{2,2}$/) || - data.match( - /^\d{4,4}-\d{2,2}-\d{2,2}T\d{2,2}:\d{2,2}:\d{2,2}(\.\d{3,3})?Z$/ - ) - ) - return set(new Date(data)); - } - } else if (schema === "DateInMs") { - return set(new Date(data)); - } else if (schema === "TwoNumberRange") { - if ( - typeof data === "object" && - typeof data.low === "number" && - typeof data.high === "number" - ) - return true; - if (typeof data === "string") { - const parts = data.split("-").map(parseFloat); - if (Number.isNaN(parts[0]) || Number.isNaN(parts[1])) { - validate.errors = validate.errors || []; - validate.errors.push({ - keyword: "yahooFinanceType", - message: - "Number.parseFloat returned NaN: [" + parts.join(",") + "]", - params: { schema, data }, - }); - return false; - } - return set({ low: parts[0], high: parts[1] }); - } - } else { - throw new Error("No such yahooFinanceType: " + schema); - } - - validate.errors = validate.errors || []; - validate.errors.push({ - keyword: "yahooFinanceType", - message: "No matching type", - params: { schema, data }, - }); - return false; - }; - - return validate; - }, -}); - -ajv.addSchema(schema); - -/* istanbul ignore next */ -const logObj = - typeof process !== "undefined" && process?.stdout?.isTTY - ? (obj: any) => console.dir(obj, { depth: 4, colors: true }) - : (obj: any) => console.log(JSON.stringify(obj, null, 2)); - -export function resolvePath(obj: any, instancePath: string) { - const path = instancePath.split("/"); - let ref = obj; - for (let i = 1; i < path.length; i++) ref = ref[path[i]]; - return ref; -} - -export interface ValidationOptions { - logErrors?: boolean; - logOptionsErrors?: boolean; -} -export interface ValidateParams { - source: string; - type: "options" | "result"; - object: object; - schemaKey: string; - options: ValidationOptions; -} - -function disallowAdditionalProps(show = false) { - const disallowed = new Set(); - // @ts-ignore: this can cause a breaking catch-22 on schema generation - for (let key of Object.keys(schema.definitions)) { - if (key.match(/Options$/)) { - continue; - } - // @ts-ignore - const def = schema.definitions[key]; - if (def.type === "object" && def.additionalProperties === undefined) { - def.additionalProperties = false; - disallowed.add(key); - } - } - /* istanbul ignore next */ - if (show) - console.log( - "Disallowed additional props in " + Array.from(disallowed).join(", ") - ); -} - -if (process.env.NODE_ENV === "test") disallowAdditionalProps(); +import { ValidationOptions } from "./options"; const handleResultError = ( e: TransformDecodeError | TransformDecodeCheckError, @@ -263,7 +40,10 @@ const handleResultError = ( so help is always appreciated! `); } - throw e; + throw new FailedYahooValidationError("Failed Yahoo Schema validation", { + result: e.value, + errors: [e], + }); }; const handleOptionsError = ( @@ -290,7 +70,10 @@ export const validateAndCoerceTypebox = ({ options: ValidationOptions; }): StaticDecode => { try { - return Value.Decode(schema, data); + const validationSchema = options._internalThrowOnAdditionalProperties + ? { ...schema, additionalProperties: false } + : schema; + return Value.Decode(validationSchema, data); } catch (e) { if ( e instanceof TransformDecodeError || @@ -309,141 +92,4 @@ export const validateAndCoerceTypebox = ({ } }; -function validate({ - source, - type, - object, - schemaKey, - options, -}: ValidateParams): void { - const validator = ajv.getSchema(schemaKey); - if (!validator) throw new Error("No such schema with key: " + schemaKey); - - const valid = validator(object); - if (valid) return; - - if (type === "result") { - /* istanbul ignore else */ - if (validator.errors) { - let origData: any = false; - - validator.errors.forEach((error) => { - // For now let's ignore the base object which could be huge. - /* istanbul ignore else */ - if (error.instancePath !== "") - // Note, not the regular ajv data value from verbose:true - error.data = resolvePath(object, error.instancePath); - - if (error.schemaPath === "#/anyOf") { - if (origData === false) { - origData = error.data; - } else if (origData === error.data) { - error.data = "[shortened by validateAndCoerceTypes]"; - } - } - }); - - // Becaue of the "anyOf" in quote, errors are huuuuge and mostly - // irrelevant... so let's filter out (some of) the latter - validator.errors = validator.errors.filter((error) => { - if (error.schemaPath.startsWith("#/definitions/Quote")) { - const schemaQuoteType = error.schemaPath - .substring(19) - .split("/")[0] - .toUpperCase(); - - /* - * Filter out entries for non-matching schema type, i.e. - * { - * schemaPath: '#/definitions/QuoteCryptoCurrency/properties...' - * data: { - * quoteType: "EQUITY" - * } - * } - */ - if ( - typeof error.data === "object" && - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore: Properrty "quoteType" does not exist on type "object" - error.data?.quoteType !== schemaQuoteType - ) - return false; - - /* - * Filter out the non-matching "const" for the above. - * { - * schemaPath: '#/definitions/QuoteCryptoCurrency/properties/quoteType/const' - * keyword: "const", - * params: { allowedValue: "CRYPTOCURRENCY"}}, - * data: "EQUITY" - * } - */ - if ( - typeof error.data === "string" && - error.params?.allowedValue === schemaQuoteType - ) - return false; - } - return true; - }); - - // In the case of there being NO match in #anyOf, bring back the data - if ( - validator.errors.length === 1 && - validator.errors[0].schemaPath === "#/anyOf" - ) - validator.errors[0].data = origData; - } - - if (options.logErrors === true) { - const title = encodeURIComponent("Failed validation: " + schemaKey); - console.log( - "The following result did not validate with schema: " + schemaKey - ); - logObj(validator.errors); - // logObj(object); - console.log(` -This may happen intermittently and you should catch errors appropriately. -However: 1) if this recently started happening on every request for a symbol -that used to work, Yahoo may have changed their API. 2) If this happens on -every request for a symbol you've never used before, but not for other -symbols, you've found an edge-case (OR, we may just be protecting you from -"bad" data sometimes stored for e.g. misspelt symbols on Yahoo's side). -Please see if anyone has reported this previously: - - ${pkg.repository}/issues?q=is%3Aissue+${title} - -or open a new issue (and mention the symbol): ${pkg.name} v${pkg.version} - - ${pkg.repository}/issues/new?labels=bug%2C+validation&template=validation.md&title=${title} - -For information on how to turn off the above logging or skip these errors, -see https://github.com/gadicc/node-yahoo-finance2/tree/devel/docs/validation.md. - -At the end of the doc, there's also a section on how to -[Help Fix Validation Errors](https://github.com/gadicc/node-yahoo-finance2/blob/devel/docs/validation.md#help-fix) -in case you'd like to contribute to the project. Most of the time, these -fixes are very quick and easy; it's just hard for our small core team to keep up, -so help is always appreciated! -`); - } /* if (logErrors) */ - - throw new FailedYahooValidationError("Failed Yahoo Schema validation", { - result: object, - errors: validator.errors, - }); - } /* if (type === 'options') */ else { - if (options.logOptionsErrors === true) { - console.error( - `[yahooFinance.${source}] Invalid options ("${schemaKey}")` - ); - logObj({ errors: validator.errors, input: object }); - } - throw new InvalidOptionsError( - `yahooFinance.${source} called with invalid options.` - ); - } -} - -export { disallowAdditionalProps }; -export default validate; +export default validateAndCoerceTypebox; diff --git a/src/modules/chart.spec.ts b/src/modules/chart.spec.ts index 924f1e25..a18b95ab 100644 --- a/src/modules/chart.spec.ts +++ b/src/modules/chart.spec.ts @@ -137,7 +137,7 @@ describe("chart", () => { * As long as it doesn't throw an error, that could confuse jest :) */ const yf = { - _moduleExecTypebox: jest.fn(async () => ({ + _moduleExec: jest.fn(async () => ({ meta: {}, timestamp: [], })), @@ -147,7 +147,7 @@ describe("chart", () => { // @ts-ignore: TODO yf.chart("symbol", { period1: "required-but-not-used" }); // @ts-ignore: TODO - const { transformWith } = yf._moduleExecTypebox.mock.calls[0][0].query; + const { transformWith } = yf._moduleExec.mock.calls[0][0].query; it("uses today's date as default for period2", () => { const now = new Date(); diff --git a/src/modules/chart.ts b/src/modules/chart.ts index e93b529b..d1f87279 100644 --- a/src/modules/chart.ts +++ b/src/modules/chart.ts @@ -314,7 +314,7 @@ export default async function chart( ): Promise { const returnAs = queryOptionsOverrides?.return || "array"; - const result = (await this._moduleExecTypebox({ + const result = (await this._moduleExec({ moduleName: "chart", query: { diff --git a/src/modules/dailyGainers.ts b/src/modules/dailyGainers.ts index a98f0d88..308588e3 100644 --- a/src/modules/dailyGainers.ts +++ b/src/modules/dailyGainers.ts @@ -182,7 +182,7 @@ export default function dailyGainers( queryOptionsOverrides?: DailyGainersOptions, moduleOptions?: ModuleOptions ): Promise { - return this._moduleExecTypebox({ + return this._moduleExec({ moduleName: "dailyGainers", query: { url: "https://${YF_QUERY_HOST}/v1/finance/screener/predefined/saved", diff --git a/src/modules/fundamentalsTimeSeries.ts b/src/modules/fundamentalsTimeSeries.ts index 82e966b5..29e946ef 100644 --- a/src/modules/fundamentalsTimeSeries.ts +++ b/src/modules/fundamentalsTimeSeries.ts @@ -88,7 +88,7 @@ export default function fundamentalsTimeSeries( queryOptionsOverrides: FundamentalsTimeSeriesOptions, moduleOptions?: ModuleOptions ): Promise { - return this._moduleExecTypebox({ + return this._moduleExec({ moduleName: "options", query: { diff --git a/src/modules/historical.spec.ts b/src/modules/historical.spec.ts index 2a4a5cf4..8d6d8571 100644 --- a/src/modules/historical.spec.ts +++ b/src/modules/historical.spec.ts @@ -67,11 +67,11 @@ describe("historical", () => { }); describe("transformWith", () => { - const yf = { _moduleExecTypebox: jest.fn(), historical }; + const yf = { _moduleExec: jest.fn(), historical }; // @ts-ignore: TODO yf.historical("symbol", { period1: "required-but-not-used" }); // @ts-ignore: TODO - const { transformWith } = yf._moduleExecTypebox.mock.calls[0][0].query; + const { transformWith } = yf._moduleExec.mock.calls[0][0].query; it("uses today's date as default for period2", () => { const now = new Date(); diff --git a/src/modules/historical.ts b/src/modules/historical.ts index 93875c9e..f43628db 100644 --- a/src/modules/historical.ts +++ b/src/modules/historical.ts @@ -163,7 +163,7 @@ export default function historical( schema = HistoricalStockSplitsResultSchema; else throw new Error("No such event type:" + queryOptionsOverrides.events); - return this._moduleExecTypebox({ + return this._moduleExec({ moduleName: "historical", query: { diff --git a/src/modules/insights.ts b/src/modules/insights.ts index 250c3964..0ad36a46 100644 --- a/src/modules/insights.ts +++ b/src/modules/insights.ts @@ -327,7 +327,7 @@ export default function trendingSymbols( queryOptionsOverrides?: InsightsOptions, moduleOptions?: ModuleOptions ): Promise { - return this._moduleExecTypebox({ + return this._moduleExec({ moduleName: "insights", query: { assertSymbol: symbol, diff --git a/src/modules/options.ts b/src/modules/options.ts index 6f7bd111..5b12bbb5 100644 --- a/src/modules/options.ts +++ b/src/modules/options.ts @@ -241,7 +241,7 @@ export default function options( queryOptionsOverrides: OptionsOptions, moduleOptions?: ModuleOptions ): Promise { - return this._moduleExecTypebox({ + return this._moduleExec({ moduleName: "options", query: { diff --git a/src/modules/quote.ts b/src/modules/quote.ts index 86451d71..64607c67 100644 --- a/src/modules/quote.ts +++ b/src/modules/quote.ts @@ -332,7 +332,7 @@ export default async function quote( const symbols = typeof query === "string" ? query : query.join(","); const returnAs = queryOptionsOverrides && queryOptionsOverrides.return; - const results: Quote[] = await this._moduleExecTypebox({ + const results: Quote[] = await this._moduleExec({ moduleName: "quote", query: { diff --git a/src/modules/quoteSummary.ts b/src/modules/quoteSummary.ts index ed2cb67a..dc5292e4 100644 --- a/src/modules/quoteSummary.ts +++ b/src/modules/quoteSummary.ts @@ -116,7 +116,7 @@ export default function quoteSummary( queryOptionsOverrides?: QuoteSummaryOptions, moduleOptions?: ModuleOptions ): Promise { - return this._moduleExecTypebox({ + return this._moduleExec({ moduleName: "quoteSummary", query: { assertSymbol: symbol, diff --git a/src/modules/recommendationsBySymbol.ts b/src/modules/recommendationsBySymbol.ts index 6769b229..a1ba1b98 100644 --- a/src/modules/recommendationsBySymbol.ts +++ b/src/modules/recommendationsBySymbol.ts @@ -76,7 +76,7 @@ export default function recommendationsBySymbol( ): Promise { const symbols = typeof query === "string" ? query : query.join(","); - return this._moduleExecTypebox({ + return this._moduleExec({ moduleName: "recommendationsBySymbol", query: { diff --git a/src/modules/screener.ts b/src/modules/screener.ts index dc560915..5dad6017 100644 --- a/src/modules/screener.ts +++ b/src/modules/screener.ts @@ -224,7 +224,7 @@ export default function screener( queryOptionsOverrides?: ScreenerOptions, moduleOptions?: ModuleOptions ): Promise { - return this._moduleExecTypebox({ + return this._moduleExec({ moduleName: "screener", query: { url: "https://${YF_QUERY_HOST}/v1/finance/screener/predefined/saved", diff --git a/src/modules/search.ts b/src/modules/search.ts index 237d8300..608959e4 100644 --- a/src/modules/search.ts +++ b/src/modules/search.ts @@ -283,7 +283,7 @@ export default function search( queryOptionsOverrides?: SearchOptions, moduleOptions?: ModuleOptions ): Promise { - return this._moduleExecTypebox({ + return this._moduleExec({ moduleName: "searchTypebox", query: { diff --git a/src/modules/trendingSymbols.ts b/src/modules/trendingSymbols.ts index 177a26aa..ca24a814 100644 --- a/src/modules/trendingSymbols.ts +++ b/src/modules/trendingSymbols.ts @@ -70,7 +70,7 @@ export default function trendingSymbols( queryOptionsOverrides?: TrendingSymbolsOptions, moduleOptions?: ModuleOptions ): Promise { - return this._moduleExecTypebox({ + return this._moduleExec({ moduleName: "trendingSymbols", query: { url: "https://${YF_QUERY_HOST}/v1/finance/trending/" + query, diff --git a/tests/http/getCrumb-getcrumb b/tests/http/getCrumb-getcrumb deleted file mode 100644 index 1cd08dd9..00000000 --- a/tests/http/getCrumb-getcrumb +++ /dev/null @@ -1,67 +0,0 @@ -{ - "request": { - "url": "https://query2.finance.yahoo.com/v1/test/getcrumb" - }, - "response": { - "ok": true, - "status": 200, - "statusText": "OK", - "headers": { - "content-type": [ - "text/plain;charset=utf-8" - ], - "access-control-allow-origin": [ - "https://finance.yahoo.com" - ], - "access-control-allow-credentials": [ - "true" - ], - "y-rid": [ - "4o3fbchj9sck2" - ], - "cache-control": [ - "private, max-age=60, stale-while-revalidate=30" - ], - "vary": [ - "Origin,Accept-Encoding" - ], - "content-length": [ - "11" - ], - "x-envoy-upstream-service-time": [ - "1" - ], - "date": [ - "Mon, 22 Jul 2024 10:20:50 GMT" - ], - "server": [ - "ATS" - ], - "x-envoy-decorator-operation": [ - "finance-external-services-api--mtls-production-sg3.finance-k8s.svc.yahoo.local:4080/*" - ], - "age": [ - "0" - ], - "strict-transport-security": [ - "max-age=31536000" - ], - "referrer-policy": [ - "no-referrer-when-downgrade" - ], - "connection": [ - "close" - ], - "expect-ct": [ - "max-age=31536000, report-uri=\"http://csp.yahoo.com/beacon/csp?src=yahoocom-expect-ct-report-only\"" - ], - "x-xss-protection": [ - "1; mode=block" - ], - "x-content-type-options": [ - "nosniff" - ] - }, - "body": "mloUP8q7ZPH" - } -} \ No newline at end of file diff --git a/tests/testYf.ts b/tests/testYf.ts index 79aa1f2a..2936e3a0 100644 --- a/tests/testYf.ts +++ b/tests/testYf.ts @@ -2,7 +2,6 @@ import _env from "../src/env-test"; import _opts from "../src/lib/options"; import _fetch from "../src/lib/yahooFinanceFetch"; import _moduleExec from "../src/lib/moduleExec"; -import _moduleExecTypebox from "../src/lib/moduleExecTypebox"; export default function genYf(extend: object): any { return { @@ -10,7 +9,6 @@ export default function genYf(extend: object): any { _opts, _fetch, _moduleExec, - _moduleExecTypebox, ...extend, }; } diff --git a/yarn.lock b/yarn.lock index 9ca568da..0f039811 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1644,11 +1644,6 @@ expect "^29.0.0" pretty-format "^29.0.0" -"@types/json-schema@^7.0.12": - version "7.0.13" - resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.13.tgz#02c24f4363176d2d18fc8b70b9f3c54aba178a85" - integrity sha512-RbSSoHliUbnXj3ny0CNFOoxrIDV6SUGyStHsvDqosw6CkdPV8TtWGlfecuK4ToyMEAql6pzNxgCFKanovUzlgQ== - "@types/json-schema@^7.0.9": version "7.0.9" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.9.tgz#97edc9037ea0c38585320b28964dde3b39e4660d" @@ -1883,23 +1878,6 @@ aggregate-error@^3.0.0: clean-stack "^2.0.0" indent-string "^4.0.0" -ajv-formats@2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ajv-formats/-/ajv-formats-2.1.1.tgz#6e669400659eb74973bbf2e33327180a0996b520" - integrity sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA== - dependencies: - ajv "^8.0.0" - -ajv@8.10.0, ajv@^8.0.0: - version "8.10.0" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.10.0.tgz#e573f719bd3af069017e3b66538ab968d040e54d" - integrity sha512-bzqAEZOjkrUMl2afH8dknrq5KEk2SrwdBROR+vH1EKVQTqaUbJVPdc/gEdggTMM0Se+s+Ja4ju4TlNcStKl2Hw== - dependencies: - fast-deep-equal "^3.1.1" - json-schema-traverse "^1.0.0" - require-from-string "^2.0.2" - uri-js "^4.2.2" - ajv@^6.12.4: version "6.12.6" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" @@ -2151,13 +2129,6 @@ brace-expansion@^1.1.7: balanced-match "^1.0.0" concat-map "0.0.1" -brace-expansion@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" - integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== - dependencies: - balanced-match "^1.0.0" - braces@^3.0.1: version "3.0.2" resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" @@ -2467,11 +2438,6 @@ combined-stream@^1.0.8: dependencies: delayed-stream "~1.0.0" -commander@^11.0.0: - version "11.0.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-11.0.0.tgz#43e19c25dbedc8256203538e8d7e9346877a6f67" - integrity sha512-9HMlXtt/BNoYr8ooyjjNRdIilOTkVJXB+GhxMTtOKwk0R4j4lS4NpjuqmRxroBfnfTSHQIHQB7wryHhXarNjmQ== - common-ancestor-path@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/common-ancestor-path/-/common-ancestor-path-1.0.1.tgz#4f7d2d1394d91b7abdf51871c62f71eadb0182a7" @@ -3322,17 +3288,6 @@ glob@^7.2.0: once "^1.3.0" path-is-absolute "^1.0.0" -glob@^8.0.3: - version "8.1.0" - resolved "https://registry.yarnpkg.com/glob/-/glob-8.1.0.tgz#d388f656593ef708ee3e34640fdfb99a9fd1c33e" - integrity sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^5.0.1" - once "^1.3.0" - globals@^11.1.0: version "11.12.0" resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" @@ -4299,11 +4254,6 @@ json-schema-traverse@^0.4.1: resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== -json-schema-traverse@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" - integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== - json-stable-stringify-without-jsonify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" @@ -4768,13 +4718,6 @@ minimatch@^3.0.5, minimatch@^3.1.2: dependencies: brace-expansion "^1.1.7" -minimatch@^5.0.1: - version "5.1.6" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.6.tgz#1cfcb8cf5522ea69952cd2af95ae09477f122a96" - integrity sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g== - dependencies: - brace-expansion "^2.0.1" - minimist-options@4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/minimist-options/-/minimist-options-4.1.0.tgz#c0655713c53a8a2ebd77ffa247d342c40f010619" @@ -5232,11 +5175,6 @@ npmlog@^6.0.0, npmlog@^6.0.1: gauge "^4.0.0" set-blocking "^2.0.0" -oas-schema-walker@1.1.5: - version "1.1.5" - resolved "https://registry.yarnpkg.com/oas-schema-walker/-/oas-schema-walker-1.1.5.tgz#74c3cd47b70ff8e0b19adada14455b5d3ac38a22" - integrity sha512-2yucenq1a9YPmeNExoUa9Qwrt9RFkjqaMAA1X+U7sbb0AqBeTIdMHky9SQQ6iN94bO5NW0W4TRYXerG+BdAvAQ== - once@^1.3.0, once@^1.3.1, once@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" @@ -5769,11 +5707,6 @@ require-directory@^2.1.1: resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= -require-from-string@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" - integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== - requires-port@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" @@ -5849,11 +5782,6 @@ safe-buffer@~5.2.0: resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== -safe-stable-stringify@^2.4.3: - version "2.4.3" - resolved "https://registry.yarnpkg.com/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz#138c84b6f6edb3db5f8ef3ef7115b8f55ccbf886" - integrity sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g== - "safer-buffer@>= 2.1.2 < 3.0.0": version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" @@ -6397,19 +6325,6 @@ ts-jest@29.1.2: semver "^7.5.3" yargs-parser "^21.0.1" -ts-json-schema-generator@1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/ts-json-schema-generator/-/ts-json-schema-generator-1.5.0.tgz#9f5cea606c27ebcf13060157542ac1d3b225430f" - integrity sha512-RkiaJ6YxGc5EWVPfyHxszTmpGxX8HC2XBvcFlAl1zcvpOG4tjjh+eXioStXJQYTvr9MoK8zCOWzAUlko3K0DiA== - dependencies: - "@types/json-schema" "^7.0.12" - commander "^11.0.0" - glob "^8.0.3" - json5 "^2.2.3" - normalize-path "^3.0.0" - safe-stable-stringify "^2.4.3" - typescript "~5.3.2" - ts-node@10.9.2: version "10.9.2" resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.2.tgz#70f021c9e185bccdca820e26dc413805c101c71f" @@ -6493,11 +6408,6 @@ typescript@5.4.3: resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.4.3.tgz#5c6fedd4c87bee01cd7a528a30145521f8e0feff" integrity sha512-KrPd3PKaCLr78MalgiwJnA25Nm8HAmdwN3mYUYZgG/wizIo9EainNVQI9/yDavtVFRN2h3k8uf3GLHuhDMgEHg== -typescript@~5.3.2: - version "5.3.2" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.3.2.tgz#00d1c7c1c46928c5845c1ee8d0cc2791031d4c43" - integrity sha512-6l+RyNy7oAHDfxC4FzSJcz9vnjTKxrLpDG5M2Vu4SHRVNg6xzqZp6LYSR9zjqQTu8DU/f5xwxUdADOkbrIX2gQ== - uglify-js@^3.1.4: version "3.12.5" resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.12.5.tgz#83241496087c640efe9dfc934832e71725aba008"