diff --git a/demos/stock-ohlcv/demo.js b/demos/stock-ohlcv/demo.js index 09ace0a..005bff1 100644 --- a/demos/stock-ohlcv/demo.js +++ b/demos/stock-ohlcv/demo.js @@ -7,6 +7,7 @@ async function displayOHLCV (postmanJSON) { postman: { environmentJSON: postmanJSON }, + replaceZeroWithCloseValue: true, series: { type: 'OHLCV' }, diff --git a/src/TimeSeries/Converters/OHLCVSeriesConverter.ts b/src/TimeSeries/Converters/OHLCVSeriesConverter.ts index 5e7db84..a9d09e2 100644 --- a/src/TimeSeries/Converters/OHLCVSeriesConverter.ts +++ b/src/TimeSeries/Converters/OHLCVSeriesConverter.ts @@ -108,10 +108,20 @@ export class OHLCVSeriesConverter extends TimeSeriesConverter { const sortedOHLCVItems: Array = []; for (const ohlcvItem of json) { + const [date, /* Open */ , /* High */, /* Low */, close, volume] = ohlcvItem; + let [/* Date */, open, high, low] = ohlcvItem; + + + if (volume === 0 && userOptions.replaceZeroWithCloseValue) { + open = close; + high = close; + low = close; + } + sortedOHLCVItems.push({ Id: securityIds[0], - Date: ohlcvItem[0], - Value: [ohlcvItem[1], ohlcvItem[2], ohlcvItem[3], ohlcvItem[4], ohlcvItem[5]] + Date: date, + Value: [open, high, low, close, volume] }); } diff --git a/src/TimeSeries/TimeSeriesConnector.ts b/src/TimeSeries/TimeSeriesConnector.ts index 2da6fbe..0c49f7b 100644 --- a/src/TimeSeries/TimeSeriesConnector.ts +++ b/src/TimeSeries/TimeSeriesConnector.ts @@ -29,7 +29,7 @@ import MorningstarConnector from '../Shared/MorningstarConnector'; import MorningstarURL from '../Shared/MorningstarURL'; import CumulativeReturnSeriesConverter from './Converters/CumulativeReturnSeriesConverter'; import DividendSeriesConverter from './Converters/DividendSeriesConverter'; -import TimeSeriesOptions from './TimeSeriesOptions'; +import TimeSeriesOptions, { OHLCVSeriesOptions } from './TimeSeriesOptions'; import TimeSeriesRatingConverter from './Converters/RatingSeriesConverter'; import PriceSeriesConverter from './Converters/PriceSeriesConverter'; import TimeSeriesConverter from './TimeSeriesConverter'; @@ -99,7 +99,9 @@ export class TimeSeriesConnector extends MorningstarConnector { this.converter = new OHLCVSeriesConverter({ ...options.converter, ...options.series, - securities: options.securities + securities: options.securities, + replaceZeroWithCloseValue: (options as OHLCVSeriesOptions) + .replaceZeroWithCloseValue }); break; diff --git a/src/TimeSeries/TimeSeriesOptions.ts b/src/TimeSeries/TimeSeriesOptions.ts index 1bf4544..380aedf 100644 --- a/src/TimeSeries/TimeSeriesOptions.ts +++ b/src/TimeSeries/TimeSeriesOptions.ts @@ -119,6 +119,17 @@ export interface OHLCVSeriesOptions extends TimeSeriesConverterOptions { */ type: 'OHLCV'; + /** + * When this property is `true`, open, high and low are replaced with + * the close value if the volume is zero. + * + * If volume is zero, open high low are zero too. If you do not prefer this + * behavior, you can enable this property. + * + * @default false + */ + replaceZeroWithCloseValue?: boolean; + /** * Security to retrieve. */ diff --git a/test/unit-tests/TimeSeries/OHLCV.test.ts b/test/unit-tests/TimeSeries/OHLCV.test.ts index 1d416f4..57e61af 100644 --- a/test/unit-tests/TimeSeries/OHLCV.test.ts +++ b/test/unit-tests/TimeSeries/OHLCV.test.ts @@ -51,3 +51,71 @@ export async function ohlcvLoad ( ); } + +export function ohlcvReplaceZeroWithClose () { + const data = [ + [1722816000000, 0, 0, 0, 14754.871, 0], + [1722816000001, 0, 0, 0, 14754.871, 1] + ]; + + const expectedFirstRow = [1722816000000, 14754.871, 14754.871, 14754.871, 14754.871, 0]; + const expectedSecondRow = [1722816000001, 0, 0, 0, 14754.871, 1]; + + const converter = new MC.TimeSeriesConverters.OHLCVSeriesConverter({ + type: 'OHLCV', + replaceZeroWithCloseValue: true, + securities: [ + { + id: 'XIUSA000O2', + idType: 'SECID' + } + ], + json: data + }); + + converter.parse({ type: 'OHLCV' }); + + const dataTable = converter.getTable(); + + Assert.deepEqual( + dataTable.getRow(0), + expectedFirstRow, + 'Should replace o, h, l with c when v is 0' + ); + + Assert.deepEqual( + dataTable.getRow(1), + expectedSecondRow, + 'Should not replace o, h, l with c when v is not 0' + ); +} + +export function ohlcvDoNotReplaceZeroWithClose () { + const data = [ + [1722816000000, 0, 0, 0, 14754.871, 0] + ]; + + const expectedRow = [1722816000000, 0, 0, 0, 14754.871, 0]; + + const converter = new MC.TimeSeriesConverters.OHLCVSeriesConverter({ + type: 'OHLCV', + replaceZeroWithCloseValue: false, + securities: [ + { + id: 'XIUSA000O2', + idType: 'SECID' + } + ], + json: data + }); + + converter.parse({ type: 'OHLCV' }); + + const dataTable = converter.getTable(); + + Assert.deepEqual( + dataTable.getRow(0), + expectedRow, + 'Should not replace o, h, l with c when v is 0' + ); +}