"use strict";
var _ = require("underscore");
var Type = require("../core/Type");
const _default_config = {
};
/**
* Represents a time series data point, where properties will be for price and volume.
* @typedef {Object} DataPoint
* @memberof timeseries
*/
/**
* Used to map OHLCV data point properties.
* @typedef {Object} FieldMap
* @property {string} time Name of time field.
* @property {string} open Name of open field.
* @property {string} high Name of high field.
* @property {string} low Name of low field.
* @property {string} close Name of close field.
* @property {string} volume Name of volume field.
* @memberof timeseries
*/
/**
* @typedef {Object} ValueBounds
* @property {number} min
* @property {number} max
* @memberof timeseries
*/
/**
* @typedef {Object} MinAndMaxFields
* @property {(string|undefined)} min
* @property {(string|undefined)} max
* @memberof timeseries
*/
/**
* @typedef {Object} MinAndMaxValues
* @property {number|undefined} min
* @property {number|undefined} max
* @memberof timeseries
*/
/**
* The time series data that is represented graphically in the chart panels.
*
* @extends core.Type
* @memberof timeseries
*/
class TimeSeriesData extends Type {
/**
* Instantiate TimeSeriesData
* @constructor
* @param {timeseries.DataPoint[]} raw_data
* @param {timeseries.FieldMap} field_map
* @param {string} symbol
* @param {string} gran
* @param {Object} config
*/
constructor(raw_data, field_map, symbol, gran, config) {
config = _.extend({}, _default_config, config);
super(config);
this._raw_data = raw_data;
this._field_map = field_map;
this._symbol = symbol;
this._granularity = gran;
this._initTimeToIndexMap();
}
/**
* Initialize time-to-index map.
* @private
*/
_initTimeToIndexMap() {
this._time_to_index_map = {};
for(var i = 0; i < this._raw_data.length; i++)
{
var dat = this._raw_data[i];
var time = dat[this._field_map.time];
this._time_to_index_map[time] = i;
}
}
/**
* Get data array, that was originally provided in the constructor.
* @returns {timeseries.DataPoint[]}
*/
getRawData() {
return this._raw_data;
}
/**
* Get field map, that was originally provided in the constructor.
* @returns {timeseries.FieldMap}
*/
getFieldMap() {
return this._field_map;
}
/**
* Get symbol
* @returns {string}
*/
getSymbol() {
return this._symbol;
}
/**
* Get granularity
* @returns {string}
*/
getGranularity() {
return this._granularity;
}
/**
* Deduce minimum and maximum values of in range data.
*
* Minimum and maximum values can be explicity given, otherwise field names.
* Where no minimum is provided, zero will be assumed.
* @param {number} count
* @param {number} offset
* @param {timeseries.MinAndMaxFields} min_and_max_fields
* @param {timeseries.MinAndMaxValues} min_and_max_values
* @returns {timeseries.ValueBounds}
*/
findValueBounds(count, offset, min_and_max_fields, min_and_max_values) {
var data_arr = this._raw_data;
var index_start = offset;
var index_end = (count + offset) - 1;
if(index_start < 0)
{
index_start = 0;
}
if(index_end >= data_arr.length)
{
index_end = data_arr.length - 1;
}
var min_field = min_and_max_fields.min;
var max_field = min_and_max_fields.max;
var min_value = min_and_max_values.min;
var max_value = min_and_max_values.max;
var minimum = 99999999, maximum = -99999999;
var i, dat;
// Deduce minimum value
if(min_value !== undefined)
{
minimum = min_value;
}
else if(min_field !== undefined)
{
var min_field_name = this._field_map[min_field];
for(i = index_start; i <= index_end; i++)
{
dat = data_arr[i];
var min = dat[min_field_name]; // e.g. low
if(min < minimum)
{
minimum = min;
}
}
}
else
{
minimum = 0;
}
// Deduce maximum value
if(max_value !== undefined)
{
maximum = max_value;
}
else if(max_field !== undefined)
{
var max_field_name = this._field_map[max_field];
for(i = index_start; i <= index_end; i++)
{
dat = data_arr[i];
var max = dat[max_field_name]; // e.g. low
if(max > maximum)
{
maximum = max;
}
}
}
return {
min: minimum,
max: maximum
};
}
}
module.exports = TimeSeriesData;