ohlcv-indicators 3.5.85 → 3.5.86
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1 +1 @@
|
|
|
1
|
-
var OHLCV_INDICATORS;(()=>{"use strict";const e={d:(t,i)=>{for(var s in i)e.o(i,s)&&!e.o(t,s)&&Object.defineProperty(t,s,{enumerable:!0,get:i[s]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t)};let t={};(()=>{e.d(t,{default:()=>ee});const i=(e,t)=>{if(0===e.length)return!1;for(let i=0;i<e.length;i++){const s=e[i][t];if(null==s||Number.isNaN(s))return!1}return!0},s=(e,t)=>{if(!Array.isArray(e))throw new Error('Property "inputParams" must be an "Array" or "Set".');for(const i of e){if(!i||"string"!=typeof i.key||!Array.isArray(i.params))throw new TypeError("Each inputParams entry must have an indicator key and a params array.");if(void 0!==i.order&&!Number.isFinite(i.order))throw new TypeError("Indicator order must be a finite number when provided.");const{params:e}=i;for(const i of e)if("number"==typeof i&&i>t)throw console.log(i,t),new Error("At least one of the params of the indicator is greater than the input OHLCV length. Make sure to have enough datapoints in the input OHLCV.")}},o=e=>{if(!0===e.isComputing)throw Error("You cannot add indicators while computation is in progress.");if(!0===e.isComputed)throw Error('ohlcv is already computed, you can not add new indicators after "compute", "getLastValues" or "getData" methods are called.')},n=(e,t,i)=>{if(!Array.isArray(e))throw new Error(`Param "${t}" must be an array in "${i}".`);return!0},r=(e,t,i)=>{if(e instanceof Object==0)throw new Error(`Param "${t}" must be an object in "${i}".`);return!0},a=(e,t,i,s)=>{if(n(e,"arrayOptions",`${s}.${i}.validateArrayOptions`),!e.includes(t.toString()))throw new Error(`Param "${i}" must be any of the following values [${e.join(", ")}] in "${s}".`);return!0},l=(e,t,i)=>{if("boolean"!=typeof e)throw new Error(`Param "${t}" must be an boolean in "${i}".`);return!0},c=(e,t,i,s)=>{r(t,"options",`${s}.${i}.validateNumber`);const{allowDecimals:o=!1,min:n,max:a}=t,l=o?"number":"integer";if("number"!=typeof e||!1===o&&!Number.isInteger(e))throw new Error(`Param "${i}" must be an ${l} in "${s}".`);if(void 0!==n&&"number"!=typeof n)throw new Error(`Param "min" must be a valid ${l} (if provided) in "${s}.${i}.validateNumber".`);if(void 0!==a&&"number"!=typeof a)throw new Error(`Param "max" must be a valid ${l} (if provided) in "${s}.${i}.validateNumber".`);if(void 0!==n&&void 0!==a&&n>=a)throw new Error(`Param "min" must be less than "max" in "${s}.${i}.validateNumber".`);if(void 0!==n&&e<n)throw new Error(`Param "${i}" must be an ${l} ≥ ${n} in "${s}".`);if(void 0!==a&&e>a)throw new Error(`Param "${i}" must be an ${l} ≤ ${a} in "${s}".`);return!0},h=(e,t,i)=>{if("string"!=typeof e||!e.length)throw new Error(`Invalid "${t}" property in "${i}". Only strings are accepted.`);return!0},u=(e,t,i,s)=>{if(0!==i)return!0;const o=[];for(const s of Object.keys(e)){const e=t[s]?.[i];("volume"===s?Number.isFinite(e)&&e>=0:Number.isFinite(e)&&e>0)||o.push(s)}if(o.length>0)throw new TypeError(`Invalid or missing input value(s) [${o.join(", ")}] at index ${i} in "${s}".`);return!0};class p extends Error{constructor(e="Not enough data"){super(e),this.name="NotEnoughDataError"}}class m{constructor(){this.result=void 0}get isStable(){return void 0!==this.result}getResult(){if(!this.isStable)throw new p;return this.result}}class d extends m{constructor(){super(),this.previousResult=void 0,this.highest=void 0,this.lowest=void 0,this.previousHighest=void 0,this.previousLowest=void 0}setResult(e,t=!1){return t&&(this.highest=this.previousHighest,this.lowest=this.previousLowest,this.result=this.previousResult),void 0===this.highest?this.highest=e:(this.previousHighest=this.highest,e>this.highest&&(this.highest=e)),void 0===this.lowest?this.lowest=e:(this.previousLowest=this.lowest,e<this.lowest&&(this.lowest=e)),this.previousResult=this.result,this.result=e,e}replace(e){return this.update(e,!0)}updates(e){return e.forEach(e=>this.update(e)),this.result}}class g extends d{constructor(e){super(),this.interval=e,this.pricesCounter=0,this.weightFactor=2/(e+1)}update(e,t=!1){t&&0!==this.pricesCounter||this.pricesCounter++;const i=t&&void 0!==this.previousResult?this.previousResult:void 0!==this.result?this.result:e;return this.setResult(e*this.weightFactor+i*(1-this.weightFactor),t)}get isStable(){return this.pricesCounter>=this.interval}}class f extends d{constructor(e){super(),this.interval=e,this.prices=new Float64Array(e),this.count=0,this.head=0}update(e,t=!1){"number"==typeof e||Array.isArray(this.prices)||(this.prices=Array.from(this.prices));const{interval:i,prices:s}=this;if(t&&this.count){let t=this.head+this.count-1;t>=i&&(t-=i),s[t]=e}else this.count<i?s[this.count++]=e:(s[this.head]=e,++this.head===i&&(this.head=0));if(this.count===i){let e=0;for(let t=this.head;t<i;t++)e+=s[t];for(let t=0;t<this.head;t++)e+=s[t];return this.setResult(e/i,t)}}}class v extends d{constructor(e){super(),this.interval=e,this.indicator=new f(e),this.smoothingFactor=1/e}update(e,t=!1){if(void 0===this.result){const i=this.indicator.update(e);if(void 0!==i)return this.indicator=void 0,this.setResult(i,t)}else{if(t&&void 0!==this.previousResult){const i=(e-this.previousResult)*this.smoothingFactor;return this.setResult(i+this.previousResult,t)}if(!t){const i=(e-this.result)*this.smoothingFactor;return this.setResult(i+this.result,t)}}}}class y extends d{constructor(e,t=v){super(),this.interval=e,this.avgGain=new t(e),this.avgLoss=new t(e),this.maxValue=100,this.priceCount=0,this.previousPrice=void 0,this.currentPrice=void 0}update(e,t=!1){if(t&&0!==this.priceCount||(this.previousPrice=this.currentPrice,this.priceCount<2&&this.priceCount++),this.currentPrice=e,this.priceCount<2)return;const i=this.previousPrice;if(e>i?(this.avgLoss.update(0,t),this.avgGain.update(e-i,t)):(this.avgLoss.update(i-e,t),this.avgGain.update(0,t)),this.avgGain.isStable){const e=this.avgLoss.getResult();if(0===e)return this.setResult(100,t);const i=this.avgGain.getResult()/e;return this.setResult(this.maxValue-this.maxValue/(i+1),t)}}}class w extends d{constructor(){super(),this.previousCandle=void 0,this.twoPreviousCandle=void 0}update(e,t=!1){const{high:i,low:s}=e,o=i-s;if(this.previousCandle&&t&&(this.previousCandle=this.twoPreviousCandle),this.previousCandle){const n=Math.abs(i-this.previousCandle.close),r=Math.abs(s-this.previousCandle.close);return this.twoPreviousCandle=this.previousCandle,this.previousCandle=e,this.setResult(Math.max(o,n,r),t)}return this.twoPreviousCandle=this.previousCandle,this.previousCandle=e,this.setResult(o,t)}}class b extends d{constructor(e,t=v){super(),this.interval=e,this.tr=new w,this.smoothing=new t(e)}update(e,t=!1){const i=this.tr.update(e,t);if(this.smoothing.update(i,t),this.smoothing.isStable)return this.setResult(this.smoothing.getResult(),t)}}class $ extends d{constructor(e,t=v){super(),this.interval=e,this.atr=new b(e,t),this.movesDown=new t(e),this.movesUp=new t(e),this.previousCandle=void 0,this.mdi=void 0,this.pdi=void 0}updateState(e,t=0,i=0){this.atr.update(e),this.movesUp.update(t),this.movesDown.update(i),this.previousCandle=e}update(e){if(!this.previousCandle)return void this.updateState(e);const t=e.high-this.previousCandle.high,i=this.previousCandle.low-e.low,s=t<0||t<i?0:t,o=i<0||i<t?0:i;if(this.updateState(e,s,o),this.movesUp.isStable){const e=this.atr.getResult();this.pdi=this.movesUp.getResult()/e,this.mdi=this.movesDown.getResult()/e;const t=Math.abs(this.pdi-this.mdi),i=this.pdi+this.mdi;return 0===i?this.setResult(0,!1):this.setResult(t/i*100,!1)}}}class _ extends d{constructor(e,t=v){super(),this.interval=e,this.adx=new t(e),this.dx=new $(e,t)}get mdi(){return this.dx.mdi}get pdi(){return this.dx.pdi}update(e,t=!1){const i=this.dx.update(e);if(void 0!==i&&this.adx.update(i),this.adx.isStable)return this.setResult(this.adx.getResult(),t)}}class N extends m{constructor(e,t=2){super(),this.interval=e,this.deviationMultiplier=t,this.prices=new Float64Array(e),this.count=0,this.head=0}update(e){if("number"==typeof e||Array.isArray(this.prices)||(this.prices=Array.from(this.prices)),this.count<this.interval)return void(this.prices[this.count++]=e);this.prices[this.head]=e,this.head=(this.head+1)%this.interval;let t=0,i=this.head;for(let e=0;e<this.count;e++)t+=this.prices[i],++i===this.interval&&(i=0);const s=this.count?t/this.count:0;let o=s;if(!o&&Array.isArray(this.prices)){t=0,i=this.head;for(let e=0;e<this.count;e++)t+=this.prices[i],++i===this.interval&&(i=0);o=this.count?t/this.count:0}let n=0;i=this.head;for(let e=0;e<this.count;e++){const e=this.prices[i]-o;n+=e*e,++i===this.interval&&(i=0)}const r=Math.sqrt(this.count?n/this.count:0);return this.result={lower:s-r*this.deviationMultiplier,middle:s,upper:s+r*this.deviationMultiplier}}}class x extends m{constructor(e,t,i){super(),this.short=e,this.long=t,this.signal=i,this.pricesCounter=0}update(e,t=!1){t&&0!==this.pricesCounter||this.pricesCounter++;const i=this.short.update(e,t),s=this.long.update(e,t);if(this.pricesCounter>this.long.interval&&this.pricesCounter--,this.pricesCounter===this.long.interval){const e=i-s,o=this.signal.update(e,t);return this.result={histogram:e-o,macd:e,signal:o}}}}class k extends m{constructor(e,t,i){super(),this.n=e,this.m=t,this.p=i,this.periodM=new f(t),this.periodP=new f(i),this.candles=new Array(e),this.count=0,this.head=0}update(e){if(this.count<this.n?this.candles[this.count++]=e:(this.candles[this.head]=e,this.head=(this.head+1)%this.n),this.count===this.n){let t=-1/0,i=1/0,s=this.head;for(let e=0;e<this.count;e++)t=Math.max(t,this.candles[s].high),++s===this.n&&(s=0);s=this.head;for(let e=0;e<this.count;e++)i=Math.min(i,this.candles[s].low),++s===this.n&&(s=0);const o=t-i,n=100*(e.close-i)/(0===o?1:o),r=this.periodM.update(n),a=r&&this.periodP.update(r);if(void 0!==r&&void 0!==a)return this.result={stochD:a,stochK:r}}}}const O=(e,t)=>{if(0===e&&(e=.001),0===t&&(t=.001),Math.sign(e)!==Math.sign(t))throw new Error(`[BUG] Params must have the same sign in mathLog a=${e} b=${t}.`);e<0&&(e=-e,t=-t);const i=Math.log(e/t);if(null==(s=i)||!Number.isFinite(s))throw new Error(`[BUG] Invalid params passed to mathLog a=${e} b=${t}.`);var s;return i},T=e=>{const t=String(e);return 1===e?0:t.length-1},M=(e,t,i)=>{if("string"!=typeof e)throw new Error("addPrecisionExact expects a string when precision=true");const s="-"===e.charAt(0),o=s?e.slice(1):e,[n,r=""]=o.split("."),a=void 0===i?T(t):i,l=r.padEnd(a,"0").slice(0,a);let c=parseInt(n+l||"0",10);return s&&(c=-c),c},S={number:e=>e,numberCleanString:e=>Number(e),precisionNumberCleanString:(e,t,i)=>M(e,t,i)},P=(e,t,i)=>((e,t,i)=>{if("number"!=typeof e||!Number.isFinite(e))throw new Error("revertPrecisionAsNumber expects a finite number");const s=e<0;let o=Math.abs(e);o=Math.trunc(o);const n=void 0===i?T(t):i;if(0===n)return s?-o:o;const r=Math.trunc(o/t);let a=String(o%t).padStart(n,"0");a=a.replace(/0+$/,"");const l=0===a.length?String(r):`${r}.${a}`;return Number(s?`-${l}`:l)})(e,t,i),F=(e,t=!1,i=!1)=>{const s="number"==typeof e&&!Number.isNaN(e),o="string"==typeof e&&/^-?\d+(\.\d+)?$/.test(e);if(!0===i){if(o)return"precisionNumberCleanString";if(t)throw new Error("Invalid number forma");return typeof e}if(s)return"number";if(o)return"numberCleanString";if(t)throw new TypeError("Invalid input: expected a number or numeric string");return typeof e},C={toString:e=>e.toString(),string:e=>e.toString(),toISOString:e=>e.toISOString(),iso:e=>e.toISOString(),toUTCString:e=>e.toUTCString(),milliseconds:e=>e.getTime(),seconds:e=>e.getTime()/1e3,object:e=>e},A={dateObject:e=>e,dateMilliseconds:e=>new Date(e),dateSeconds:e=>new Date(1e3*e),dateIncompleteDayString:e=>new Date(`${e} 00:00:00`),dateCompleteDateString:e=>new Date(e)},D=e=>{const t=/^\d{4}-\d{2}-\d{2}[T ]\d{2}:\d{2}:\d{2}(?:\.\d+)?Z$/i,i=/^\d{4}-\d{2}-\d{2}[T ]\d{2}:\d{2}:\d{2}(?:\.\d+)?([+-]\d{2}:\d{2})$/,s=/^\d{4}-\d{2}-\d{2}[T ]\d{2}:\d{2}:\d{2}(?:\.\d+)?$/,o=/^\d{4}-\d{2}-\d{2}$/,n=/^\d{4}\/\d{2}\/\d{2}$/,r=["Date -> object","Milliseconds Timestamp -> integer","Seconds Timestamp -> integer","UTC Time Format (ISO 8601) -> string","Including a Timezone Offset (ISO 8601) -> string","Local Time Format (ISO 8601) -> string","YYYY/MM/DD or YYYY-MM-DD -> string"],a=()=>{throw new Error(`Invalid "${typeof e}" date value passed in selectDateFormatter. Supported formats: \n-${r.join("\n- ")}`)};if("object"==typeof e){if(e instanceof Date&&!isNaN(e.valueOf()))return"dateObject";a()}else{if("number"==typeof e)return Math.abs(e)<1e11?"dateSeconds":"dateMillseconds";if("string"==typeof e){if(t.test(e)||i.test(e)||s.test(e)&&e.length>10||n.test(e))return"dateCompleteDateString";if(o.test(e))return"dateIncompleteDayString";a()}else a()}},L=(e,t,i)=>{const s={Array,Float64Array,Float32Array,Int32Array,Uint8Array,Int8Array,Int16Array}[e];if(!s||"function"!=typeof s.from)throw new Error(`Unsupported array type: ${e}`);let o;return o=void 0!==i?i:"Array"===e?null:NaN,new s(t).fill(o)},I=(e,t,{lag:i=0}={})=>{const s=[],o=[];for(const{key:i,type:n="Float64Array",fill:r,enabled:a=!0,priceBased:l=!1,includeInLag:c=!0}of t)if(a){if(Object.prototype.hasOwnProperty.call(e.verticalOhlcv,i))throw new Error(`Output column "${i}" already exists in verticalOhlcv.`);if(/^(?:Int|Uint)/.test(n)&&void 0===r)throw new Error(`Integer output column "${i}" requires an explicit fill value.`);e.verticalOhlcv[i]=L(n,e.len,r),l&&e.priceBased.add(i),s.push(i),c&&o.push(i)}return i>0&&o.length>0&&(c(i,{min:1,max:e.len},"lag","initializeColumns"),e.executionParams.push({key:"lag",params:[o,i]})),s},E=e=>null==e||!Number.isFinite(e),R={ema:g,sma:f},j=(e,t,i,s,{target:o,lag:n,retLogs:r=!1})=>{const{verticalOhlcv:a,instances:l,priceBased:c}=e,h=`${r?"ret_log_":""}${i}_${s}${"close"!==o?`_${o}`:""}`;if(0===t){if(u({[o]:!0},a,t,i),!a.hasOwnProperty(o))throw new Error(`Target property ${o} not found in verticalOhlcv for ${i}.`);l[h]=new R[i](s),I(e,r?[{key:`${h}_distance`,priceBased:!1},{key:`${h}_change`,priceBased:!1}]:[{key:h,priceBased:c.has(o)}],{lag:n})}const p=a[o][t];if(E(p))return;const m=l[h],d=m.isStable?m.getResult():NaN;m.update(p);const g=m.isStable?m.getResult():NaN;if(!E(g))if(r){const i=O(p,g);if(e.pushToMain({index:t,key:`${h}_distance`,value:i}),E(d))return;const s=O(g,d);e.pushToMain({index:t,key:`${h}_change`,value:s})}else e.pushToMain({index:t,key:h,value:g})},H=e=>null==e||!Number.isFinite(e),B=(e,t)=>(e-t)/t,V="close",K=Symbol("lagColumns"),U=(e,t)=>{const i=new Uint8Array(t);return i[e]=1,i},z=(e,t)=>e>t,Z=(e,t)=>e<t;class G{constructor(){Object.assign(this,{interval:0,prevState:.5,prevFast:NaN,prevSlow:NaN,prevHigh:NaN,prevLow:NaN,areHighAndLowUndefined:!1})}update(e,{fast:t,high:i,slow:s,low:o}){let n=this.prevState;this.areHighAndLowUndefined||void 0!==i&&void 0!==o||(this.areHighAndLowUndefined=!0),Number.isNaN(t)||Number.isNaN(s)||((e,t)=>e===t)(t,s)?n=.5:z(t,s)?n=this.areHighAndLowUndefined?1:[o,s,this.prevLow,this.prevSlow].every(e=>!Number.isNaN(e))&&Z(o,s)&&z(this.prevLow,this.prevSlow)?0:1:Z(t,s)&&(n=this.areHighAndLowUndefined?0:[i,s,this.prevHigh,this.prevSlow].every(e=>!Number.isNaN(e))&&z(i,s)&&Z(this.prevHigh,this.prevSlow)?1:0),.5===n?this.interval=0:1===n?this.prevState<=.5?this.interval=1:this.interval++:0===n&&(this.prevState>=.5?this.interval=-1:this.interval--),Object.assign(this,{prevState:n,prevFast:t,prevSlow:s,prevHigh:i,prevLow:o})}getResult(){return this.interval}}const Y=["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],q=e=>null==e||!Number.isFinite(e),J={candleFeatures:(e,t,{lag:i,colKeys:s,retLogs:o})=>{const{verticalOhlcv:n,priceBased:r,scaledGroups:a}=e,l=(e,t)=>o?Math.log(e/t):(e-t)/t,c=o?"ret_log_":"ret_";if(0===t){u({open:!0,high:!0,low:!0,close:!0},n,t,"candleFeatures");const o=["change","mid_price_change","upper_wick","lower_wick","gap","body","range"].map(e=>({key:`${c}${e}`}));for(const e of s){if(!n.hasOwnProperty(e))throw new Error(`Target property in "options.colKey" array "${e}" not found in verticalOhlcv for "candleFeatures".`);if(!r.has(e))throw new Error(`Target property in "options.colKey" array "${e}" not found in priceBased for "candleFeatures".`);o.push({key:`${c}${e}`})}a.candleFeatures=I(e,o,{lag:i})}const h=n.close[t-1],p=n.open[t-1];if(void 0===h)return;const m=n.open[t],d=n.high[t],g=n.low[t],f=n.close[t],v=(h+p)/2,y=(m+f)/2,w=Math.max(m,f),b=Math.min(m,f),$=l(f,h),_=l(y,v),N=l(d,w),x=l(b,g),k=l(m,h),O=l(f,m),T=l(d,g);if(0===s.length)return e.pushToMain({index:t,key:`${c}change`,value:$}),e.pushToMain({index:t,key:`${c}mid_price_change`,value:_}),e.pushToMain({index:t,key:`${c}upper_wick`,value:N}),e.pushToMain({index:t,key:`${c}lower_wick`,value:x}),e.pushToMain({index:t,key:`${c}gap`,value:k}),e.pushToMain({index:t,key:`${c}body`,value:O}),void e.pushToMain({index:t,key:`${c}range`,value:T});const M={[`${c}change`]:$,[`${c}mid_price_change`]:_,[`${c}upper_wick`]:N,[`${c}lower_wick`]:x,[`${c}gap`]:k,[`${c}body`]:O,[`${c}range`]:T};let S=!1;for(const e of s){const i=n[e][t];if(q(i)){S=!0;break}const s=l(f,i);M[`${c}${e}`]=s}if(!S)for(const[i,s]of Object.entries(M))e.pushToMain({index:t,key:i,value:s})},dateTime:(e,t,{lag:i,oneHot:s,precompute:o})=>{const{instances:n,verticalOhlcv:r}=e,{prefix:a}=o;if(0===t){const{dateType:t}=e;if(!t)throw Error('dateTime method found and invalid "date" in input ohlcv');Object.assign(n,{dateTime:{formatter:new Intl.DateTimeFormat("en-US-u-ca-gregory-nu-latn",{timeZone:e.timeZone,year:"numeric",month:"numeric",day:"numeric",weekday:"short",hour:"numeric",minute:"numeric",hourCycle:"h23"}),colKeys:[...o.colKeys,`${a}year`].filter(e=>"one_hot_year"!==e),colKeySizes:{...o.colKeySizes}}});const{colKeys:r}=n.dateTime;I(e,r.map(e=>({key:e,type:s?"Array":"Int16Array",fill:s?null:0})),{lag:i})}const{colKeySizes:l,formatter:c}=n.dateTime,h=r.date[t];let u,p,m,d,g,f;for(const e of c.formatToParts(h))switch(e.type){case"year":u=e.value;break;case"month":p=e.value;break;case"hour":m=e.value;break;case"minute":d=e.value;break;case"weekday":g=e.value;break;case"day":f=e.value}const v=Number(u),y=Number(p)-1,w=Number(m),b=Number(d),$=Y.indexOf(g),_=Number(f)-1;if(!s)return e.pushToMain({index:t,key:"year",value:v}),e.pushToMain({index:t,key:"month",value:y+1}),e.pushToMain({index:t,key:"hour",value:w}),e.pushToMain({index:t,key:"minute",value:b}),e.pushToMain({index:t,key:"day_of_the_week",value:($+6)%7+1}),void e.pushToMain({index:t,key:"day_of_the_month",value:_+1});const N=U(y,l.one_hot_month),x=U(w,l.one_hot_hour),k=U(b,l.one_hot_minute),O=U($,l.one_hot_day_of_the_week),T=U(_,l.one_hot_day_of_the_month);e.pushToMain({index:t,key:"one_hot_month",value:N}),e.pushToMain({index:t,key:"one_hot_hour",value:x}),e.pushToMain({index:t,key:"one_hot_minute",value:k}),e.pushToMain({index:t,key:"one_hot_day_of_the_week",value:O}),e.pushToMain({index:t,key:"one_hot_day_of_the_month",value:T})},heikenAshi:(e,t,i,s,{lag:o=0,noSmoothing:n=!1,retLogs:r=!1}={})=>{const{verticalOhlcv:a,instances:l,scaledGroups:c}=e,h=n?"heiken_ashi":`heiken_ashi_${i}_${s}`;if(0===t){u({open:!0,high:!0,low:!0,close:!0},a,t,"heikenAshi");const p=["open","high","low","close"],m=["body","upper_wick","lower_wick","range"],d=n?"":`_${i}_${s}`,f=r?"ret_log_":"ret_",v=Object.fromEntries(m.map(e=>[e,`${f}heiken_ashi_${e}${d}`])),y=`heiken_ashi_cross${d}`,w=Object.values(v);l[h]={emaPre:n?null:Object.fromEntries(p.map(e=>[e,new g(i)])),emaPost:n?null:Object.fromEntries(p.map(e=>[e,new g(s)])),prevHaOpen:NaN,prevHaClose:NaN,prevSmOpen:NaN,prevSmClose:NaN,trendDirection:0,getRet:r?O:B,outputKeys:v,crossKey:y},I(e,[...w,y].map(e=>({key:e})),{lag:o}),c&&(c.heikenAshi=w)}const p=a.open[t],m=a.high[t],d=a.low[t],f=a.close[t],v=l[h],{crossKey:y,emaPre:w,emaPost:b,getRet:$,outputKeys:_}=v;if(H(p)||H(m)||H(d)||H(f))return;let N,x,k,T;if(null!==w){if(w.open.update(p),w.high.update(m),w.low.update(d),w.close.update(f),!(w.open.isStable&&w.high.isStable&&w.low.isStable&&w.close.isStable))return;N=w.open.getResult(),x=w.high.getResult(),k=w.low.getResult(),T=w.close.getResult()}else N=p,x=m,k=d,T=f;if(H(N)||H(x)||H(k)||H(T))return;const M=(N+x+k+T)/4,S=Number.isNaN(v.prevHaOpen)||Number.isNaN(v.prevHaClose)?(N+T)/2:(v.prevHaOpen+v.prevHaClose)/2,P=Math.max(x,S,M),F=Math.min(k,S,M);let C,A,D,L;if(v.prevHaOpen=S,v.prevHaClose=M,null!==b){if(b.open.update(S),b.high.update(P),b.low.update(F),b.close.update(M),!(b.open.isStable&&b.high.isStable&&b.low.isStable&&b.close.isStable))return;C=b.open.getResult(),A=b.high.getResult(),D=b.low.getResult(),L=b.close.getResult()}else C=S,A=P,D=F,L=M;if(H(C)||H(A)||H(D)||H(L)||C<=0||A<=0||D<=0||L<=0)return;const E=Number.isFinite(v.prevSmOpen)&&Number.isFinite(v.prevSmClose),R=t>0?a[y][t-1]:NaN,j=L>C?1:L<C?-1:v.trendDirection;let V=0;E&&0!==j&&(V=Number.isFinite(R)&&Math.sign(R)===j?R+j:j),v.trendDirection=j,v.prevSmOpen=C,v.prevSmClose=L;const K=Math.max(C,L),U=Math.min(C,L),z=$(L,C),Z=$(A,K),G=$(U,D),Y=$(A,D);H(z)||e.pushToMain({index:t,key:_.body,value:z}),H(Z)||e.pushToMain({index:t,key:_.upper_wick,value:Z}),H(G)||e.pushToMain({index:t,key:_.lower_wick,value:G}),H(Y)||e.pushToMain({index:t,key:_.range,value:Y}),e.pushToMain({index:t,key:y,value:V})},rsi:(e,t,i,{target:s,lag:o,retLogs:n})=>{const{verticalOhlcv:r,instances:a}=e,l="close"===s?"":`_${s}`,c=n?`ret_log_rsi_${i}${l}`:`rsi_${i}${l}`,h=n?`ret_log_rsi_sma_${i}${l}`:`rsi_sma_${i}${l}`;if(0===t){if(u({[s]:!0},r,t,"rsi"),!r.hasOwnProperty(s))throw new Error(`Target property ${s} not found in verticalOhlcv for rsi.`);Object.assign(a,{[c]:new y(i),[h]:new f(i)}),I(e,[{key:c},{key:h}],{lag:o})}const p=r[s][t];a[c].update(p);const m=a[c].isStable?a[c].getResult():NaN,d=Number.isNaN(m)?NaN:n?O(m,50):m;e.pushToMain({index:t,key:c,value:d}),Number.isNaN(m)||a[h].update(m);const g=a[h].isStable?a[h].getResult():NaN,v=Number.isNaN(g)?NaN:n?O(g,50):g;e.pushToMain({index:t,key:h,value:v})},mfi:(e,t,i,{lag:s,retLogs:o})=>{const{verticalOhlcv:n,instances:r}=e,a=`${o?"ret_log_":""}mfi_${i}`;0===t&&(u({high:!0,low:!0,close:!0,volume:!0},n,t,"mfi"),I(e,[{key:a}],{lag:s}),r[a]={flows:new Float64Array(i),next:0,count:0,previousTypical:NaN});const l=r[a],c=(n.high[t]+n.low[t]+n.close[t])/3,h=c-l.previousTypical;if(l.previousTypical=c,0===t)return;const p=c*n.volume[t];if(l.flows[l.next]=Number.isFinite(h)&&Number.isFinite(p)&&p>=0?Math.sign(h)*p:NaN,l.next=(l.next+1)%i,l.count<i&&l.count++,l.count<i)return;let m=0,d=0,g=l.next;for(let e=0;e<i;e++){const e=l.flows[g];if(Number.isNaN(e))return;e>0?m+=e:e<0&&(d-=e),++g===i&&(g=0)}if(!Number.isFinite(m)||!Number.isFinite(d))return;const f=0===m&&0===d?NaN:100-100/(1+m/d);e.pushToMain({index:t,key:a,value:Number.isNaN(f)?NaN:o?O(f,50):f})},cmf:(e,t,i,s={})=>{const{verticalOhlcv:o,instances:n}=e,{lag:r=0}=s,a=`cmf_${i}`;if(0===t){const l=Object.keys(s).find(e=>"lag"!==e);if(l)throw new Error(`Unsupported option "${l}" in "cmf"; only "lag" is available.`);u({high:!0,low:!0,close:!0,volume:!0},o,t,"cmf"),I(e,[{key:a}],{lag:r}),n[a]={moneyFlowVolumes:new Float64Array(i),volumes:new Float64Array(i),next:0,count:0}}const l=n[a],c=o.high[t],h=o.low[t],p=o.close[t],m=o.volume[t],d=c-h;let g=NaN,f=NaN;if(Number.isFinite(c)&&Number.isFinite(h)&&Number.isFinite(p)&&Number.isFinite(m)&&m>=0&&c>=h&&p>=h&&p<=c&&Number.isFinite(d)){const e=0===d?0:(p-h-(c-p))/d,t=e*m;Number.isFinite(e)&&Number.isFinite(t)&&(g=t,f=m)}if(l.moneyFlowVolumes[l.next]=g,l.volumes[l.next]=f,l.next=(l.next+1)%i,l.count<i&&l.count++,l.count<i)return;let v=0,y=0,w=l.next;for(let e=0;e<i;e++){const e=l.moneyFlowVolumes[w],t=l.volumes[w];if(!Number.isFinite(e)||!Number.isFinite(t))return;v+=e,y+=t,++w===i&&(w=0)}if(!Number.isFinite(v)||!Number.isFinite(y)||0===y)return;const b=v/y;Number.isFinite(b)&&e.pushToMain({index:t,key:a,value:b})},stochastic:(e,t,i,s,o,{lag:n,retLogs:r})=>{const{verticalOhlcv:a,instances:l,useFullNames:c}=e,h=14!==i||3!==s||3!==o||c?`_${i}_${s}_${o}`:"",p=r?`ret_log_stochastic_d${h}`:`stochastic_d${h}`,m=r?`ret_log_stochastic_k${h}`:`stochastic_k${h}`,d=h;0===t&&(u({high:!0,low:!0,close:!0},a,t,"stochastic"),Object.assign(l,{[d]:new k(i,s,o)}),I(e,[{key:p},{key:m}],{lag:n}));const g=a.close[t],f=a.low[t],v=a.high[t];l[d].update({close:g,low:f,high:v});const y=l[d].isStable?l[d].getResult():null,w=y?r?O(y.stochK,50):y.stochK:NaN,b=y?r?O(y.stochD,50):y.stochD:NaN;e.pushToMain({index:t,key:m,value:w}),e.pushToMain({index:t,key:p,value:b})},atr:(e,t,i,{lag:s,retLogs:o})=>{const{verticalOhlcv:n,instances:r}=e,a=o?`ret_log_atr_${i}`:`atr_${i}`;if(0===t){const{instances:n,verticalOhlcv:r}=e;u({high:!0,low:!0,close:!0},r,t,"atr"),n[a]=new b(i,v),I(e,[{key:a,priceBased:!o}],{lag:s})}const l={high:n.high[t],low:n.low[t],close:n.close[t]},c=r[a];c.update(l);const h=c.isStable?c.getResult():NaN;e.pushToMain({index:t,key:a,value:Number.isNaN(h)?NaN:o?O(h,l.close):h})},adx:(e,t,i,{lag:s,retLogs:o})=>{const{verticalOhlcv:n,instances:r,useFullNames:a}=e,l=o?`ret_log_adx_${i}`:`adx_${i}`,c=`adx_${i}`;if(0===t){if(u({high:!0,low:!0,close:!0},n,t,"adx"),!n.hasOwnProperty("high"))throw new Error("Property high not found in verticalOhlcv for adx.");if(!n.hasOwnProperty("low"))throw new Error("Property low not found in verticalOhlcv for adx.");if(!n.hasOwnProperty("close"))throw new Error("Property close not found in verticalOhlcv for adx.");Object.assign(r,{[c]:new _(i)}),I(e,[{key:l}],{lag:s})}const h=n.high[t],p=n.low[t],m=n.close[t];r[c].update({high:h,low:p,close:m});const d=r[c].isStable?r[c].getResult():NaN,g=Number.isNaN(d)?NaN:o?O(d,20):d;e.pushToMain({index:t,key:l,value:g})},ema:j,sma:j,macd:(e,t,i,s,o,{target:n,lag:r,precomputed:a})=>{const{verticalOhlcv:l,instances:c,useFullNames:h}=e,{instanceKey:p}=a;if(0===t){u({[n]:!0},l,t,"macd");const{inputParams:a}=e;if(!l.hasOwnProperty(n))throw new Error(`Target property ${n} not found in verticalOhlcv for macd.`);let m=0;for(const e of a)"macd"===e.key&&m++;const d=m>1||h,f=`${i}_${s}_${o}`,v=e=>n===V?d?`macd_${e}_${f}`:`macd_${e}`:d?`macd_${e}_${n}_${f}`:`macd_${e}_${n}`,y=v("diff"),w=v("dea"),b=v("histogram");c.hasOwnProperty("macd")||(c.macd={numberOfIndicators:m,settings:{}}),c.macd.settings[p]=new x(new g(i),new g(s),new g(o)),I(e,[y,w,b].map(e=>({key:e,priceBased:!0})),{lag:r})}const{numberOfIndicators:m,settings:d}=c.macd,f=m>1||h,v=`${i}_${s}_${o}`,y=e=>n===V?f?`macd_${e}_${v}`:`macd_${e}`:f?`macd_${e}_${n}_${v}`:`macd_${e}_${n}`,w=y("diff"),b=y("dea"),$=y("histogram"),_=d[p],N=l[n][t];_.update(N);const k=_.isStable?_.getResult():null;e.pushToMain({index:t,key:w,value:k?k.macd:NaN}),e.pushToMain({index:t,key:b,value:k?k.signal:NaN}),e.pushToMain({index:t,key:$,value:k?k.histogram:NaN})},volumeDelta:(e,t,{lag:i=0})=>{const{verticalOhlcv:s,instances:o}=e,n="volume_delta";0===t&&(u({open:!0,close:!0,volume:!0},s,t,"volumeDelta"),o[n]||(o[n]={isBuyVolume:!0,cross:0}),I(e,[`${n}_high`,`${n}_low`,`${n}_close`,`${n}_cross`].map(e=>({key:e})),{lag:i}));const r=o[n],{hasInvalidInputValue:a}=r,l=s.volume[t];if(0===l)return;const c=s.open[t],h=s.close[t],p=t>0?s.close[t-1]:NaN;let m=r.isBuyVolume;h>c?m=!0:h<c?m=!1:h>p?m=!0:h<p&&(m=!1),r.isBuyVolume=m,t<1?r.cross=m?1:-1:m?r.cross>0?r.cross=r.cross+1:r.cross=1:r.cross>0?r.cross=-1:r.cross=r.cross-1;const d=m?l:-l,g=d,f=Math.max(d,0),v=Math.min(d,0);e.pushToMain({index:t,key:`${n}_high`,value:f}),e.pushToMain({index:t,key:`${n}_low`,value:v}),e.pushToMain({index:t,key:`${n}_close`,value:g}),e.pushToMain({index:t,key:`${n}_cross`,value:r.cross})},relativeVolume:(e,t,i,{lag:s,retLogs:o=!1})=>{const n=`${o?"ret_log_":""}relative_volume_${i}`,{instances:r,verticalOhlcv:a}=e;0===t&&(u({volume:!0},a,t,"relativeVolume"),r[n]={instance:new f(i),prevRelativeVolumeSma:NaN},I(e,[{key:n}],{lag:s}));const l=a.volume[t];if(0===l)return;const c=r[n].instance;c.update(l);const h=c.isStable?c.getResult():NaN,p=r[n].prevRelativeVolumeSma;if(r[n].prevRelativeVolumeSma=h,Number.isNaN(h)||Number.isNaN(p))return;const m=l/p,d=o?l>0&&p>0&&m>0&&Number.isFinite(m)?O(m,1):NaN:m;e.pushToMain({index:t,key:n,value:d})},donchianChannels:(e,t,i,s,o)=>{const{verticalOhlcv:n,instances:r,len:a,inputParams:l,useFullNames:c}=e,{lag:h=0,retLogs:p=!1}=o,m=`${i}_${s}`,d=`${p?"ret_log_":""}${m}`,g=(p?"ret_log_":"")+"donchian_channel";if(0===t){u({high:!0,low:!0},n,t,"donchianChannels"),p&&u({close:!0},n,t,"donchianChannels");const i=l.filter(e=>"donchianChannels"===e.key).length,s=i>1||c,o=(p?["width","position"]:["upper","basis","lower"]).map(e=>s?`${g}_${e}_${m}`:`${g}_${e}`);r.donchian_channel||(r.donchian_channel={numberOfIndicators:i,settings:{}}),r.donchian_channel.numberOfIndicators=i,r.donchian_channel.settings[d]={maxDeque:{indices:[],head:0,length:0},minDeque:{indices:[],head:0,length:0}},I(e,o.map(e=>({key:e,priceBased:!p})),{lag:h})}const{numberOfIndicators:f,settings:v}=r.donchian_channel,y=f>1||c,w=e=>y?`${g}_${e}_${m}`:`${g}_${e}`,{maxDeque:b,minDeque:$}=v[d],_=t-s,N=_-i+1;if(_<0||_>=a)return;const{high:x,low:k}=n,T=(e,t,s)=>{const{indices:o}=e;for(;e.length&&o[e.head]<N;)e.head=(e.head+1)%i,e.length--;for(;e.length&&s(t[o[(e.head+e.length-1)%i]],t[_]);)e.length--;o[(e.head+e.length)%i]=_,e.length++};if(T(b,x,(e,t)=>e<=t),T($,k,(e,t)=>e>=t),N<0)return;const M=b.length&&$.length,S=M?x[b.indices[b.head]]:NaN,P=M?k[$.indices[$.head]]:NaN;if(p){let i=NaN,s=NaN;const o=S/P;if(P>0&&S>=P&&Number.isFinite(S)&&Number.isFinite(o)){const e=O(o,1);i=e/2;const r=n.close[t],a=r/P;if(e>0&&r>0&&a>0&&Number.isFinite(a)){const t=2*O(a,1)/e-1;Number.isFinite(t)&&(s=t)}}return e.pushToMain({index:t,key:w("width"),value:i}),void e.pushToMain({index:t,key:w("position"),value:s})}const F=M?(S+P)/2:NaN;e.pushToMain({index:t,key:w("upper"),value:S}),e.pushToMain({index:t,key:w("basis"),value:F}),e.pushToMain({index:t,key:w("lower"),value:P})},bollingerBands:(e,t,i,s,{lag:o,retLogs:n=!1}={})=>{const{verticalOhlcv:r,instances:a,useFullNames:l}=e,c=`${i}_${s}`,h=`${n?"ret_log_":""}${c}`,p=(n?"ret_log_":"")+"bollinger_bands",m="close";if(0===t){const{inputParams:r,verticalOhlcv:d,priceBased:g}=e;if(u({[m]:!0},d,t,"bollingerBands"),!(m in d))throw new Error(`bollingerBands could not find target "${m}"`);let f=0;for(const e of r)"bollingerBands"===e.key&&f++;a.bollinger_bands||(a.bollinger_bands={numberOfIndicators:f,settings:{}}),a.bollinger_bands.settings[h]=new N(i,s);const v=f>1||l?`_${c}`:"";I(e,(n?[`${p}_width${v}`,`${p}_position${v}`]:[`${p}_upper${v}`,`${p}_middle${v}`,`${p}_lower${v}`]).map(e=>({key:e,priceBased:!n&&g.has(m)})),{lag:o})}const{numberOfIndicators:d}=a.bollinger_bands,g=d>1||l?`_${c}`:"",f=a.bollinger_bands.settings[h],v=r[m][t];f.update(v);const y=f.isStable?f.getResult():null,w=y?.upper??NaN,b=y?.middle??NaN,$=y?.lower??NaN;if(n){let i=NaN,s=NaN;const o=w/$;if($>0&&w>=$&&Number.isFinite(w)&&Number.isFinite(o)){const e=O(o,1);i=e/2;const t=v/$;if(e>0&&v>0&&t>0&&Number.isFinite(t)){const i=2*O(t,1)/e-1;Number.isFinite(i)&&(s=i)}}return e.pushToMain({index:t,key:`${p}_width${g}`,value:i}),void e.pushToMain({index:t,key:`${p}_position${g}`,value:s})}e.pushToMain({index:t,key:`${p}_upper${g}`,value:w}),e.pushToMain({index:t,key:`${p}_middle${g}`,value:b}),e.pushToMain({index:t,key:`${p}_lower${g}`,value:$})},volumeOscillator:(e,t,i,s,{lag:o,retLogs:n})=>{const{verticalOhlcv:r,instances:a}=e,l=n?`ret_log_volume_oscillator_${i}_${s}`:`volume_oscillator_${i}_${s}`;0===t&&(u({volume:!0},r,t,"volumeOscillator"),Object.assign(a,{[l]:{fastEMA:new g(i),slowEMA:new g(s)}}),I(e,[{key:l}],{lag:o}));const{fastEMA:c,slowEMA:h}=a[l],p=r.volume[t];if(0===p)return;c.update(p),h.update(p);const m=c.isStable?c.getResult():NaN,d=h.isStable?h.getResult():NaN;let f=NaN;Number.isNaN(m)||Number.isNaN(d)||(f=n?O(m,d):100*(m-d)/d,e.pushToMain({index:t,key:l,value:f}))},crossPairs:(e,t,i,{oneHot:s,limit:o})=>{const{verticalOhlcv:n,verticalOhlcvTempCols:r,instances:a,len:l,precision:c,precisionMultiplier:h,priceBased:u}=e;for(const{fast:p,slow:m}of i){const i=`${p}_x_${m}`;if(0===t){if("number"==typeof m){const e=m.toString();r.add(e);const t=c&&("price"===p||u.has(p)),i=t?M(e,h):m,s=m>=-125&&m<=125&&!1===t?"Int8Array":"Float64Array";n[e]=L(s,l,i)}a.hasOwnProperty("crossPairs")||(a.crossPairs={}),a.crossPairs[i]={run:new G,min:1/0,max:-1/0},I(e,[{key:i,type:null!==o&&o<=125?"Int8Array":"Float64Array",fill:0},{key:`one_hot_${i}`,type:"Array",enabled:s}])}else if(t+1===l){if("price"!==p&&!n.hasOwnProperty(p))throw new Error(`crossPairs invalid param: fast "${p}" not found in "verticalOhlcv": ${JSON.stringify(Object.keys(n))}`);if(!n.hasOwnProperty(m))throw new Error(`crossPairs invalid param: slow "${m}" not found in "verticalOhlcv": ${JSON.stringify(Object.keys(n))}`)}if("price"!==p&&!n.hasOwnProperty(p))return;if(!n.hasOwnProperty(m))return;const{run:d}=a.crossPairs[i];if("price"===p){const e=n.close[t],i=n[m][t];d.update(t,{fast:e,slow:i,high:n.high[t],low:n.low[t]})}else{const e=n[p][t],i=n[m][t];d.update(t,{fast:e,slow:i})}const g=d.getResult(),f=null!==o?Math.min(Math.max(g,-o),o):g;if(e.pushToMain({index:t,key:i,value:f}),s){const s=f+o,n=2*o+1;e.pushToMain({index:t,key:`one_hot_${i}`,value:U(s,n)})}}},lag:(e,t,i,s)=>{const{verticalOhlcv:o,priceBased:n,instances:r}=e;if(0===t){const t=new Map;for(const r of i){if(!o.hasOwnProperty(r))throw new Error(`Lag processing invoked by col "${r}" was not found in "verticalOhlcv".`);const i=n.has(r),a=Array.isArray(o[r])?"Array":"Float64Array",l=[],c=[];for(let e=1;e<=s;e++){const t=`${r}_lag_${e}`;l.push({key:t,type:a,priceBased:i,includeInLag:!1}),c.push(t)}I(e,l),t.set(r,c)}r[K]||(r[K]=new WeakMap),r[K].set(i,t)}const a=r[K]?.get(i);for(const n of i){const i=a?.get(n),r=o[n],l=Array.isArray(r)?null:NaN;for(let o=1;o<=s;o++){const s=i?.[o-1]??`${n}_lag_${o}`,a=t-o,c=a<0||null==r[a]?l:r[a];e.pushToMain({index:t,key:s,value:c})}}}},W=({main:e,skipNull:t=!1,startIndex:i=0,dateFormat:s})=>{const{verticalOhlcv:o,invalidValueIndex:n,len:r,verticalOhlcvKeyNames:a,verticalOhlcvTempCols:l,priceBased:c,precision:h,precisionMultiplier:u}=e;if(0===a.length)return[];const p=h&&"number"==typeof u?T(u):void 0,m=t&&n>=0?n+1:0,d=Math.max(m,i),g=r-d,f=Array.from({length:g},()=>({}));for(const[e,t]of Object.entries(o))if(!l.has(e))if("date"===e){const i=C[s];for(let s=d;s<r;s++)f[s-d][e]=i(t[s])}else if(h&&c.has(e)){const i=P;for(let s=d;s<r;s++){const o=t[s];f[s-d][e]=null==o||Number.isNaN(o)?o:i(o,u,p)}}else for(let i=d;i<r;i++)f[i-d][e]=t[i];return f},Q=(e,t=new Set)=>{if(null===e||"string"==typeof e||"boolean"==typeof e)return e;if("number"==typeof e&&Number.isFinite(e))return e;if("object"!=typeof e||null===e)throw new TypeError("Configuration values must be JSON-safe: no undefined, non-finite numbers, or functions.");if(t.has(e))throw new TypeError("Configuration must not contain circular references.");const i=Object.getPrototypeOf(e);if(!Array.isArray(e)&&i!==Object.prototype&&null!==i)throw new TypeError("Configuration must contain only plain objects and arrays.");if(Object.getOwnPropertySymbols(e).length)throw new TypeError("Configuration must not contain symbol keys.");t.add(e);const s=Array.isArray(e)?Array.from(e,e=>Q(e,t)):Object.fromEntries(Object.entries(e).map(([e,i])=>[e,Q(i,t)]));return t.delete(e),s},X=e=>{if(null!==e&&"object"==typeof e){for(const t of Object.values(e))X(t);Object.freeze(e)}return e};class ee{constructor({input:e,ticker:t=null,chunkProcess:i=2e3,config:o={}}){if(null===o||Array.isArray(o)||"object"!=typeof o)throw new TypeError('Constructor "config" must be a plain object.');const r=Q(o),u=["schemaVersion","precision","useFullNames","inputParams","dateFormat","skipNull","timeZone"];for(const e of Object.keys(r))if(!u.includes(e))throw new Error(`Unknown configuration option "${e}".`);const{schemaVersion:p=1,precision:m=!1,useFullNames:d=!1,inputParams:g=null,dateFormat:f="milliseconds",skipNull:v=!0,timeZone:y=Intl.DateTimeFormat().resolvedOptions().timeZone}=r;if(1!==p)throw new Error(`Unsupported configuration schemaVersion: ${p}.`);l(v,"config.skipNull","constructor"),h(f,"config.dateFormat","constructor"),a(Object.keys(C),f,"config.dateFormat","constructor"),h(y,"config.timeZone","constructor");const w=new Intl.DateTimeFormat("en-US",{timeZone:y}).resolvedOptions().timeZone;if(this.config=Object.freeze({schemaVersion:p,precision:m,useFullNames:d,dateFormat:f,skipNull:v,timeZone:w}),this.timeZone=w,n(e,"input",null!==t?`contructor ${t}`:"constuctor"),0===e.length)throw Error("input OHLCV must not be empty: "+t);c(i,{min:100,max:5e4,allowDecimals:!1},"chunkProcess","constructor"),l(m,"precision","contructor"),l(d,"config.useFullNames","constructor"),this.chunkProcess=i,this.input=[...e],this.len=this.input.length,this.firstRow=this.input[0],this.precision=m,this.useFullNames=d;const b=["open","high","low","close","mid_price"];this.initialPriceBased=new Set(b),this.priceBased=new Set(b),this.precisionMultiplier=(e=>{const{precision:t,firstRow:i,initialPriceBased:s}=e;if(!1===t)return 1;let o=1;for(const[e,t]of Object.entries(i)){if(!s.has(e))continue;if("string"!=typeof t||!/^\d+(\.\d+)?$/.test(t))throw new Error(`If "precision" is set to true all the "open", "high", "low" and "close" values must be numeric strings like "123.45" with no commas or currency symbols. Property "${e}" had the value "${t}" type ${typeof t}.`);const[i,n=""]=t.split("."),r=Number(i);let a=4;if(0===Math.abs(r)){const e=n.length,t=Math.max(4,e),i=n.search(/[1-9]/);if(-1===i)a=t;else{const e=i+1+5;a=Math.max(t,e)}}const l=10**a;l>o&&(o=l)}return o})(this);const{inputTypes:$,arrayTypes:_}=(e=>{const{firstRow:t,precision:i,initialPriceBased:s}=e,o={},n={},r=new Map;for(const[e,a]of Object.entries(t))if("date"===e)o[e]=D(a),n[e]="Array";else if("volume"===e)o[e]=F(a,!0),n[e]="Float64Array";else if(s.has(e))o[e]=F(a,!0,i),n[e]="Float64Array",r.set(e,o[e]);else{const t=F(a,!1,i);o[e]=t,n[e]="number"===t?"Float64Array":"Array"}if(new Set(r.values()).size>1){const e=[...r.entries()].map(([e,t])=>`${e}: "${t}"`).join(", ");throw new Error(`Inconsistent types among price-based columns — ${e}. All initialPriceBased columns must share the same numeric type.`)}return n.hasOwnProperty("open")&&n.hasOwnProperty("close")&&(n.mid_price=n.open,o.mid_price=o.open),{inputTypes:o,arrayTypes:n}})(this);if(this.inputTypes=$,this.arrayTypes=_,!this.firstRow.hasOwnProperty("close"))throw Error(`input OHLCV array objects require at least "close" property: ${t}`);return this.dateType=this.inputTypes.date?this.inputTypes.date:null,this.isComputed=!1,this.isComputing=!1,this.executionParams=[],this.instances={},this.verticalOhlcv={},this.verticalOhlcvKeyNames=[],this.verticalOhlcvTempCols=new Set,this.utilities={},this.invalidValueIndex=-1,this.scaledGroups={},this.isAlreadyComputed=new Set,this.pushToMain=({index:e,key:t,value:i})=>{this.verticalOhlcv[t][e]=i},null!==g?(s(g,this.len),this.inputParams=X(Q(g)),this.compute()):this.inputParams=Object.freeze([]),this}exportConfig(){return{...this.config,inputParams:Q(this.inputParams)}}_registerIndicator(e){return o(this),this.inputParams=Object.freeze([...this.inputParams,X(Q(e))]),this}getData(e={}){this.compute();const{skipNull:t=this.config.skipNull,dateFormat:i=this.config.dateFormat}=e;return a(Object.keys(C),i,"dateFormat","getData"),r(e,"options","getData"),W({main:this,skipNull:t,startIndex:0,dateFormat:i})}getLastValues(e={}){this.compute();const{dateFormat:t=this.config.dateFormat}=e;return a(Object.keys(C),t,"dateFormat","getData"),W({skipNull:!1,main:this,startIndex:this.len-1,dateFormat:t})[0]}compute(){if(this.isComputed)return this;if(this.isComputing)throw new Error("Computation is already in progress.");if(this.executionParams=Q(this.inputParams).sort((e,t)=>(e.order??0)-(t.order??0)),this.isComputed=!1,this.len>0){this.isComputing=!0;try{((e,t)=>{const{len:o,arrayTypes:n,verticalOhlcv:r,verticalOhlcvKeyNames:a,inputTypes:l,chunkProcess:c,precisionMultiplier:h,executionParams:u}=t;s(u,o);for(const{key:e}of u)if(!Object.prototype.hasOwnProperty.call(J,e))throw new Error(`Unknown indicator "${e}" in configuration.`);for(const e of Object.keys(l))r[e]=L(n[e],o);const p=Object.entries(l).map(([e,t])=>{const i=S.hasOwnProperty(t);return{key:e,formatter:i?S[t]:A.hasOwnProperty(t)?A[t]:null,numeric:i}}),m="number"==typeof h?T(h):void 0;let d=null;for(let s=0;s<o;s+=c){const n=Math.min(s+c,o);for(let o=s;o<n;o++){const s=e[o];for(const{key:e,formatter:i,numeric:n}of p){const r=s[e];if(void 0===r)continue;const a=null===i?r:n?i(r,h,m):i(r);t.pushToMain({index:o,key:e,value:a})}const n=(r.open[o]+r.close[o])/2;t.pushToMain({index:o,key:"mid_price",value:n});for(const{key:e,params:i}of u)J[e](t,o,...i);e[o]=null,null===d&&(d=Object.values(r)),i(d,o)||(t.invalidValueIndex=o)}}a.push(...Object.keys(r))})(this.input,this)}finally{this.isComputing=!1}this.isComputed=!0,this.input=[],this.instances={},this.firstRow=[]}return this}crossPairs(e=[],t={}){const i="crossPairs";o(this),n(e,"arr",i),r(t,"options",i);const{limit:s=null,oneHot:a=!1}=t;null!==s&&c(s,{min:2,max:this.len},"options.limit",i),l(a,"options.oneHot",i);const h=[];for(const{fast:t="",slow:i=""}of e){if(""===t||""===i)throw new Error(`Invalid crossPairs[${t}_${i}]: Object property “fast” must be a non-null column name and “slow” must be a non-null column name or integer.`);h.push(t.toString(),i.toString())}if(this.isAlreadyComputed.has(i))throw new Error(`You can only call the "${i}" method once.`);return this.isAlreadyComputed.add(i),this._registerIndicator({key:i,params:[e,{limit:s,oneHot:a}]}),this}lag(e=["close"],t=1){const i="lag";o(this),n(e,"colKeys",i);const s=e.find(e=>"string"!=typeof e||""===e);if(void 0!==s)throw new Error(`Invalid item "${s}" (column name) in "colKeys" array param of "${i}()".`);return c(t,{min:1,max:this.len,allowDecimals:!1},"lookback",i),this._registerIndicator({key:i,params:[e,t]}),this}relativeVolume(e=10,t={}){const i="relativeVolume";if(!this.inputTypes.hasOwnProperty("volume"))throw new Error('If "relativeVolume" is called the input ohlcv must contain valid volume properties.');o(this),c(e,{min:1,max:this.len,allowDecimals:!1},"size",i),r(t,"options",i);const{lag:s=0,retLogs:n=!1}=t;return c(s,{min:0,max:this.len,allowDecimals:!1},"options.lag",i),l(n,"options.retLogs",i),this._registerIndicator({key:i,order:0,params:[e,{lag:s,retLogs:n}]}),this}volumeDelta(e={}){const t="volumeDelta";if(!this.inputTypes.hasOwnProperty("volume"))throw new Error('If "volumeDelta" is called the input ohlcv must contain valid volume properties.');o(this),r(e,"options",t);const{lag:i=0}=e;return c(i,{min:0,max:this.len,allowDecimals:!1},"options.lag",t),this._registerIndicator({key:t,order:0,params:[{lag:i}]}),this}atr(e=14,t={}){const i="atr";o(this),c(e,{min:1,max:this.len,allowDecimals:!1},"size",i),r(t,"options",i);const{lag:s=0,retLogs:n=!1}=t;return c(s,{min:0,max:this.len,allowDecimals:!1},"options.lag",i),l(n,"options.retLogs",i),this._registerIndicator({key:i,order:0,params:[e,{lag:s,retLogs:n}]}),this}adx(e=14,t={}){const i="adx";o(this),c(e,{min:1,max:this.len,allowDecimals:!1},"size",i),r(t,"options",i);const{lag:s=0,retLogs:n=!1}=t;return c(s,{min:0,max:this.len,allowDecimals:!1},"options.lag",i),l(n,"options.retLogs",i),this._registerIndicator({key:i,order:0,params:[e,{lag:s,retLogs:n}]}),this}ema(e=5,t={}){const i="ema";o(this),c(e,{min:1,max:this.len,allowDecimals:!1},"size",i),r(t,"options",i);const{target:s="close",lag:n=0,retLogs:a=!1}=t;return h(s,"options.target",i),c(n,{min:0,max:this.len,allowDecimals:!1},"options.lag",i),l(a,"options.retLogs",i),this._registerIndicator({key:i,params:[i,e,{target:s,lag:n,retLogs:a}]}),this}sma(e=5,t={}){const i="sma";o(this),c(e,{min:1,max:this.len,allowDecimals:!1},"size",i),r(t,"options",i);const{target:s="close",lag:n=0,retLogs:a=!1}=t;return h(s,"options.target",i),c(n,{min:0,max:this.len,allowDecimals:!1},"options.lag",i),l(a,"options.retLogs",i),this._registerIndicator({key:i,params:[i,e,{target:s,lag:n,retLogs:a}]}),this}heikenAshi(e=null,t=null,i={}){const s="heikenAshi";o(this);const n=null===e&&null===t;!1===n&&(c(e,{min:1,max:this.len,allowDecimals:!1},"smoothLength",s),c(t,{min:1,max:this.len,allowDecimals:!1},"afterSmoothLength",s)),r(i,"options",s);const{lag:a=0,retLogs:h=!1}=i;return c(a,{min:0,max:this.len,allowDecimals:!1},"options.lag",s),l(h,"option.retLogs",s),this._registerIndicator({key:s,order:0,params:[e,t,{lag:a,noSmoothing:n,retLogs:h}]}),this}stochastic(e=14,t=3,i=3,s={}){const n="stochastic";o(this);const{len:a}=this;c(e,{min:1,max:a,allowDecimals:!1},"kPeriod",n),c(t,{min:1,max:a,allowDecimals:!1},"kSlowingPeriod",n),c(i,{min:1,max:a,allowDecimals:!1},"dPeriod",n),r(s,"options",n);const{lag:h=0,retLogs:u}=s;return c(h,{min:0,max:a,allowDecimals:!1},"options.lag",n),l(u,"retLogs",n),this._registerIndicator({key:n,params:[e,t,i,{lag:h,retLogs:u}]}),this}macd(e=12,t=26,i=9,s={}){const n="macd";o(this),c(e,{min:1,max:this.len,allowDecimals:!1},"fast",n),c(t,{min:1,max:this.len,allowDecimals:!1},"slow",n),c(i,{min:1,max:this.len,allowDecimals:!1},"signal",n),r(s,"options",n);const{target:a="close",lag:l=0}=s;h(a,"options.target",n),c(l,{min:0,max:this.len,allowDecimals:!1},"options.lag",n);const u={instanceKey:`${e}_${t}_${i}${"close"===a?"":`_${a}`}`};return this._registerIndicator({key:n,params:[e,t,i,{target:a,lag:l,precomputed:u}]}),this}bollingerBands(e=20,t=2,i={}){const s="bollingerBands";o(this),c(e,{min:1,max:this.len,allowDecimals:!1},"size",s),c(t,{min:.01,max:50,allowDecimals:!0},"stdDev",s),r(i,"options",s);const{lag:n=0,retLogs:a=!1}=i;return c(n,{min:0,max:this.len,allowDecimals:!1},"options.lag",s),l(a,"options.retLogs",s),this._registerIndicator({key:s,params:[e,t,{lag:n,retLogs:a}]}),this}rsi(e=14,t={}){const i="rsi";o(this),c(e,{min:1,max:this.len,allowDecimals:!1},"size",i),r(t,"options",i);const{target:s="close",lag:n=0,retLogs:a=!1}=t;return h(s,"options.target",i),c(n,{min:0,max:this.len,allowDecimals:!1},"options.lag",i),l(a,"retLogs",i),this._registerIndicator({key:i,params:[e,{target:s,lag:n,retLogs:a}]}),this}mfi(e=14,t={}){const i="mfi";o(this),c(e,{min:1,max:this.len,allowDecimals:!1},"size",i),r(t,"options",i);const{lag:s=0,retLogs:n=!1}=t;return c(s,{min:0,max:this.len,allowDecimals:!1},"options.lag",i),l(n,"options.retLogs",i),this._registerIndicator({key:i,params:[e,{lag:s,retLogs:n}]}),this}cmf(e=20,t={}){const i="cmf";if(!this.inputTypes.hasOwnProperty("volume"))throw new Error('If "cmf" is called the input ohlcv must contain valid volume properties.');o(this),c(e,{min:1,max:this.len,allowDecimals:!1},"size",i),r(t,"options",i);const s=Object.keys(t).find(e=>"lag"!==e);if(s)throw new Error(`Unsupported option "${s}" in "cmf"; only "lag" is available.`);const{lag:n=0}=t;return c(n,{min:0,max:this.len,allowDecimals:!1},"options.lag",i),this._registerIndicator({key:i,params:[e,{lag:n}]}),this}donchianChannels(e=20,t=0,i={}){const s="donchianChannels";o(this),c(e,{min:1,max:this.len,allowDecimals:!1},"size",s),c(t,{min:0,max:this.len,allowDecimals:!1},"offset",s),r(i,"options",s);const{lag:n=0,retLogs:a=!1}=i;return c(n,{min:0,max:this.len,allowDecimals:!1},"options.lag",s),l(a,"options.retLogs",s),this._registerIndicator({key:s,order:0,params:[e,t,{lag:n,retLogs:a}]}),this}volumeOscillator(e=5,t=10,i={}){const s="volumeOscillator";if(!this.inputTypes.hasOwnProperty("volume"))throw new Error('If "volumeOscillator" is called the input ohlcv must contain valid volume properties.');o(this),c(e,{min:1,max:this.len,allowDecimals:!1},"fastsize",s),c(t,{min:e,max:this.len,allowDecimals:!1},"slowsize",s),r(i,"options",s);const{lag:n=0,retLogs:a=!1}=i;return c(n,{min:0,max:this.len,allowDecimals:!1},"options.lag",s),l(a,"retLogs",s),this._registerIndicator({key:s,order:0,params:[e,t,{lag:n,retLogs:a}]}),this}dateTime(e={}){const t="dateTime";o(this),r(e,"options",t);const{lag:i=0,oneHot:s=!1}=e;c(i,{min:0,max:this.len,allowDecimals:!1},"options.lag",t),l(s,"options.oneHot",t);const n=s?"one_hot_":"",a={[`${n}month`]:12,[`${n}day_of_the_month`]:31,[`${n}day_of_the_week`]:7,[`${n}hour`]:24,[`${n}minute`]:60},h={prefix:n,colKeySizes:a,colKeys:Object.keys(a)};return this._registerIndicator({key:t,order:0,params:[{lag:i,oneHot:s,precompute:h}]}),this}candleFeatures(e={}){let t="candleFeatures";o(this),r(e,"options",t);const{lag:i=0,colKeys:s=[],retLogs:a=!1}=e;return c(i,{min:0,max:this.len,allowDecimals:!1},"options.lag",t),n(s,"options.colKeys",t),l(a,"retLogs",t),this._registerIndicator({key:t,params:[{lag:i,colKeys:s,retLogs:a}]}),this}}})(),OHLCV_INDICATORS=t.default})();
|
|
1
|
+
var OHLCV_INDICATORS;(()=>{"use strict";const e={d:(t,s)=>{for(var i in s)e.o(s,i)&&!e.o(t,i)&&Object.defineProperty(t,i,{enumerable:!0,get:s[i]})},o:(e,t)=>Object.prototype.hasOwnProperty.call(e,t)};let t={};(()=>{e.d(t,{default:()=>ie});const s=(e,t)=>{if(0===e.length)return!1;for(let s=0;s<e.length;s++){const i=e[s][t];if(null==i||Number.isNaN(i))return!1}return!0},i=(e,t)=>{if(!Array.isArray(e))throw new Error('Property "inputParams" must be an "Array" or "Set".');for(const s of e){if(!s||"string"!=typeof s.key||!Array.isArray(s.params))throw new TypeError("Each inputParams entry must have an indicator key and a params array.");if(void 0!==s.order&&!Number.isFinite(s.order))throw new TypeError("Indicator order must be a finite number when provided.");const{params:e}=s;for(const s of e)if("number"==typeof s&&s>t)throw console.log(s,t),new Error("At least one of the params of the indicator is greater than the input OHLCV length. Make sure to have enough datapoints in the input OHLCV.")}},o=e=>{if(!0===e.isComputing)throw Error("You cannot add indicators while computation is in progress.");if(!0===e.isComputed)throw Error('ohlcv is already computed, you can not add new indicators after "compute", "getLastValues" or "getData" methods are called.')},r=(e,t,s)=>{if(!Array.isArray(e))throw new Error(`Param "${t}" must be an array in "${s}".`);return!0},n=(e,t,s)=>{if(e instanceof Object==0)throw new Error(`Param "${t}" must be an object in "${s}".`);return!0},a=(e,t,s,i)=>{if(r(e,"arrayOptions",`${i}.${s}.validateArrayOptions`),!e.includes(t.toString()))throw new Error(`Param "${s}" must be any of the following values [${e.join(", ")}] in "${i}".`);return!0},l=(e,t,s)=>{if("boolean"!=typeof e)throw new Error(`Param "${t}" must be an boolean in "${s}".`);return!0},c=(e,t,s,i)=>{n(t,"options",`${i}.${s}.validateNumber`);const{allowDecimals:o=!1,min:r,max:a}=t,l=o?"number":"integer";if("number"!=typeof e||!1===o&&!Number.isInteger(e))throw new Error(`Param "${s}" must be an ${l} in "${i}".`);if(void 0!==r&&"number"!=typeof r)throw new Error(`Param "min" must be a valid ${l} (if provided) in "${i}.${s}.validateNumber".`);if(void 0!==a&&"number"!=typeof a)throw new Error(`Param "max" must be a valid ${l} (if provided) in "${i}.${s}.validateNumber".`);if(void 0!==r&&void 0!==a&&r>=a)throw new Error(`Param "min" must be less than "max" in "${i}.${s}.validateNumber".`);if(void 0!==r&&e<r)throw new Error(`Param "${s}" must be an ${l} ≥ ${r} in "${i}".`);if(void 0!==a&&e>a)throw new Error(`Param "${s}" must be an ${l} ≤ ${a} in "${i}".`);return!0},h=(e,t,s)=>{if("string"!=typeof e||!e.length)throw new Error(`Invalid "${t}" property in "${s}". Only strings are accepted.`);return!0},u=(e,t,s,i)=>{if(0!==s)return!0;const o=[];for(const i of Object.keys(e)){const e=t[i]?.[s];("volume"===i?Number.isFinite(e)&&e>=0:Number.isFinite(e)&&e>0)||o.push(i)}if(o.length>0)throw new TypeError(`Invalid or missing input value(s) [${o.join(", ")}] at index ${s} in "${i}".`);return!0};class p extends Error{constructor(e="Not enough data"){super(e),this.name="NotEnoughDataError"}}class m{constructor(){this.result=void 0}get isStable(){return void 0!==this.result}getResult(){if(!this.isStable)throw new p;return this.result}}class d extends m{constructor(){super(),this.previousResult=void 0,this.highest=void 0,this.lowest=void 0,this.previousHighest=void 0,this.previousLowest=void 0}setResult(e,t=!1){return t&&(this.highest=this.previousHighest,this.lowest=this.previousLowest,this.result=this.previousResult),void 0===this.highest?this.highest=e:(this.previousHighest=this.highest,e>this.highest&&(this.highest=e)),void 0===this.lowest?this.lowest=e:(this.previousLowest=this.lowest,e<this.lowest&&(this.lowest=e)),this.previousResult=this.result,this.result=e,e}replace(e){return this.update(e,!0)}updates(e){return e.forEach(e=>this.update(e)),this.result}}class g extends d{constructor(e){super(),this.interval=e,this.pricesCounter=0,this.weightFactor=2/(e+1)}update(e,t=!1){t&&0!==this.pricesCounter||this.pricesCounter++;const s=t&&void 0!==this.previousResult?this.previousResult:void 0!==this.result?this.result:e;return this.setResult(e*this.weightFactor+s*(1-this.weightFactor),t)}get isStable(){return this.pricesCounter>=this.interval}}class f extends d{constructor(e){super(),this.interval=e,this.prices=new Float64Array(e),this.count=0,this.head=0}update(e,t=!1){"number"==typeof e||Array.isArray(this.prices)||(this.prices=Array.from(this.prices));const{interval:s,prices:i}=this;if(t&&this.count){let t=this.head+this.count-1;t>=s&&(t-=s),i[t]=e}else this.count<s?i[this.count++]=e:(i[this.head]=e,++this.head===s&&(this.head=0));if(this.count===s){let e=0;for(let t=this.head;t<s;t++)e+=i[t];for(let t=0;t<this.head;t++)e+=i[t];return this.setResult(e/s,t)}}}class v extends d{constructor(e){super(),this.interval=e,this.indicator=new f(e),this.smoothingFactor=1/e}update(e,t=!1){if(void 0===this.result){const s=this.indicator.update(e);if(void 0!==s)return this.indicator=void 0,this.setResult(s,t)}else{if(t&&void 0!==this.previousResult){const s=(e-this.previousResult)*this.smoothingFactor;return this.setResult(s+this.previousResult,t)}if(!t){const s=(e-this.result)*this.smoothingFactor;return this.setResult(s+this.result,t)}}}}class y extends d{constructor(e,t=v){super(),this.interval=e,this.avgGain=new t(e),this.avgLoss=new t(e),this.maxValue=100,this.priceCount=0,this.previousPrice=void 0,this.currentPrice=void 0}update(e,t=!1){if(t&&0!==this.priceCount||(this.previousPrice=this.currentPrice,this.priceCount<2&&this.priceCount++),this.currentPrice=e,this.priceCount<2)return;const s=this.previousPrice;if(e>s?(this.avgLoss.update(0,t),this.avgGain.update(e-s,t)):(this.avgLoss.update(s-e,t),this.avgGain.update(0,t)),this.avgGain.isStable){const e=this.avgLoss.getResult();if(0===e)return this.setResult(100,t);const s=this.avgGain.getResult()/e;return this.setResult(this.maxValue-this.maxValue/(s+1),t)}}}class w extends d{constructor(){super(),this.previousCandle=void 0,this.twoPreviousCandle=void 0}update(e,t=!1){const{high:s,low:i}=e,o=s-i;if(this.previousCandle&&t&&(this.previousCandle=this.twoPreviousCandle),this.previousCandle){const r=Math.abs(s-this.previousCandle.close),n=Math.abs(i-this.previousCandle.close);return this.twoPreviousCandle=this.previousCandle,this.previousCandle=e,this.setResult(Math.max(o,r,n),t)}return this.twoPreviousCandle=this.previousCandle,this.previousCandle=e,this.setResult(o,t)}}class b extends d{constructor(e,t=v){super(),this.interval=e,this.tr=new w,this.smoothing=new t(e)}update(e,t=!1){const s=this.tr.update(e,t);if(this.smoothing.update(s,t),this.smoothing.isStable)return this.setResult(this.smoothing.getResult(),t)}}class $ extends d{constructor(e,t=v){super(),this.interval=e,this.atr=new b(e,t),this.movesDown=new t(e),this.movesUp=new t(e),this.previousCandle=void 0,this.mdi=void 0,this.pdi=void 0}updateState(e,t=0,s=0){this.atr.update(e),this.movesUp.update(t),this.movesDown.update(s),this.previousCandle=e}update(e){if(!this.previousCandle)return void this.updateState(e);const t=e.high-this.previousCandle.high,s=this.previousCandle.low-e.low,i=t<0||t<s?0:t,o=s<0||s<t?0:s;if(this.updateState(e,i,o),this.movesUp.isStable){const e=this.atr.getResult();this.pdi=this.movesUp.getResult()/e,this.mdi=this.movesDown.getResult()/e;const t=Math.abs(this.pdi-this.mdi),s=this.pdi+this.mdi;return 0===s?this.setResult(0,!1):this.setResult(t/s*100,!1)}}}class N extends d{constructor(e,t=v){super(),this.interval=e,this.adx=new t(e),this.dx=new $(e,t)}get mdi(){return this.dx.mdi}get pdi(){return this.dx.pdi}update(e,t=!1){const s=this.dx.update(e);if(void 0!==s&&this.adx.update(s),this.adx.isStable)return this.setResult(this.adx.getResult(),t)}}class _ extends m{constructor(e,t=2){super(),this.interval=e,this.deviationMultiplier=t,this.prices=new Float64Array(e),this.count=0,this.head=0}update(e){if("number"==typeof e||Array.isArray(this.prices)||(this.prices=Array.from(this.prices)),this.count<this.interval)return void(this.prices[this.count++]=e);this.prices[this.head]=e,this.head=(this.head+1)%this.interval;let t=0,s=this.head;for(let e=0;e<this.count;e++)t+=this.prices[s],++s===this.interval&&(s=0);const i=this.count?t/this.count:0;let o=i;if(!o&&Array.isArray(this.prices)){t=0,s=this.head;for(let e=0;e<this.count;e++)t+=this.prices[s],++s===this.interval&&(s=0);o=this.count?t/this.count:0}let r=0;s=this.head;for(let e=0;e<this.count;e++){const e=this.prices[s]-o;r+=e*e,++s===this.interval&&(s=0)}const n=Math.sqrt(this.count?r/this.count:0);return this.result={lower:i-n*this.deviationMultiplier,middle:i,upper:i+n*this.deviationMultiplier}}}class k extends m{constructor(e,t,s){super(),this.short=e,this.long=t,this.signal=s,this.pricesCounter=0}update(e,t=!1){t&&0!==this.pricesCounter||this.pricesCounter++;const s=this.short.update(e,t),i=this.long.update(e,t);if(this.pricesCounter>this.long.interval&&this.pricesCounter--,this.pricesCounter===this.long.interval){const e=s-i,o=this.signal.update(e,t);return this.result={histogram:e-o,macd:e,signal:o}}}}class x extends m{constructor(e,t,s){super(),this.n=e,this.m=t,this.p=s,this.periodM=new f(t),this.periodP=new f(s),this.candles=new Array(e),this.count=0,this.head=0}update(e){if(this.count<this.n?this.candles[this.count++]=e:(this.candles[this.head]=e,this.head=(this.head+1)%this.n),this.count===this.n){let t=-1/0,s=1/0,i=this.head;for(let e=0;e<this.count;e++)t=Math.max(t,this.candles[i].high),++i===this.n&&(i=0);i=this.head;for(let e=0;e<this.count;e++)s=Math.min(s,this.candles[i].low),++i===this.n&&(i=0);const o=t-s,r=100*(e.close-s)/(0===o?1:o),n=this.periodM.update(r),a=n&&this.periodP.update(n);if(void 0!==n&&void 0!==a)return this.result={stochD:a,stochK:n}}}}const O=(e,t)=>{if(0===e&&(e=.001),0===t&&(t=.001),Math.sign(e)!==Math.sign(t))throw new Error(`[BUG] Params must have the same sign in mathLog a=${e} b=${t}.`);e<0&&(e=-e,t=-t);const s=Math.log(e/t);if(null==(i=s)||!Number.isFinite(i))throw new Error(`[BUG] Invalid params passed to mathLog a=${e} b=${t}.`);var i;return s},T=e=>{const t=String(e);return 1===e?0:t.length-1},M=(e,t,s)=>{if("string"!=typeof e)throw new Error("addPrecisionExact expects a string when precision=true");const i="-"===e.charAt(0),o=i?e.slice(1):e,[r,n=""]=o.split("."),a=void 0===s?T(t):s,l=n.padEnd(a,"0").slice(0,a);let c=parseInt(r+l||"0",10);return i&&(c=-c),c},S={number:e=>e,numberCleanString:e=>Number(e),precisionNumberCleanString:(e,t,s)=>M(e,t,s)},F=(e,t,s)=>((e,t,s)=>{if("number"!=typeof e||!Number.isFinite(e))throw new Error("revertPrecisionAsNumber expects a finite number");const i=e<0;let o=Math.abs(e);o=Math.trunc(o);const r=void 0===s?T(t):s;if(0===r)return i?-o:o;const n=Math.trunc(o/t);let a=String(o%t).padStart(r,"0");a=a.replace(/0+$/,"");const l=0===a.length?String(n):`${n}.${a}`;return Number(i?`-${l}`:l)})(e,t,s),P=(e,t=!1,s=!1)=>{const i="number"==typeof e&&!Number.isNaN(e),o="string"==typeof e&&/^-?\d+(\.\d+)?$/.test(e);if(!0===s){if(o)return"precisionNumberCleanString";if(t)throw new Error("Invalid number forma");return typeof e}if(i)return"number";if(o)return"numberCleanString";if(t)throw new TypeError("Invalid input: expected a number or numeric string");return typeof e},A={toString:e=>e.toString(),string:e=>e.toString(),toISOString:e=>e.toISOString(),iso:e=>e.toISOString(),toUTCString:e=>e.toUTCString(),milliseconds:e=>e.getTime(),seconds:e=>e.getTime()/1e3,object:e=>e},C={dateObject:e=>e,dateMilliseconds:e=>new Date(e),dateSeconds:e=>new Date(1e3*e),dateIncompleteDayString:e=>new Date(`${e} 00:00:00`),dateCompleteDateString:e=>new Date(e)},D=e=>{const t=/^\d{4}-\d{2}-\d{2}[T ]\d{2}:\d{2}:\d{2}(?:\.\d+)?Z$/i,s=/^\d{4}-\d{2}-\d{2}[T ]\d{2}:\d{2}:\d{2}(?:\.\d+)?([+-]\d{2}:\d{2})$/,i=/^\d{4}-\d{2}-\d{2}[T ]\d{2}:\d{2}:\d{2}(?:\.\d+)?$/,o=/^\d{4}-\d{2}-\d{2}$/,r=/^\d{4}\/\d{2}\/\d{2}$/,n=["Date -> object","Milliseconds Timestamp -> integer","Seconds Timestamp -> integer","UTC Time Format (ISO 8601) -> string","Including a Timezone Offset (ISO 8601) -> string","Local Time Format (ISO 8601) -> string","YYYY/MM/DD or YYYY-MM-DD -> string"],a=()=>{throw new Error(`Invalid "${typeof e}" date value passed in selectDateFormatter. Supported formats: \n-${n.join("\n- ")}`)};if("object"==typeof e){if(e instanceof Date&&!isNaN(e.valueOf()))return"dateObject";a()}else{if("number"==typeof e)return Math.abs(e)<1e11?"dateSeconds":"dateMillseconds";if("string"==typeof e){if(t.test(e)||s.test(e)||i.test(e)&&e.length>10||r.test(e))return"dateCompleteDateString";if(o.test(e))return"dateIncompleteDayString";a()}else a()}},E=(e,t,s)=>{const i={Array,Float64Array,Float32Array,Int32Array,Uint8Array,Int8Array,Int16Array}[e];if(!i||"function"!=typeof i.from)throw new Error(`Unsupported array type: ${e}`);let o;return o=void 0!==s?s:"Array"===e?null:NaN,new i(t).fill(o)},I=(e,t,{lag:s=0}={})=>{const i=[],o=[];for(const{key:s,type:r="Float64Array",fill:n,enabled:a=!0,priceBased:l=!1,includeInLag:c=!0}of t)if(a){if(Object.prototype.hasOwnProperty.call(e.verticalOhlcv,s))throw new Error(`Output column "${s}" already exists in verticalOhlcv.`);if(/^(?:Int|Uint)/.test(r)&&void 0===n)throw new Error(`Integer output column "${s}" requires an explicit fill value.`);e.verticalOhlcv[s]=E(r,e.len,n),l&&e.priceBased.add(s),i.push(s),c&&o.push(s)}return s>0&&o.length>0&&(c(s,{min:1,max:e.len},"lag","initializeColumns"),e.executionParams.push({key:"lag",params:[o,s]})),i},L=e=>null==e||!Number.isFinite(e),j={ema:g,sma:f},R=(e,t,s,i,{target:o,lag:r,retLogs:n=!1})=>{const{verticalOhlcv:a,instances:l,priceBased:c}=e,h=`${n?"ret_log_":""}${s}_${i}${"close"!==o?`_${o}`:""}`;if(0===t){if(u({[o]:!0},a,t,s),!a.hasOwnProperty(o))throw new Error(`Target property ${o} not found in verticalOhlcv for ${s}.`);l[h]=new j[s](i),I(e,n?[{key:`${h}_distance`,priceBased:!1},{key:`${h}_change`,priceBased:!1}]:[{key:h,priceBased:c.has(o)}],{lag:r})}const p=a[o][t];if(L(p))return;const m=l[h],d=m.isStable?m.getResult():NaN;m.update(p);const g=m.isStable?m.getResult():NaN;if(!L(g))if(n){const s=O(p,g);if(e.pushToMain({index:t,key:`${h}_distance`,value:s}),L(d))return;const i=O(g,d);e.pushToMain({index:t,key:`${h}_change`,value:i})}else e.pushToMain({index:t,key:h,value:g})},H=e=>null==e||!Number.isFinite(e),B=(e,t)=>(e-t)/t,V="close",z=Symbol("lagColumns"),K=(e,t)=>{const s=new Uint8Array(t);return s[e]=1,s},U=(e,t)=>e>t,Z=(e,t)=>e<t;class G{constructor(){Object.assign(this,{interval:0,prevState:.5,prevFast:NaN,prevSlow:NaN,prevHigh:NaN,prevLow:NaN,areHighAndLowUndefined:!1})}update(e,{fast:t,high:s,slow:i,low:o}){let r=this.prevState;this.areHighAndLowUndefined||void 0!==s&&void 0!==o||(this.areHighAndLowUndefined=!0),Number.isNaN(t)||Number.isNaN(i)||((e,t)=>e===t)(t,i)?r=.5:U(t,i)?r=this.areHighAndLowUndefined?1:[o,i,this.prevLow,this.prevSlow].every(e=>!Number.isNaN(e))&&Z(o,i)&&U(this.prevLow,this.prevSlow)?0:1:Z(t,i)&&(r=this.areHighAndLowUndefined?0:[s,i,this.prevHigh,this.prevSlow].every(e=>!Number.isNaN(e))&&U(s,i)&&Z(this.prevHigh,this.prevSlow)?1:0),.5===r?this.interval=0:1===r?this.prevState<=.5?this.interval=1:this.interval++:0===r&&(this.prevState>=.5?this.interval=-1:this.interval--),Object.assign(this,{prevState:r,prevFast:t,prevSlow:i,prevHigh:s,prevLow:o})}getResult(){return this.interval}}const Y=["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],q=e=>null==e||!Number.isFinite(e),J=(e,t=new Set)=>{if(null===e||"string"==typeof e||"boolean"==typeof e)return e;if("number"==typeof e&&Number.isFinite(e))return e;if("object"!=typeof e||null===e)throw new TypeError("Configuration values must be JSON-safe: no undefined, non-finite numbers, or functions.");if(t.has(e))throw new TypeError("Configuration must not contain circular references.");const s=Object.getPrototypeOf(e);if(!Array.isArray(e)&&s!==Object.prototype&&null!==s)throw new TypeError("Configuration must contain only plain objects and arrays.");if(Object.getOwnPropertySymbols(e).length)throw new TypeError("Configuration must not contain symbol keys.");t.add(e);const i=Array.isArray(e)?Array.from(e,e=>J(e,t)):Object.fromEntries(Object.entries(e).map(([e,s])=>[e,J(s,t)]));return t.delete(e),i},W=e=>{if(null!==e&&"object"==typeof e){for(const t of Object.values(e))W(t);Object.freeze(e)}return e},Q=Object.freeze([Object.freeze({sessions:21,weight:.1}),Object.freeze({sessions:63,weight:.3}),Object.freeze({sessions:126,weight:.4}),Object.freeze({sessions:252,weight:.2})]),X=Symbol("scoreMomentumStates"),ee=e=>{if(J(e),!Array.isArray(e)||0===e.length)throw new TypeError("lookbacks must be a non-empty array.");const t=new Set;let s=0;for(const[i,o]of e.entries()){if(null===o||"object"!=typeof o||Array.isArray(o))throw new TypeError(`lookbacks[${i}] must be an object.`);const{sessions:e,weight:r}=o;if(!Number.isInteger(e)||e<1)throw new RangeError(`lookbacks[${i}].sessions must be a positive integer, got ${e}.`);if(t.has(e))throw new RangeError(`lookbacks[${i}].sessions is duplicated: ${e}.`);if("number"!=typeof r||!Number.isFinite(r))throw new TypeError(`lookbacks[${i}].weight must be a finite number, got ${r}.`);if(r<.099999999||r>1+1e-9)throw new RangeError(`lookbacks[${i}].weight must be between 0.1 and 1, got ${r}.`);t.add(e),s+=r}if(s>1+1e-9)throw new RangeError(`The sum of weights must not exceed 1, got ${s}.`)},te={candleFeatures:(e,t,{lag:s,colKeys:i,retLogs:o})=>{const{verticalOhlcv:r,priceBased:n,scaledGroups:a}=e,l=(e,t)=>o?Math.log(e/t):(e-t)/t,c=o?"ret_log_":"ret_";if(0===t){u({open:!0,high:!0,low:!0,close:!0},r,t,"candleFeatures");const o=["change","mid_price_change","upper_wick","lower_wick","gap","body","range"].map(e=>({key:`${c}${e}`}));for(const e of i){if(!r.hasOwnProperty(e))throw new Error(`Target property in "options.colKey" array "${e}" not found in verticalOhlcv for "candleFeatures".`);if(!n.has(e))throw new Error(`Target property in "options.colKey" array "${e}" not found in priceBased for "candleFeatures".`);o.push({key:`${c}${e}`})}a.candleFeatures=I(e,o,{lag:s})}const h=r.close[t-1],p=r.open[t-1];if(void 0===h)return;const m=r.open[t],d=r.high[t],g=r.low[t],f=r.close[t],v=(h+p)/2,y=(m+f)/2,w=Math.max(m,f),b=Math.min(m,f),$=l(f,h),N=l(y,v),_=l(d,w),k=l(b,g),x=l(m,h),O=l(f,m),T=l(d,g);if(0===i.length)return e.pushToMain({index:t,key:`${c}change`,value:$}),e.pushToMain({index:t,key:`${c}mid_price_change`,value:N}),e.pushToMain({index:t,key:`${c}upper_wick`,value:_}),e.pushToMain({index:t,key:`${c}lower_wick`,value:k}),e.pushToMain({index:t,key:`${c}gap`,value:x}),e.pushToMain({index:t,key:`${c}body`,value:O}),void e.pushToMain({index:t,key:`${c}range`,value:T});const M={[`${c}change`]:$,[`${c}mid_price_change`]:N,[`${c}upper_wick`]:_,[`${c}lower_wick`]:k,[`${c}gap`]:x,[`${c}body`]:O,[`${c}range`]:T};let S=!1;for(const e of i){const s=r[e][t];if(q(s)){S=!0;break}const i=l(f,s);M[`${c}${e}`]=i}if(!S)for(const[s,i]of Object.entries(M))e.pushToMain({index:t,key:s,value:i})},scoreMomentum:(e,t,s=Q)=>{const{verticalOhlcv:i,instances:o}=e;if(0===t){ee(s),u({close:!0},i,t,"scoreMomentum");let r=0;for(const{sessions:e}of s)r=Math.max(r,e);const n="score_momentum"+(e.useFullNames||e.inputParams.filter(e=>"scoreMomentum"===e.key).length>1?`_${s.map(({sessions:e,weight:t})=>`${e}_${t}`).join("_")}`:"");I(e,[{key:n}]),o[X]||(o[X]=new WeakMap),o[X].set(s,{key:n,maxSessions:r})}const{key:r,maxSessions:n}=o[X].get(s);if(t<n)return;const a=i.close,l=a[t];if(!Number.isFinite(l)||l<=0)return;let c=0;for(const{sessions:e,weight:i}of s){const s=a[t-e],o=l/s;if(!Number.isFinite(s)||s<=0||!Number.isFinite(o)||o<=0)return;c+=i*O(l,s)}Number.isFinite(c)&&e.pushToMain({index:t,key:r,value:c})},dateTime:(e,t,{lag:s,oneHot:i,precompute:o})=>{const{instances:r,verticalOhlcv:n}=e,{prefix:a}=o;if(0===t){const{dateType:t}=e;if(!t)throw Error('dateTime method found and invalid "date" in input ohlcv');Object.assign(r,{dateTime:{formatter:new Intl.DateTimeFormat("en-US-u-ca-gregory-nu-latn",{timeZone:e.timeZone,year:"numeric",month:"numeric",day:"numeric",weekday:"short",hour:"numeric",minute:"numeric",hourCycle:"h23"}),colKeys:[...o.colKeys,`${a}year`].filter(e=>"one_hot_year"!==e),colKeySizes:{...o.colKeySizes}}});const{colKeys:n}=r.dateTime;I(e,n.map(e=>({key:e,type:i?"Array":"Int16Array",fill:i?null:0})),{lag:s})}const{colKeySizes:l,formatter:c}=r.dateTime,h=n.date[t];let u,p,m,d,g,f;for(const e of c.formatToParts(h))switch(e.type){case"year":u=e.value;break;case"month":p=e.value;break;case"hour":m=e.value;break;case"minute":d=e.value;break;case"weekday":g=e.value;break;case"day":f=e.value}const v=Number(u),y=Number(p)-1,w=Number(m),b=Number(d),$=Y.indexOf(g),N=Number(f)-1;if(!i)return e.pushToMain({index:t,key:"year",value:v}),e.pushToMain({index:t,key:"month",value:y+1}),e.pushToMain({index:t,key:"hour",value:w}),e.pushToMain({index:t,key:"minute",value:b}),e.pushToMain({index:t,key:"day_of_the_week",value:($+6)%7+1}),void e.pushToMain({index:t,key:"day_of_the_month",value:N+1});const _=K(y,l.one_hot_month),k=K(w,l.one_hot_hour),x=K(b,l.one_hot_minute),O=K($,l.one_hot_day_of_the_week),T=K(N,l.one_hot_day_of_the_month);e.pushToMain({index:t,key:"one_hot_month",value:_}),e.pushToMain({index:t,key:"one_hot_hour",value:k}),e.pushToMain({index:t,key:"one_hot_minute",value:x}),e.pushToMain({index:t,key:"one_hot_day_of_the_week",value:O}),e.pushToMain({index:t,key:"one_hot_day_of_the_month",value:T})},heikenAshi:(e,t,s,i,{lag:o=0,noSmoothing:r=!1,retLogs:n=!1}={})=>{const{verticalOhlcv:a,instances:l,scaledGroups:c}=e,h=r?"heiken_ashi":`heiken_ashi_${s}_${i}`;if(0===t){u({open:!0,high:!0,low:!0,close:!0},a,t,"heikenAshi");const p=["open","high","low","close"],m=["body","upper_wick","lower_wick","range"],d=r?"":`_${s}_${i}`,f=n?"ret_log_":"ret_",v=Object.fromEntries(m.map(e=>[e,`${f}heiken_ashi_${e}${d}`])),y=`heiken_ashi_cross${d}`,w=Object.values(v);l[h]={emaPre:r?null:Object.fromEntries(p.map(e=>[e,new g(s)])),emaPost:r?null:Object.fromEntries(p.map(e=>[e,new g(i)])),prevHaOpen:NaN,prevHaClose:NaN,prevSmOpen:NaN,prevSmClose:NaN,trendDirection:0,getRet:n?O:B,outputKeys:v,crossKey:y},I(e,[...w,y].map(e=>({key:e})),{lag:o}),c&&(c.heikenAshi=w)}const p=a.open[t],m=a.high[t],d=a.low[t],f=a.close[t],v=l[h],{crossKey:y,emaPre:w,emaPost:b,getRet:$,outputKeys:N}=v;if(H(p)||H(m)||H(d)||H(f))return;let _,k,x,T;if(null!==w){if(w.open.update(p),w.high.update(m),w.low.update(d),w.close.update(f),!(w.open.isStable&&w.high.isStable&&w.low.isStable&&w.close.isStable))return;_=w.open.getResult(),k=w.high.getResult(),x=w.low.getResult(),T=w.close.getResult()}else _=p,k=m,x=d,T=f;if(H(_)||H(k)||H(x)||H(T))return;const M=(_+k+x+T)/4,S=Number.isNaN(v.prevHaOpen)||Number.isNaN(v.prevHaClose)?(_+T)/2:(v.prevHaOpen+v.prevHaClose)/2,F=Math.max(k,S,M),P=Math.min(x,S,M);let A,C,D,E;if(v.prevHaOpen=S,v.prevHaClose=M,null!==b){if(b.open.update(S),b.high.update(F),b.low.update(P),b.close.update(M),!(b.open.isStable&&b.high.isStable&&b.low.isStable&&b.close.isStable))return;A=b.open.getResult(),C=b.high.getResult(),D=b.low.getResult(),E=b.close.getResult()}else A=S,C=F,D=P,E=M;if(H(A)||H(C)||H(D)||H(E)||A<=0||C<=0||D<=0||E<=0)return;const L=Number.isFinite(v.prevSmOpen)&&Number.isFinite(v.prevSmClose),j=t>0?a[y][t-1]:NaN,R=E>A?1:E<A?-1:v.trendDirection;let V=0;L&&0!==R&&(V=Number.isFinite(j)&&Math.sign(j)===R?j+R:R),v.trendDirection=R,v.prevSmOpen=A,v.prevSmClose=E;const z=Math.max(A,E),K=Math.min(A,E),U=$(E,A),Z=$(C,z),G=$(K,D),Y=$(C,D);H(U)||e.pushToMain({index:t,key:N.body,value:U}),H(Z)||e.pushToMain({index:t,key:N.upper_wick,value:Z}),H(G)||e.pushToMain({index:t,key:N.lower_wick,value:G}),H(Y)||e.pushToMain({index:t,key:N.range,value:Y}),e.pushToMain({index:t,key:y,value:V})},rsi:(e,t,s,{target:i,lag:o,retLogs:r})=>{const{verticalOhlcv:n,instances:a}=e,l="close"===i?"":`_${i}`,c=r?`ret_log_rsi_${s}${l}`:`rsi_${s}${l}`,h=r?`ret_log_rsi_sma_${s}${l}`:`rsi_sma_${s}${l}`;if(0===t){if(u({[i]:!0},n,t,"rsi"),!n.hasOwnProperty(i))throw new Error(`Target property ${i} not found in verticalOhlcv for rsi.`);Object.assign(a,{[c]:new y(s),[h]:new f(s)}),I(e,[{key:c},{key:h}],{lag:o})}const p=n[i][t];a[c].update(p);const m=a[c].isStable?a[c].getResult():NaN,d=Number.isNaN(m)?NaN:r?O(m,50):m;e.pushToMain({index:t,key:c,value:d}),Number.isNaN(m)||a[h].update(m);const g=a[h].isStable?a[h].getResult():NaN,v=Number.isNaN(g)?NaN:r?O(g,50):g;e.pushToMain({index:t,key:h,value:v})},mfi:(e,t,s,{lag:i,retLogs:o})=>{const{verticalOhlcv:r,instances:n}=e,a=`${o?"ret_log_":""}mfi_${s}`;0===t&&(u({high:!0,low:!0,close:!0,volume:!0},r,t,"mfi"),I(e,[{key:a}],{lag:i}),n[a]={flows:new Float64Array(s),next:0,count:0,previousTypical:NaN});const l=n[a],c=(r.high[t]+r.low[t]+r.close[t])/3,h=c-l.previousTypical;if(l.previousTypical=c,0===t)return;const p=c*r.volume[t];if(l.flows[l.next]=Number.isFinite(h)&&Number.isFinite(p)&&p>=0?Math.sign(h)*p:NaN,l.next=(l.next+1)%s,l.count<s&&l.count++,l.count<s)return;let m=0,d=0,g=l.next;for(let e=0;e<s;e++){const e=l.flows[g];if(Number.isNaN(e))return;e>0?m+=e:e<0&&(d-=e),++g===s&&(g=0)}if(!Number.isFinite(m)||!Number.isFinite(d))return;const f=0===m&&0===d?NaN:100-100/(1+m/d);e.pushToMain({index:t,key:a,value:Number.isNaN(f)?NaN:o?O(f,50):f})},cmf:(e,t,s,i={})=>{const{verticalOhlcv:o,instances:r}=e,{lag:n=0}=i,a=`cmf_${s}`;if(0===t){const l=Object.keys(i).find(e=>"lag"!==e);if(l)throw new Error(`Unsupported option "${l}" in "cmf"; only "lag" is available.`);u({high:!0,low:!0,close:!0,volume:!0},o,t,"cmf"),I(e,[{key:a}],{lag:n}),r[a]={moneyFlowVolumes:new Float64Array(s),volumes:new Float64Array(s),next:0,count:0}}const l=r[a],c=o.high[t],h=o.low[t],p=o.close[t],m=o.volume[t],d=c-h;let g=NaN,f=NaN;if(Number.isFinite(c)&&Number.isFinite(h)&&Number.isFinite(p)&&Number.isFinite(m)&&m>=0&&c>=h&&p>=h&&p<=c&&Number.isFinite(d)){const e=0===d?0:(p-h-(c-p))/d,t=e*m;Number.isFinite(e)&&Number.isFinite(t)&&(g=t,f=m)}if(l.moneyFlowVolumes[l.next]=g,l.volumes[l.next]=f,l.next=(l.next+1)%s,l.count<s&&l.count++,l.count<s)return;let v=0,y=0,w=l.next;for(let e=0;e<s;e++){const e=l.moneyFlowVolumes[w],t=l.volumes[w];if(!Number.isFinite(e)||!Number.isFinite(t))return;v+=e,y+=t,++w===s&&(w=0)}if(!Number.isFinite(v)||!Number.isFinite(y)||0===y)return;const b=v/y;Number.isFinite(b)&&e.pushToMain({index:t,key:a,value:b})},stochastic:(e,t,s,i,o,{lag:r,retLogs:n})=>{const{verticalOhlcv:a,instances:l,useFullNames:c}=e,h=14!==s||3!==i||3!==o||c?`_${s}_${i}_${o}`:"",p=n?`ret_log_stochastic_d${h}`:`stochastic_d${h}`,m=n?`ret_log_stochastic_k${h}`:`stochastic_k${h}`,d=h;0===t&&(u({high:!0,low:!0,close:!0},a,t,"stochastic"),Object.assign(l,{[d]:new x(s,i,o)}),I(e,[{key:p},{key:m}],{lag:r}));const g=a.close[t],f=a.low[t],v=a.high[t];l[d].update({close:g,low:f,high:v});const y=l[d].isStable?l[d].getResult():null,w=y?n?O(y.stochK,50):y.stochK:NaN,b=y?n?O(y.stochD,50):y.stochD:NaN;e.pushToMain({index:t,key:m,value:w}),e.pushToMain({index:t,key:p,value:b})},atr:(e,t,s,{lag:i,retLogs:o})=>{const{verticalOhlcv:r,instances:n}=e,a=o?`ret_log_atr_${s}`:`atr_${s}`;if(0===t){const{instances:r,verticalOhlcv:n}=e;u({high:!0,low:!0,close:!0},n,t,"atr"),r[a]=new b(s,v),I(e,[{key:a,priceBased:!o}],{lag:i})}const l={high:r.high[t],low:r.low[t],close:r.close[t]},c=n[a];c.update(l);const h=c.isStable?c.getResult():NaN;e.pushToMain({index:t,key:a,value:Number.isNaN(h)?NaN:o?O(h,l.close):h})},adx:(e,t,s,{lag:i,retLogs:o})=>{const{verticalOhlcv:r,instances:n,useFullNames:a}=e,l=o?`ret_log_adx_${s}`:`adx_${s}`,c=`adx_${s}`;if(0===t){if(u({high:!0,low:!0,close:!0},r,t,"adx"),!r.hasOwnProperty("high"))throw new Error("Property high not found in verticalOhlcv for adx.");if(!r.hasOwnProperty("low"))throw new Error("Property low not found in verticalOhlcv for adx.");if(!r.hasOwnProperty("close"))throw new Error("Property close not found in verticalOhlcv for adx.");Object.assign(n,{[c]:new N(s)}),I(e,[{key:l}],{lag:i})}const h=r.high[t],p=r.low[t],m=r.close[t];n[c].update({high:h,low:p,close:m});const d=n[c].isStable?n[c].getResult():NaN,g=Number.isNaN(d)?NaN:o?O(d,20):d;e.pushToMain({index:t,key:l,value:g})},ema:R,sma:R,macd:(e,t,s,i,o,{target:r,lag:n,precomputed:a})=>{const{verticalOhlcv:l,instances:c,useFullNames:h}=e,{instanceKey:p}=a;if(0===t){u({[r]:!0},l,t,"macd");const{inputParams:a}=e;if(!l.hasOwnProperty(r))throw new Error(`Target property ${r} not found in verticalOhlcv for macd.`);let m=0;for(const e of a)"macd"===e.key&&m++;const d=m>1||h,f=`${s}_${i}_${o}`,v=e=>r===V?d?`macd_${e}_${f}`:`macd_${e}`:d?`macd_${e}_${r}_${f}`:`macd_${e}_${r}`,y=v("diff"),w=v("dea"),b=v("histogram");c.hasOwnProperty("macd")||(c.macd={numberOfIndicators:m,settings:{}}),c.macd.settings[p]=new k(new g(s),new g(i),new g(o)),I(e,[y,w,b].map(e=>({key:e,priceBased:!0})),{lag:n})}const{numberOfIndicators:m,settings:d}=c.macd,f=m>1||h,v=`${s}_${i}_${o}`,y=e=>r===V?f?`macd_${e}_${v}`:`macd_${e}`:f?`macd_${e}_${r}_${v}`:`macd_${e}_${r}`,w=y("diff"),b=y("dea"),$=y("histogram"),N=d[p],_=l[r][t];N.update(_);const x=N.isStable?N.getResult():null;e.pushToMain({index:t,key:w,value:x?x.macd:NaN}),e.pushToMain({index:t,key:b,value:x?x.signal:NaN}),e.pushToMain({index:t,key:$,value:x?x.histogram:NaN})},volumeDelta:(e,t,{lag:s=0})=>{const{verticalOhlcv:i,instances:o}=e,r="volume_delta";0===t&&(u({open:!0,close:!0,volume:!0},i,t,"volumeDelta"),o[r]||(o[r]={isBuyVolume:!0,cross:0}),I(e,[`${r}_high`,`${r}_low`,`${r}_close`,`${r}_cross`].map(e=>({key:e})),{lag:s}));const n=o[r],{hasInvalidInputValue:a}=n,l=i.volume[t];if(0===l)return;const c=i.open[t],h=i.close[t],p=t>0?i.close[t-1]:NaN;let m=n.isBuyVolume;h>c?m=!0:h<c?m=!1:h>p?m=!0:h<p&&(m=!1),n.isBuyVolume=m,t<1?n.cross=m?1:-1:m?n.cross>0?n.cross=n.cross+1:n.cross=1:n.cross>0?n.cross=-1:n.cross=n.cross-1;const d=m?l:-l,g=d,f=Math.max(d,0),v=Math.min(d,0);e.pushToMain({index:t,key:`${r}_high`,value:f}),e.pushToMain({index:t,key:`${r}_low`,value:v}),e.pushToMain({index:t,key:`${r}_close`,value:g}),e.pushToMain({index:t,key:`${r}_cross`,value:n.cross})},relativeVolume:(e,t,s,{lag:i,retLogs:o=!1})=>{const r=`${o?"ret_log_":""}relative_volume_${s}`,{instances:n,verticalOhlcv:a}=e;0===t&&(u({volume:!0},a,t,"relativeVolume"),n[r]={instance:new f(s),prevRelativeVolumeSma:NaN},I(e,[{key:r}],{lag:i}));const l=a.volume[t];if(0===l)return;const c=n[r].instance;c.update(l);const h=c.isStable?c.getResult():NaN,p=n[r].prevRelativeVolumeSma;if(n[r].prevRelativeVolumeSma=h,Number.isNaN(h)||Number.isNaN(p))return;const m=l/p,d=o?l>0&&p>0&&m>0&&Number.isFinite(m)?O(m,1):NaN:m;e.pushToMain({index:t,key:r,value:d})},donchianChannels:(e,t,s,i,o)=>{const{verticalOhlcv:r,instances:n,len:a,inputParams:l,useFullNames:c}=e,{lag:h=0,retLogs:p=!1}=o,m=`${s}_${i}`,d=`${p?"ret_log_":""}${m}`,g=(p?"ret_log_":"")+"donchian_channel";if(0===t){u({high:!0,low:!0},r,t,"donchianChannels"),p&&u({close:!0},r,t,"donchianChannels");const s=l.filter(e=>"donchianChannels"===e.key).length,i=s>1||c,o=(p?["width","position"]:["upper","basis","lower"]).map(e=>i?`${g}_${e}_${m}`:`${g}_${e}`);n.donchian_channel||(n.donchian_channel={numberOfIndicators:s,settings:{}}),n.donchian_channel.numberOfIndicators=s,n.donchian_channel.settings[d]={maxDeque:{indices:[],head:0,length:0},minDeque:{indices:[],head:0,length:0}},I(e,o.map(e=>({key:e,priceBased:!p})),{lag:h})}const{numberOfIndicators:f,settings:v}=n.donchian_channel,y=f>1||c,w=e=>y?`${g}_${e}_${m}`:`${g}_${e}`,{maxDeque:b,minDeque:$}=v[d],N=t-i,_=N-s+1;if(N<0||N>=a)return;const{high:k,low:x}=r,T=(e,t,i)=>{const{indices:o}=e;for(;e.length&&o[e.head]<_;)e.head=(e.head+1)%s,e.length--;for(;e.length&&i(t[o[(e.head+e.length-1)%s]],t[N]);)e.length--;o[(e.head+e.length)%s]=N,e.length++};if(T(b,k,(e,t)=>e<=t),T($,x,(e,t)=>e>=t),_<0)return;const M=b.length&&$.length,S=M?k[b.indices[b.head]]:NaN,F=M?x[$.indices[$.head]]:NaN;if(p){let s=NaN,i=NaN;const o=S/F;if(F>0&&S>=F&&Number.isFinite(S)&&Number.isFinite(o)){const e=O(o,1);s=e/2;const n=r.close[t],a=n/F;if(e>0&&n>0&&a>0&&Number.isFinite(a)){const t=2*O(a,1)/e-1;Number.isFinite(t)&&(i=t)}}return e.pushToMain({index:t,key:w("width"),value:s}),void e.pushToMain({index:t,key:w("position"),value:i})}const P=M?(S+F)/2:NaN;e.pushToMain({index:t,key:w("upper"),value:S}),e.pushToMain({index:t,key:w("basis"),value:P}),e.pushToMain({index:t,key:w("lower"),value:F})},bollingerBands:(e,t,s,i,{lag:o,retLogs:r=!1}={})=>{const{verticalOhlcv:n,instances:a,useFullNames:l}=e,c=`${s}_${i}`,h=`${r?"ret_log_":""}${c}`,p=(r?"ret_log_":"")+"bollinger_bands",m="close";if(0===t){const{inputParams:n,verticalOhlcv:d,priceBased:g}=e;if(u({[m]:!0},d,t,"bollingerBands"),!(m in d))throw new Error(`bollingerBands could not find target "${m}"`);let f=0;for(const e of n)"bollingerBands"===e.key&&f++;a.bollinger_bands||(a.bollinger_bands={numberOfIndicators:f,settings:{}}),a.bollinger_bands.settings[h]=new _(s,i);const v=f>1||l?`_${c}`:"";I(e,(r?[`${p}_width${v}`,`${p}_position${v}`]:[`${p}_upper${v}`,`${p}_middle${v}`,`${p}_lower${v}`]).map(e=>({key:e,priceBased:!r&&g.has(m)})),{lag:o})}const{numberOfIndicators:d}=a.bollinger_bands,g=d>1||l?`_${c}`:"",f=a.bollinger_bands.settings[h],v=n[m][t];f.update(v);const y=f.isStable?f.getResult():null,w=y?.upper??NaN,b=y?.middle??NaN,$=y?.lower??NaN;if(r){let s=NaN,i=NaN;const o=w/$;if($>0&&w>=$&&Number.isFinite(w)&&Number.isFinite(o)){const e=O(o,1);s=e/2;const t=v/$;if(e>0&&v>0&&t>0&&Number.isFinite(t)){const s=2*O(t,1)/e-1;Number.isFinite(s)&&(i=s)}}return e.pushToMain({index:t,key:`${p}_width${g}`,value:s}),void e.pushToMain({index:t,key:`${p}_position${g}`,value:i})}e.pushToMain({index:t,key:`${p}_upper${g}`,value:w}),e.pushToMain({index:t,key:`${p}_middle${g}`,value:b}),e.pushToMain({index:t,key:`${p}_lower${g}`,value:$})},volumeOscillator:(e,t,s,i,{lag:o,retLogs:r})=>{const{verticalOhlcv:n,instances:a}=e,l=r?`ret_log_volume_oscillator_${s}_${i}`:`volume_oscillator_${s}_${i}`;0===t&&(u({volume:!0},n,t,"volumeOscillator"),Object.assign(a,{[l]:{fastEMA:new g(s),slowEMA:new g(i)}}),I(e,[{key:l}],{lag:o}));const{fastEMA:c,slowEMA:h}=a[l],p=n.volume[t];if(0===p)return;c.update(p),h.update(p);const m=c.isStable?c.getResult():NaN,d=h.isStable?h.getResult():NaN;let f=NaN;Number.isNaN(m)||Number.isNaN(d)||(f=r?O(m,d):100*(m-d)/d,e.pushToMain({index:t,key:l,value:f}))},crossPairs:(e,t,s,{oneHot:i,limit:o})=>{const{verticalOhlcv:r,verticalOhlcvTempCols:n,instances:a,len:l,precision:c,precisionMultiplier:h,priceBased:u}=e;for(const{fast:p,slow:m}of s){const s=`${p}_x_${m}`;if(0===t){if("number"==typeof m){const e=m.toString();n.add(e);const t=c&&("price"===p||u.has(p)),s=t?M(e,h):m,i=m>=-125&&m<=125&&!1===t?"Int8Array":"Float64Array";r[e]=E(i,l,s)}a.hasOwnProperty("crossPairs")||(a.crossPairs={}),a.crossPairs[s]={run:new G,min:1/0,max:-1/0},I(e,[{key:s,type:null!==o&&o<=125?"Int8Array":"Float64Array",fill:0},{key:`one_hot_${s}`,type:"Array",enabled:i}])}else if(t+1===l){if("price"!==p&&!r.hasOwnProperty(p))throw new Error(`crossPairs invalid param: fast "${p}" not found in "verticalOhlcv": ${JSON.stringify(Object.keys(r))}`);if(!r.hasOwnProperty(m))throw new Error(`crossPairs invalid param: slow "${m}" not found in "verticalOhlcv": ${JSON.stringify(Object.keys(r))}`)}if("price"!==p&&!r.hasOwnProperty(p))return;if(!r.hasOwnProperty(m))return;const{run:d}=a.crossPairs[s];if("price"===p){const e=r.close[t],s=r[m][t];d.update(t,{fast:e,slow:s,high:r.high[t],low:r.low[t]})}else{const e=r[p][t],s=r[m][t];d.update(t,{fast:e,slow:s})}const g=d.getResult(),f=null!==o?Math.min(Math.max(g,-o),o):g;if(e.pushToMain({index:t,key:s,value:f}),i){const i=f+o,r=2*o+1;e.pushToMain({index:t,key:`one_hot_${s}`,value:K(i,r)})}}},lag:(e,t,s,i)=>{const{verticalOhlcv:o,priceBased:r,instances:n}=e;if(0===t){const t=new Map;for(const n of s){if(!o.hasOwnProperty(n))throw new Error(`Lag processing invoked by col "${n}" was not found in "verticalOhlcv".`);const s=r.has(n),a=Array.isArray(o[n])?"Array":"Float64Array",l=[],c=[];for(let e=1;e<=i;e++){const t=`${n}_lag_${e}`;l.push({key:t,type:a,priceBased:s,includeInLag:!1}),c.push(t)}I(e,l),t.set(n,c)}n[z]||(n[z]=new WeakMap),n[z].set(s,t)}const a=n[z]?.get(s);for(const r of s){const s=a?.get(r),n=o[r],l=Array.isArray(n)?null:NaN;for(let o=1;o<=i;o++){const i=s?.[o-1]??`${r}_lag_${o}`,a=t-o,c=a<0||null==n[a]?l:n[a];e.pushToMain({index:t,key:i,value:c})}}}},se=({main:e,skipNull:t=!1,startIndex:s=0,dateFormat:i})=>{const{verticalOhlcv:o,invalidValueIndex:r,len:n,verticalOhlcvKeyNames:a,verticalOhlcvTempCols:l,priceBased:c,precision:h,precisionMultiplier:u}=e;if(0===a.length)return[];const p=h&&"number"==typeof u?T(u):void 0,m=t&&r>=0?r+1:0,d=Math.max(m,s),g=n-d,f=Array.from({length:g},()=>({}));for(const[e,t]of Object.entries(o))if(!l.has(e))if("date"===e){const s=A[i];for(let i=d;i<n;i++)f[i-d][e]=s(t[i])}else if(h&&c.has(e)){const s=F;for(let i=d;i<n;i++){const o=t[i];f[i-d][e]=null==o||Number.isNaN(o)?o:s(o,u,p)}}else for(let s=d;s<n;s++)f[s-d][e]=t[s];return f};class ie{constructor({input:e,ticker:t=null,chunkProcess:s=2e3,config:o={}}){if(null===o||Array.isArray(o)||"object"!=typeof o)throw new TypeError('Constructor "config" must be a plain object.');const n=J(o),u=["schemaVersion","precision","useFullNames","inputParams","dateFormat","skipNull","timeZone"];for(const e of Object.keys(n))if(!u.includes(e))throw new Error(`Unknown configuration option "${e}".`);const{schemaVersion:p=1,precision:m=!1,useFullNames:d=!1,inputParams:g=null,dateFormat:f="milliseconds",skipNull:v=!0,timeZone:y=Intl.DateTimeFormat().resolvedOptions().timeZone}=n;if(1!==p)throw new Error(`Unsupported configuration schemaVersion: ${p}.`);l(v,"config.skipNull","constructor"),h(f,"config.dateFormat","constructor"),a(Object.keys(A),f,"config.dateFormat","constructor"),h(y,"config.timeZone","constructor");const w=new Intl.DateTimeFormat("en-US",{timeZone:y}).resolvedOptions().timeZone;if(this.config=Object.freeze({schemaVersion:p,precision:m,useFullNames:d,dateFormat:f,skipNull:v,timeZone:w}),this.timeZone=w,r(e,"input",null!==t?`contructor ${t}`:"constuctor"),0===e.length)throw Error("input OHLCV must not be empty: "+t);c(s,{min:100,max:5e4,allowDecimals:!1},"chunkProcess","constructor"),l(m,"precision","contructor"),l(d,"config.useFullNames","constructor"),this.chunkProcess=s,this.input=[...e],this.len=this.input.length,this.firstRow=this.input[0],this.precision=m,this.useFullNames=d;const b=["open","high","low","close","mid_price"];this.initialPriceBased=new Set(b),this.priceBased=new Set(b),this.precisionMultiplier=(e=>{const{precision:t,firstRow:s,initialPriceBased:i}=e;if(!1===t)return 1;let o=1;for(const[e,t]of Object.entries(s)){if(!i.has(e))continue;if("string"!=typeof t||!/^\d+(\.\d+)?$/.test(t))throw new Error(`If "precision" is set to true all the "open", "high", "low" and "close" values must be numeric strings like "123.45" with no commas or currency symbols. Property "${e}" had the value "${t}" type ${typeof t}.`);const[s,r=""]=t.split("."),n=Number(s);let a=4;if(0===Math.abs(n)){const e=r.length,t=Math.max(4,e),s=r.search(/[1-9]/);if(-1===s)a=t;else{const e=s+1+5;a=Math.max(t,e)}}const l=10**a;l>o&&(o=l)}return o})(this);const{inputTypes:$,arrayTypes:N}=(e=>{const{firstRow:t,precision:s,initialPriceBased:i}=e,o={},r={},n=new Map;for(const[e,a]of Object.entries(t))if("date"===e)o[e]=D(a),r[e]="Array";else if("volume"===e)o[e]=P(a,!0),r[e]="Float64Array";else if(i.has(e))o[e]=P(a,!0,s),r[e]="Float64Array",n.set(e,o[e]);else{const t=P(a,!1,s);o[e]=t,r[e]="number"===t?"Float64Array":"Array"}if(new Set(n.values()).size>1){const e=[...n.entries()].map(([e,t])=>`${e}: "${t}"`).join(", ");throw new Error(`Inconsistent types among price-based columns — ${e}. All initialPriceBased columns must share the same numeric type.`)}return r.hasOwnProperty("open")&&r.hasOwnProperty("close")&&(r.mid_price=r.open,o.mid_price=o.open),{inputTypes:o,arrayTypes:r}})(this);if(this.inputTypes=$,this.arrayTypes=N,!this.firstRow.hasOwnProperty("close"))throw Error(`input OHLCV array objects require at least "close" property: ${t}`);return this.dateType=this.inputTypes.date?this.inputTypes.date:null,this.isComputed=!1,this.isComputing=!1,this.executionParams=[],this.instances={},this.verticalOhlcv={},this.verticalOhlcvKeyNames=[],this.verticalOhlcvTempCols=new Set,this.utilities={},this.invalidValueIndex=-1,this.scaledGroups={},this.isAlreadyComputed=new Set,this.pushToMain=({index:e,key:t,value:s})=>{this.verticalOhlcv[t][e]=s},null!==g?(i(g,this.len),this.inputParams=W(J(g)),this.compute()):this.inputParams=Object.freeze([]),this}exportConfig(){return{...this.config,inputParams:J(this.inputParams)}}_registerIndicator(e){return o(this),this.inputParams=Object.freeze([...this.inputParams,W(J(e))]),this}getData(e={}){this.compute();const{skipNull:t=this.config.skipNull,dateFormat:s=this.config.dateFormat}=e;return a(Object.keys(A),s,"dateFormat","getData"),n(e,"options","getData"),se({main:this,skipNull:t,startIndex:0,dateFormat:s})}getLastValues(e={}){this.compute();const{dateFormat:t=this.config.dateFormat}=e;return a(Object.keys(A),t,"dateFormat","getData"),se({skipNull:!1,main:this,startIndex:this.len-1,dateFormat:t})[0]}compute(){if(this.isComputed)return this;if(this.isComputing)throw new Error("Computation is already in progress.");if(this.executionParams=J(this.inputParams).sort((e,t)=>(e.order??0)-(t.order??0)),this.isComputed=!1,this.len>0){this.isComputing=!0;try{((e,t)=>{const{len:o,arrayTypes:r,verticalOhlcv:n,verticalOhlcvKeyNames:a,inputTypes:l,chunkProcess:c,precisionMultiplier:h,executionParams:u}=t;i(u,o);for(const{key:e}of u)if(!Object.prototype.hasOwnProperty.call(te,e))throw new Error(`Unknown indicator "${e}" in configuration.`);for(const e of Object.keys(l))n[e]=E(r[e],o);const p=Object.entries(l).map(([e,t])=>{const s=S.hasOwnProperty(t);return{key:e,formatter:s?S[t]:C.hasOwnProperty(t)?C[t]:null,numeric:s}}),m="number"==typeof h?T(h):void 0;let d=null;for(let i=0;i<o;i+=c){const r=Math.min(i+c,o);for(let o=i;o<r;o++){const i=e[o];for(const{key:e,formatter:s,numeric:r}of p){const n=i[e];if(void 0===n)continue;const a=null===s?n:r?s(n,h,m):s(n);t.pushToMain({index:o,key:e,value:a})}const r=(n.open[o]+n.close[o])/2;t.pushToMain({index:o,key:"mid_price",value:r});for(const{key:e,params:s}of u)te[e](t,o,...s);e[o]=null,null===d&&(d=Object.values(n)),s(d,o)||(t.invalidValueIndex=o)}}a.push(...Object.keys(n))})(this.input,this)}finally{this.isComputing=!1}this.isComputed=!0,this.input=[],this.instances={},this.firstRow=[]}return this}crossPairs(e=[],t={}){const s="crossPairs";o(this),r(e,"arr",s),n(t,"options",s);const{limit:i=null,oneHot:a=!1}=t;null!==i&&c(i,{min:2,max:this.len},"options.limit",s),l(a,"options.oneHot",s);const h=[];for(const{fast:t="",slow:s=""}of e){if(""===t||""===s)throw new Error(`Invalid crossPairs[${t}_${s}]: Object property “fast” must be a non-null column name and “slow” must be a non-null column name or integer.`);h.push(t.toString(),s.toString())}if(this.isAlreadyComputed.has(s))throw new Error(`You can only call the "${s}" method once.`);return this.isAlreadyComputed.add(s),this._registerIndicator({key:s,params:[e,{limit:i,oneHot:a}]}),this}lag(e=["close"],t=1){const s="lag";o(this),r(e,"colKeys",s);const i=e.find(e=>"string"!=typeof e||""===e);if(void 0!==i)throw new Error(`Invalid item "${i}" (column name) in "colKeys" array param of "${s}()".`);return c(t,{min:1,max:this.len,allowDecimals:!1},"lookback",s),this._registerIndicator({key:s,params:[e,t]}),this}relativeVolume(e=10,t={}){const s="relativeVolume";if(!this.inputTypes.hasOwnProperty("volume"))throw new Error('If "relativeVolume" is called the input ohlcv must contain valid volume properties.');o(this),c(e,{min:1,max:this.len,allowDecimals:!1},"size",s),n(t,"options",s);const{lag:i=0,retLogs:r=!1}=t;return c(i,{min:0,max:this.len,allowDecimals:!1},"options.lag",s),l(r,"options.retLogs",s),this._registerIndicator({key:s,order:0,params:[e,{lag:i,retLogs:r}]}),this}volumeDelta(e={}){const t="volumeDelta";if(!this.inputTypes.hasOwnProperty("volume"))throw new Error('If "volumeDelta" is called the input ohlcv must contain valid volume properties.');o(this),n(e,"options",t);const{lag:s=0}=e;return c(s,{min:0,max:this.len,allowDecimals:!1},"options.lag",t),this._registerIndicator({key:t,order:0,params:[{lag:s}]}),this}atr(e=14,t={}){const s="atr";o(this),c(e,{min:1,max:this.len,allowDecimals:!1},"size",s),n(t,"options",s);const{lag:i=0,retLogs:r=!1}=t;return c(i,{min:0,max:this.len,allowDecimals:!1},"options.lag",s),l(r,"options.retLogs",s),this._registerIndicator({key:s,order:0,params:[e,{lag:i,retLogs:r}]}),this}adx(e=14,t={}){const s="adx";o(this),c(e,{min:1,max:this.len,allowDecimals:!1},"size",s),n(t,"options",s);const{lag:i=0,retLogs:r=!1}=t;return c(i,{min:0,max:this.len,allowDecimals:!1},"options.lag",s),l(r,"options.retLogs",s),this._registerIndicator({key:s,order:0,params:[e,{lag:i,retLogs:r}]}),this}ema(e=5,t={}){const s="ema";o(this),c(e,{min:1,max:this.len,allowDecimals:!1},"size",s),n(t,"options",s);const{target:i="close",lag:r=0,retLogs:a=!1}=t;return h(i,"options.target",s),c(r,{min:0,max:this.len,allowDecimals:!1},"options.lag",s),l(a,"options.retLogs",s),this._registerIndicator({key:s,params:[s,e,{target:i,lag:r,retLogs:a}]}),this}sma(e=5,t={}){const s="sma";o(this),c(e,{min:1,max:this.len,allowDecimals:!1},"size",s),n(t,"options",s);const{target:i="close",lag:r=0,retLogs:a=!1}=t;return h(i,"options.target",s),c(r,{min:0,max:this.len,allowDecimals:!1},"options.lag",s),l(a,"options.retLogs",s),this._registerIndicator({key:s,params:[s,e,{target:i,lag:r,retLogs:a}]}),this}heikenAshi(e=null,t=null,s={}){const i="heikenAshi";o(this);const r=null===e&&null===t;!1===r&&(c(e,{min:1,max:this.len,allowDecimals:!1},"smoothLength",i),c(t,{min:1,max:this.len,allowDecimals:!1},"afterSmoothLength",i)),n(s,"options",i);const{lag:a=0,retLogs:h=!1}=s;return c(a,{min:0,max:this.len,allowDecimals:!1},"options.lag",i),l(h,"option.retLogs",i),this._registerIndicator({key:i,order:0,params:[e,t,{lag:a,noSmoothing:r,retLogs:h}]}),this}stochastic(e=14,t=3,s=3,i={}){const r="stochastic";o(this);const{len:a}=this;c(e,{min:1,max:a,allowDecimals:!1},"kPeriod",r),c(t,{min:1,max:a,allowDecimals:!1},"kSlowingPeriod",r),c(s,{min:1,max:a,allowDecimals:!1},"dPeriod",r),n(i,"options",r);const{lag:h=0,retLogs:u}=i;return c(h,{min:0,max:a,allowDecimals:!1},"options.lag",r),l(u,"retLogs",r),this._registerIndicator({key:r,params:[e,t,s,{lag:h,retLogs:u}]}),this}macd(e=12,t=26,s=9,i={}){const r="macd";o(this),c(e,{min:1,max:this.len,allowDecimals:!1},"fast",r),c(t,{min:1,max:this.len,allowDecimals:!1},"slow",r),c(s,{min:1,max:this.len,allowDecimals:!1},"signal",r),n(i,"options",r);const{target:a="close",lag:l=0}=i;h(a,"options.target",r),c(l,{min:0,max:this.len,allowDecimals:!1},"options.lag",r);const u={instanceKey:`${e}_${t}_${s}${"close"===a?"":`_${a}`}`};return this._registerIndicator({key:r,params:[e,t,s,{target:a,lag:l,precomputed:u}]}),this}bollingerBands(e=20,t=2,s={}){const i="bollingerBands";o(this),c(e,{min:1,max:this.len,allowDecimals:!1},"size",i),c(t,{min:.01,max:50,allowDecimals:!0},"stdDev",i),n(s,"options",i);const{lag:r=0,retLogs:a=!1}=s;return c(r,{min:0,max:this.len,allowDecimals:!1},"options.lag",i),l(a,"options.retLogs",i),this._registerIndicator({key:i,params:[e,t,{lag:r,retLogs:a}]}),this}rsi(e=14,t={}){const s="rsi";o(this),c(e,{min:1,max:this.len,allowDecimals:!1},"size",s),n(t,"options",s);const{target:i="close",lag:r=0,retLogs:a=!1}=t;return h(i,"options.target",s),c(r,{min:0,max:this.len,allowDecimals:!1},"options.lag",s),l(a,"retLogs",s),this._registerIndicator({key:s,params:[e,{target:i,lag:r,retLogs:a}]}),this}mfi(e=14,t={}){const s="mfi";o(this),c(e,{min:1,max:this.len,allowDecimals:!1},"size",s),n(t,"options",s);const{lag:i=0,retLogs:r=!1}=t;return c(i,{min:0,max:this.len,allowDecimals:!1},"options.lag",s),l(r,"options.retLogs",s),this._registerIndicator({key:s,params:[e,{lag:i,retLogs:r}]}),this}cmf(e=20,t={}){const s="cmf";if(!this.inputTypes.hasOwnProperty("volume"))throw new Error('If "cmf" is called the input ohlcv must contain valid volume properties.');o(this),c(e,{min:1,max:this.len,allowDecimals:!1},"size",s),n(t,"options",s);const i=Object.keys(t).find(e=>"lag"!==e);if(i)throw new Error(`Unsupported option "${i}" in "cmf"; only "lag" is available.`);const{lag:r=0}=t;return c(r,{min:0,max:this.len,allowDecimals:!1},"options.lag",s),this._registerIndicator({key:s,params:[e,{lag:r}]}),this}donchianChannels(e=20,t=0,s={}){const i="donchianChannels";o(this),c(e,{min:1,max:this.len,allowDecimals:!1},"size",i),c(t,{min:0,max:this.len,allowDecimals:!1},"offset",i),n(s,"options",i);const{lag:r=0,retLogs:a=!1}=s;return c(r,{min:0,max:this.len,allowDecimals:!1},"options.lag",i),l(a,"options.retLogs",i),this._registerIndicator({key:i,order:0,params:[e,t,{lag:r,retLogs:a}]}),this}volumeOscillator(e=5,t=10,s={}){const i="volumeOscillator";if(!this.inputTypes.hasOwnProperty("volume"))throw new Error('If "volumeOscillator" is called the input ohlcv must contain valid volume properties.');o(this),c(e,{min:1,max:this.len,allowDecimals:!1},"fastsize",i),c(t,{min:e,max:this.len,allowDecimals:!1},"slowsize",i),n(s,"options",i);const{lag:r=0,retLogs:a=!1}=s;return c(r,{min:0,max:this.len,allowDecimals:!1},"options.lag",i),l(a,"retLogs",i),this._registerIndicator({key:i,order:0,params:[e,t,{lag:r,retLogs:a}]}),this}dateTime(e={}){const t="dateTime";o(this),n(e,"options",t);const{lag:s=0,oneHot:i=!1}=e;c(s,{min:0,max:this.len,allowDecimals:!1},"options.lag",t),l(i,"options.oneHot",t);const r=i?"one_hot_":"",a={[`${r}month`]:12,[`${r}day_of_the_month`]:31,[`${r}day_of_the_week`]:7,[`${r}hour`]:24,[`${r}minute`]:60},h={prefix:r,colKeySizes:a,colKeys:Object.keys(a)};return this._registerIndicator({key:t,order:0,params:[{lag:s,oneHot:i,precompute:h}]}),this}scoreMomentum(e=Q){return o(this),ee(e),this._registerIndicator({key:"scoreMomentum",params:[e]}),this}candleFeatures(e={}){let t="candleFeatures";o(this),n(e,"options",t);const{lag:s=0,colKeys:i=[],retLogs:a=!1}=e;return c(s,{min:0,max:this.len,allowDecimals:!1},"options.lag",t),r(i,"options.colKeys",t),l(a,"retLogs",t),this._registerIndicator({key:t,params:[{lag:s,colKeys:i,retLogs:a}]}),this}}})(),OHLCV_INDICATORS=t.default})();
|
package/index.js
CHANGED
|
@@ -14,6 +14,7 @@ import { assignTypes } from './src/utilities/assignTypes.js'
|
|
|
14
14
|
import { dateOutputFormaters } from './src/utilities/dateUtilities.js'
|
|
15
15
|
import { calcPrecisionMultiplier } from './src/utilities/precisionMultiplier.js'
|
|
16
16
|
import { CONFIG_VERSION, copyConfig, freezeConfig } from './src/utilities/config.js'
|
|
17
|
+
import { DEFAULT_LOOKBACKS, validateScoreMomentumParams } from './src/studies/scoreMomentum.js'
|
|
17
18
|
|
|
18
19
|
/**
|
|
19
20
|
* Class OHLCV_INDICATORS
|
|
@@ -609,6 +610,14 @@ export default class OHLCV_INDICATORS {
|
|
|
609
610
|
return this
|
|
610
611
|
}
|
|
611
612
|
|
|
613
|
+
scoreMomentum(lookbacks = DEFAULT_LOOKBACKS) {
|
|
614
|
+
isAlreadyComputed(this)
|
|
615
|
+
validateScoreMomentumParams(lookbacks)
|
|
616
|
+
|
|
617
|
+
this._registerIndicator({key: 'scoreMomentum', params: [lookbacks]})
|
|
618
|
+
return this
|
|
619
|
+
}
|
|
620
|
+
|
|
612
621
|
candleFeatures(options = {}) {
|
|
613
622
|
let methodName = 'candleFeatures'
|
|
614
623
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ohlcv-indicators",
|
|
3
|
-
"version": "3.5.
|
|
3
|
+
"version": "3.5.86",
|
|
4
4
|
"description": "A JavaScript library featuring optimized trading indicators for OHLCV arrays [{open, high, low, close, value}]. This library is optimized for backtesting and trading bot development.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -22,12 +22,14 @@ import { buildArray } from "../utilities/assignTypes.js";
|
|
|
22
22
|
import { inputNumberFormatter } from "../utilities/numberUtilities.js";
|
|
23
23
|
import { dateFormaters } from "../utilities/dateUtilities.js";
|
|
24
24
|
import { candleFeatures } from "../studies/candleFeatures.js";
|
|
25
|
+
import { scoreMomentum } from "../studies/scoreMomentum.js";
|
|
25
26
|
import { getPrecisionDecimals } from "../utilities/precisionMultiplier.js";
|
|
26
27
|
|
|
27
28
|
|
|
28
29
|
// Map indicator keys to their respective functions
|
|
29
30
|
const mainFunctions = {
|
|
30
31
|
candleFeatures,
|
|
32
|
+
scoreMomentum,
|
|
31
33
|
dateTime,
|
|
32
34
|
heikenAshi,
|
|
33
35
|
rsi,
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { initializeColumns } from '../core-functions/initializeColumns.js';
|
|
2
|
+
import { copyConfig } from '../utilities/config.js';
|
|
3
|
+
import { mathLog } from '../utilities/math.js';
|
|
4
|
+
import { validateInputValues } from '../utilities/validators.js';
|
|
5
|
+
|
|
6
|
+
export const DEFAULT_LOOKBACKS = Object.freeze([
|
|
7
|
+
Object.freeze({ sessions: 21, weight: 0.10 }),
|
|
8
|
+
Object.freeze({ sessions: 63, weight: 0.30 }),
|
|
9
|
+
Object.freeze({ sessions: 126, weight: 0.40 }),
|
|
10
|
+
Object.freeze({ sessions: 252, weight: 0.20 })
|
|
11
|
+
]);
|
|
12
|
+
|
|
13
|
+
const MIN_WEIGHT = 0.1;
|
|
14
|
+
const MAX_WEIGHT = 1;
|
|
15
|
+
const MAX_WEIGHT_SUM = 1;
|
|
16
|
+
const EPSILON = 1e-9;
|
|
17
|
+
const scoreMomentumStates = Symbol('scoreMomentumStates');
|
|
18
|
+
|
|
19
|
+
// Shared by public registration and row-zero initialization for config replay.
|
|
20
|
+
export const validateScoreMomentumParams = lookbacks => {
|
|
21
|
+
copyConfig(lookbacks);
|
|
22
|
+
|
|
23
|
+
if (!Array.isArray(lookbacks) || lookbacks.length === 0) {
|
|
24
|
+
throw new TypeError('lookbacks must be a non-empty array.');
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const seenSessions = new Set();
|
|
28
|
+
let weightSum = 0;
|
|
29
|
+
|
|
30
|
+
for (const [index, item] of lookbacks.entries()) {
|
|
31
|
+
if (item === null || typeof item !== 'object' || Array.isArray(item)) {
|
|
32
|
+
throw new TypeError(`lookbacks[${index}] must be an object.`);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const { sessions, weight } = item;
|
|
36
|
+
if (!Number.isInteger(sessions) || sessions < 1) {
|
|
37
|
+
throw new RangeError(`lookbacks[${index}].sessions must be a positive integer, got ${sessions}.`);
|
|
38
|
+
}
|
|
39
|
+
if (seenSessions.has(sessions)) {
|
|
40
|
+
throw new RangeError(`lookbacks[${index}].sessions is duplicated: ${sessions}.`);
|
|
41
|
+
}
|
|
42
|
+
if (typeof weight !== 'number' || !Number.isFinite(weight)) {
|
|
43
|
+
throw new TypeError(`lookbacks[${index}].weight must be a finite number, got ${weight}.`);
|
|
44
|
+
}
|
|
45
|
+
if (weight < MIN_WEIGHT - EPSILON || weight > MAX_WEIGHT + EPSILON) {
|
|
46
|
+
throw new RangeError(`lookbacks[${index}].weight must be between ${MIN_WEIGHT} and ${MAX_WEIGHT}, got ${weight}.`);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
seenSessions.add(sessions);
|
|
50
|
+
weightSum += weight;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (weightSum > MAX_WEIGHT_SUM + EPSILON) {
|
|
54
|
+
throw new RangeError(`The sum of weights must not exceed ${MAX_WEIGHT_SUM}, got ${weightSum}.`);
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
export const scoreMomentum = (main, index, lookbacks = DEFAULT_LOOKBACKS) => {
|
|
59
|
+
const { verticalOhlcv, instances } = main;
|
|
60
|
+
|
|
61
|
+
if (index === 0) {
|
|
62
|
+
validateScoreMomentumParams(lookbacks);
|
|
63
|
+
validateInputValues({ close: true }, verticalOhlcv, index, 'scoreMomentum');
|
|
64
|
+
|
|
65
|
+
let maxSessions = 0;
|
|
66
|
+
for (const { sessions } of lookbacks) maxSessions = Math.max(maxSessions, sessions);
|
|
67
|
+
|
|
68
|
+
const useIndexedKey = main.useFullNames || main.inputParams.filter(job => job.key === 'scoreMomentum').length > 1;
|
|
69
|
+
const suffix = useIndexedKey
|
|
70
|
+
? `_${lookbacks.map(({ sessions, weight }) => `${sessions}_${weight}`).join('_')}` : '';
|
|
71
|
+
const key = `score_momentum${suffix}`;
|
|
72
|
+
|
|
73
|
+
// Allocation rejects duplicate output keys before sharing runtime state.
|
|
74
|
+
initializeColumns(main, [{ key }]);
|
|
75
|
+
if (!instances[scoreMomentumStates]) instances[scoreMomentumStates] = new WeakMap();
|
|
76
|
+
instances[scoreMomentumStates].set(lookbacks, { key, maxSessions });
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const { key, maxSessions } = instances[scoreMomentumStates].get(lookbacks);
|
|
80
|
+
// N sessions compare today's close with index - N, requiring N + 1 rows.
|
|
81
|
+
if (index < maxSessions) return;
|
|
82
|
+
|
|
83
|
+
const closes = verticalOhlcv.close;
|
|
84
|
+
const currentClose = closes[index];
|
|
85
|
+
if (!Number.isFinite(currentClose) || currentClose <= 0) return;
|
|
86
|
+
|
|
87
|
+
let score = 0;
|
|
88
|
+
for (const { sessions, weight } of lookbacks) {
|
|
89
|
+
const previousClose = closes[index - sessions];
|
|
90
|
+
const ratio = currentClose / previousClose;
|
|
91
|
+
// Preserve NaN for invalid inputs and unrepresentable ratios; do not
|
|
92
|
+
// let mathLog's zero/sign handling change the positive-close formula.
|
|
93
|
+
if (!Number.isFinite(previousClose) || previousClose <= 0 || !Number.isFinite(ratio) || ratio <= 0) return;
|
|
94
|
+
score += weight * mathLog(currentClose, previousClose);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
if (Number.isFinite(score)) main.pushToMain({ index, key, value: score });
|
|
98
|
+
};
|