Skip to content

Commit

Permalink
fix(chart): more query tests, intervals, edge cases (#336)
Browse files Browse the repository at this point in the history
  • Loading branch information
gadicc committed Nov 23, 2021
1 parent 6332f31 commit 6b95d7e
Show file tree
Hide file tree
Showing 5 changed files with 664 additions and 23 deletions.
82 changes: 76 additions & 6 deletions schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,6 @@
},
"required": [
"meta",
"timestamp",
"indicators"
],
"additionalProperties": false
Expand Down Expand Up @@ -216,6 +215,12 @@
"chartPreviousClose": {
"yahooFinanceType": "number"
},
"previousClose": {
"yahooFinanceType": "number"
},
"scale": {
"yahooFinanceType": "number"
},
"priceHint": {
"yahooFinanceType": "number"
},
Expand All @@ -239,6 +244,9 @@
],
"additionalProperties": false
},
"tradingPeriods": {
"$ref": "#/definitions/ChartMetaTradingPeriods"
},
"dataGranularity": {
"type": "string"
},
Expand Down Expand Up @@ -296,6 +304,39 @@
],
"additionalProperties": false
},
"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"
}
}
}
},
"additionalProperties": false
},
"ChartEventsObject": {
"type": "object",
"properties": {
Expand Down Expand Up @@ -377,8 +418,7 @@
}
},
"required": [
"quote",
"adjclose"
"quote"
],
"additionalProperties": false
},
Expand Down Expand Up @@ -550,9 +590,19 @@
"interval": {
"type": "string",
"enum": [
"1m",
"2m",
"5m",
"15m",
"30m",
"60m",
"90m",
"1h",
"1d",
"5d",
"1wk",
"1mo"
"1mo",
"3mo"
]
},
"includePrePost": {
Expand Down Expand Up @@ -612,9 +662,19 @@
"interval": {
"type": "string",
"enum": [
"1m",
"2m",
"5m",
"15m",
"30m",
"60m",
"90m",
"1h",
"1d",
"5d",
"1wk",
"1mo"
"1mo",
"3mo"
]
},
"includePrePost": {
Expand Down Expand Up @@ -671,9 +731,19 @@
"interval": {
"type": "string",
"enum": [
"1m",
"2m",
"5m",
"15m",
"30m",
"60m",
"90m",
"1h",
"1d",
"5d",
"1wk",
"1mo"
"1mo",
"3mo"
]
},
"includePrePost": {
Expand Down
26 changes: 26 additions & 0 deletions src/modules/chart.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,32 @@ describe("chart", () => {
);
});

describe("specific cases", () => {
it("optional fields, empty arrays", async () => {
/*
* Same day period with 1h interval, this result has these aspects:
*
* - Missing fields: timestamp (because no quotes)
* - New fields: previousClose, scale, tradingPeriods
* - Pecularity: indicators.quote is [{}], indicators.adjclose missing
*/
await yf.chart(
"TSLA",
{ period1: "2021-11-23", period2: "2021-11-23", interval: "1h" },
{ devel: "chart-TSLA-2021-11-23-to-2021-11-23-interval-1h.json" }
);
});

it("", async () => {
// Had tradingPeriod.regular, probably a timezone thing
await yf.chart(
"TSLA",
{ period1: "2021-11-22", period2: "2021-11-23", interval: "30m" },
{ devel: "chart-TSLA-2021-11-22-to-2021-11-23-interval-30m.json" }
);
});
});

it("throws on malformed result", () => {
return expect(() => {
consoleSilent();
Expand Down
79 changes: 62 additions & 17 deletions src/modules/chart.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import type {

export interface ChartResultObject {
meta: ChartMeta;
timestamp: Array<number>;
timestamp?: Array<number>;
events?: ChartEventsObject;
indicators: ChartIndicatorsObject;
}
Expand Down Expand Up @@ -42,12 +42,15 @@ export interface ChartMeta {
exchangeTimezoneName: string; // "America/New_York",
regularMarketPrice: number; // 160.55,
chartPreviousClose: number; // 79.75,
previousClose?: number; // 1137.06
scale?: number; // 3,
priceHint: number; // 2,
currentTradingPeriod: {
pre: ChartMetaTradingPeriod;
regular: ChartMetaTradingPeriod;
post: ChartMetaTradingPeriod;
};
tradingPeriods?: ChartMetaTradingPeriods;
dataGranularity: string; // "1d",
range: string; // "",
validRanges: Array<string>; // ["1d", "5d", "1mo", "3mo", "6mo", "1y", "2y", "5y", "10y", "ytd", "max"]
Expand All @@ -60,6 +63,12 @@ export interface ChartMetaTradingPeriod {
gmtoffset: number; // -18000
}

export interface ChartMetaTradingPeriods {
pre?: Array<Array<ChartMetaTradingPeriod>>;
post?: Array<Array<ChartMetaTradingPeriod>>;
regular?: Array<Array<ChartMetaTradingPeriod>>;
}

export interface ChartEventsObject {
dividends?: ChartEventDividends;
splits?: ChartEventSplits;
Expand Down Expand Up @@ -92,7 +101,7 @@ export interface ChartEventSplit {

export interface ChartIndicatorsObject {
quote: Array<ChartIndicatorQuote>;
adjclose: Array<ChartIndicatorAdjclose>;
adjclose?: Array<ChartIndicatorAdjclose>;
}

export interface ChartIndicatorQuote {
Expand All @@ -111,7 +120,20 @@ export interface ChartOptions {
period1: Date | string | number;
period2?: Date | string | number;
useYfid?: boolean; // true
interval?: "1d" | "1wk" | "1mo"; // '1d', TODO: all | types
interval?:
| "1m"
| "2m"
| "5m"
| "15m"
| "30m"
| "60m"
| "90m"
| "1h"
| "1d"
| "5d"
| "1wk"
| "1mo"
| "3mo";
includePrePost?: boolean; // true
events?: string; // 'history',
lang?: string; // "en-US"
Expand Down Expand Up @@ -199,7 +221,27 @@ export default async function _chart(
transformWith(result: any) {
if (!result.chart)
throw new Error("Unexpected result: " + JSON.stringify(result));
return result.chart.result[0];

const chart = result.chart.result[0];

// If there are no quotes, chart.timestamp will be empty, but Yahoo also
// gives us chart.indicators.quotes = [{}]. Let's clean that up and
// deliver an empty array rather than an invalid ChartIndicatorQuote/
if (!chart.timestamp) {
if (chart.indicators.quote.length !== 1)
throw new Error(
"No timestamp with quotes.length !== 1, please report with your query"
);
if (Object.keys(chart.indicators.quote[0]).length !== 0)
// i.e. {}
throw new Error(
"No timestamp with unexpected quote, please report with your query" +
JSON.stringify(chart.indicators.quote[0])
);
chart.indicators.quote.pop();
}

return chart;
},
},

Expand All @@ -225,11 +267,12 @@ export default async function _chart(

// istanbul ignore next
if (
timestamp &&
result?.indicators?.quote &&
result.indicators.quote[0].high.length !== timestamp.length
) {
console.log({
origTimestampSize: result.timestamp.length,
origTimestampSize: result.timestamp && result.timestamp.length,
filteredSize: timestamp.length,
quoteSize: result.indicators.quote[0].high.length,
});
Expand All @@ -240,22 +283,24 @@ export default async function _chart(

const result2 = {
meta: result.meta,
quotes: new Array(timestamp.length),
quotes: timestamp ? new Array(timestamp.length) : new Array(),
} as ChartResultArray;

const adjclose = result?.indicators?.adjclose?.[0].adjclose;

for (let i = 0; i < timestamp.length; i++) {
result2.quotes[i] = {
date: new Date(timestamp[i] * 1000),
high: result.indicators.quote[0].high[i],
volume: result.indicators.quote[0].volume[i],
open: result.indicators.quote[0].open[i],
low: result.indicators.quote[0].low[i],
close: result.indicators.quote[0].close[i],
};
if (adjclose) result2.quotes[i].adjclose = adjclose[i];
}
if (timestamp)
for (let i = 0; i < timestamp.length; i++) {
result2.quotes[i] = {
date: new Date(timestamp[i] * 1000),
high: result.indicators.quote[0].high[i],
volume: result.indicators.quote[0].volume[i],
open: result.indicators.quote[0].open[i],
low: result.indicators.quote[0].low[i],
close: result.indicators.quote[0].close[i],
};
// @ts-ignore: adjClose guarantees the chain.
if (adjclose) result2.quotes[i].adjclose = adjclose[i];
}

if (result.events) {
result2.events = {};
Expand Down

0 comments on commit 6b95d7e

Please sign in to comment.