ohlcv-indicators 3.5.82 → 3.5.85
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.
- package/dist/ohlcv-indicators.min.js +1 -1
- package/index.js +21 -0
- package/package.json +1 -1
- package/src/core-functions/mainLoop.js +2 -0
- package/src/oscillators/cmf.js +78 -0
- package/src/oscillators/volumeOscillator.js +3 -0
- package/src/studies/candleFeatures.js +0 -1
- package/src/studies/findCrosses.js +0 -10
|
@@ -1 +1 @@
|
|
|
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:()=>ee});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.")}},r=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.')},o=(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(o(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},h=(e,t,s,i)=>{n(t,"options",`${i}.${s}.validateNumber`);const{allowDecimals:r=!1,min:o,max:a}=t,l=r?"number":"integer";if("number"!=typeof e||!1===r&&!Number.isInteger(e))throw new Error(`Param "${s}" must be an ${l} in "${i}".`);if(void 0!==o&&"number"!=typeof o)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!==o&&void 0!==a&&o>=a)throw new Error(`Param "min" must be less than "max" in "${i}.${s}.validateNumber".`);if(void 0!==o&&e<o)throw new Error(`Param "${s}" must be an ${l} ≥ ${o} in "${i}".`);if(void 0!==a&&e>a)throw new Error(`Param "${s}" must be an ${l} ≤ ${a} in "${i}".`);return!0},c=(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 r=[];for(const i of Object.keys(e)){const e=t[i]?.[s];("volume"===i?Number.isFinite(e)&&e>=0:Number.isFinite(e)&&e>0)||r.push(i)}if(r.length>0)throw new TypeError(`Invalid or missing input value(s) [${r.join(", ")}] at index ${s} in "${i}".`);return!0};class p extends Error{constructor(e="Not enough data"){super(e),this.name="NotEnoughDataError"}}class d{constructor(){this.result=void 0}get isStable(){return void 0!==this.result}getResult(){if(!this.isStable)throw new p;return this.result}}class m extends d{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 m{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 m{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 m{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 m{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 m{constructor(){super(),this.previousCandle=void 0,this.twoPreviousCandle=void 0}update(e,t=!1){const{high:s,low:i}=e,r=s-i;if(this.previousCandle&&t&&(this.previousCandle=this.twoPreviousCandle),this.previousCandle){const o=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(r,o,n),t)}return this.twoPreviousCandle=this.previousCandle,this.previousCandle=e,this.setResult(r,t)}}class b extends m{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 m{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,r=s<0||s<t?0:s;if(this.updateState(e,i,r),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 $ extends m{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 N extends d{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 r=i;if(!r&&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);r=this.count?t/this.count:0}let o=0;s=this.head;for(let e=0;e<this.count;e++){const e=this.prices[s]-r;o+=e*e,++s===this.interval&&(s=0)}const n=Math.sqrt(this.count?o/this.count:0);return this.result={lower:i-n*this.deviationMultiplier,middle:i,upper:i+n*this.deviationMultiplier}}}class k extends d{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,r=this.signal.update(e,t);return this.result={histogram:e-r,macd:e,signal:r}}}}class x extends d{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 r=t-s,o=100*(e.close-s)/(0===r?1:r),n=this.periodM.update(o),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),r=i?e.slice(1):e,[o,n=""]=r.split("."),a=void 0===s?T(t):s,l=n.padEnd(a,"0").slice(0,a);let h=parseInt(o+l||"0",10);return i&&(h=-h),h},S={number:e=>e,numberCleanString:e=>Number(e),precisionNumberCleanString:(e,t,s)=>M(e,t,s)},P=(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 r=Math.abs(e);r=Math.trunc(r);const o=void 0===s?T(t):s;if(0===o)return i?-r:r;const n=Math.trunc(r/t);let a=String(r%t).padStart(o,"0");a=a.replace(/0+$/,"");const l=0===a.length?String(n):`${n}.${a}`;return Number(i?`-${l}`:l)})(e,t,s),C=(e,t=!1,s=!1)=>{const i="number"==typeof e&&!Number.isNaN(e),r="string"==typeof e&&/^-?\d+(\.\d+)?$/.test(e);if(!0===s){if(r)return"precisionNumberCleanString";if(t)throw new Error("Invalid number forma");return typeof e}if(i)return"number";if(r)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},F={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+)?$/,r=/^\d{4}-\d{2}-\d{2}$/,o=/^\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||o.test(e))return"dateCompleteDateString";if(r.test(e))return"dateIncompleteDayString";a()}else a()}},L=(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 r;return r=void 0!==s?s:"Array"===e?null:NaN,new i(t).fill(r)},I=(e,t,{lag:s=0}={})=>{const i=[],r=[];for(const{key:s,type:o="Float64Array",fill:n,enabled:a=!0,priceBased:l=!1,includeInLag:h=!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(o)&&void 0===n)throw new Error(`Integer output column "${s}" requires an explicit fill value.`);e.verticalOhlcv[s]=L(o,e.len,n),l&&e.priceBased.add(s),i.push(s),h&&r.push(s)}return s>0&&r.length>0&&(h(s,{min:1,max:e.len},"lag","initializeColumns"),e.executionParams.push({key:"lag",params:[r,s]})),i},E=e=>null==e||!Number.isFinite(e),R={ema:g,sma:f},j=(e,t,s,i,{target:r,lag:o,retLogs:n=!1})=>{const{verticalOhlcv:a,instances:l,priceBased:h}=e,c=`${n?"ret_log_":""}${s}_${i}${"close"!==r?`_${r}`:""}`;if(0===t){if(u({[r]:!0},a,t,s),!a.hasOwnProperty(r))throw new Error(`Target property ${r} not found in verticalOhlcv for ${s}.`);l[c]=new R[s](i),I(e,n?[{key:`${c}_distance`,priceBased:!1},{key:`${c}_change`,priceBased:!1}]:[{key:c,priceBased:h.has(r)}],{lag:o})}const p=a[r][t];if(E(p))return;const d=l[c],m=d.isStable?d.getResult():NaN;d.update(p);const g=d.isStable?d.getResult():NaN;if(!E(g))if(n){const s=O(p,g);if(e.pushToMain({index:t,key:`${c}_distance`,value:s}),E(m))return;const i=O(g,m);e.pushToMain({index:t,key:`${c}_change`,value:i})}else e.pushToMain({index:t,key:c,value:g})},H=e=>null==e||!Number.isFinite(e),B=(e,t)=>(e-t)/t,V="close",K=Symbol("lagColumns"),U=(e,t)=>{const s=new Uint8Array(t);return s[e]=1,s},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:s,slow:i,low:r}){let o=this.prevState;this.areHighAndLowUndefined||void 0!==s&&void 0!==r||(this.areHighAndLowUndefined=!0),Number.isNaN(t)||Number.isNaN(i)||((e,t)=>e===t)(t,i)?o=.5:z(t,i)?o=this.areHighAndLowUndefined?1:[r,i,this.prevLow,this.prevSlow].every(e=>!Number.isNaN(e))&&Z(r,i)&&z(this.prevLow,this.prevSlow)?0:1:Z(t,i)&&(o=this.areHighAndLowUndefined?0:[s,i,this.prevHigh,this.prevSlow].every(e=>!Number.isNaN(e))&&z(s,i)&&Z(this.prevHigh,this.prevSlow)?1:0),.5===o?this.interval=0:1===o?this.prevState<=.5?this.interval=1:this.interval++:0===o&&(this.prevState>=.5?this.interval=-1:this.interval--),Object.assign(this,{prevState:o,prevFast:t,prevSlow:i,prevHigh:s,prevLow:r})}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:s,colKeys:i,retLogs:r})=>{const{verticalOhlcv:o,priceBased:n,scaledGroups:a}=e,l=(e,t)=>r?Math.log(e/t):(e-t)/t,h=r?"ret_log_":"ret_";if(0===t){u({open:!0,high:!0,low:!0,close:!0},o,t,"candleFeatures");const r=["change","mid_price_change","upper_wick","lower_wick","gap","body","range"].map(e=>({key:`${h}${e}`}));for(const e of i){if(u({[e]:!0},o,t,"candleFeatures"),!o.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".`);r.push({key:`${h}${e}`})}a.candleFeatures=I(e,r,{lag:s})}const c=o.close[t-1],p=o.open[t-1];if(void 0===c)return;const d=o.open[t],m=o.high[t],g=o.low[t],f=o.close[t],v=(c+p)/2,y=(d+f)/2,w=Math.max(d,f),b=Math.min(d,f),_=l(f,c),$=l(y,v),N=l(m,w),k=l(b,g),x=l(d,c),O=l(f,d),T=l(m,g);if(0===i.length)return e.pushToMain({index:t,key:`${h}change`,value:_}),e.pushToMain({index:t,key:`${h}mid_price_change`,value:$}),e.pushToMain({index:t,key:`${h}upper_wick`,value:N}),e.pushToMain({index:t,key:`${h}lower_wick`,value:k}),e.pushToMain({index:t,key:`${h}gap`,value:x}),e.pushToMain({index:t,key:`${h}body`,value:O}),void e.pushToMain({index:t,key:`${h}range`,value:T});const M={[`${h}change`]:_,[`${h}mid_price_change`]:$,[`${h}upper_wick`]:N,[`${h}lower_wick`]:k,[`${h}gap`]:x,[`${h}body`]:O,[`${h}range`]:T};let S=!1;for(const e of i){const s=o[e][t];if(q(s)){S=!0;break}const i=l(f,s);M[`${h}${e}`]=i}if(!S)for(const[s,i]of Object.entries(M))e.pushToMain({index:t,key:s,value:i})},dateTime:(e,t,{lag:s,oneHot:i,precompute:r})=>{const{instances:o,verticalOhlcv:n}=e,{prefix:a}=r;if(0===t){const{dateType:t}=e;if(!t)throw Error('dateTime method found and invalid "date" in input ohlcv');Object.assign(o,{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:[...r.colKeys,`${a}year`].filter(e=>"one_hot_year"!==e),colKeySizes:{...r.colKeySizes}}});const{colKeys:n}=o.dateTime;I(e,n.map(e=>({key:e,type:i?"Array":"Int16Array",fill:i?null:0})),{lag:s})}const{colKeySizes:l,formatter:h}=o.dateTime,c=n.date[t];let u,p,d,m,g,f;for(const e of h.formatToParts(c))switch(e.type){case"year":u=e.value;break;case"month":p=e.value;break;case"hour":d=e.value;break;case"minute":m=e.value;break;case"weekday":g=e.value;break;case"day":f=e.value}const v=Number(u),y=Number(p)-1,w=Number(d),b=Number(m),_=Y.indexOf(g),$=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:$+1});const N=U(y,l.one_hot_month),k=U(w,l.one_hot_hour),x=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: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:r=0,noSmoothing:o=!1,retLogs:n=!1}={})=>{const{verticalOhlcv:a,instances:l,scaledGroups:h}=e,c=o?"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"],d=["body","upper_wick","lower_wick","range"],m=o?"":`_${s}_${i}`,f=n?"ret_log_":"ret_",v=Object.fromEntries(d.map(e=>[e,`${f}heiken_ashi_${e}${m}`])),y=`heiken_ashi_cross${m}`,w=Object.values(v);l[c]={emaPre:o?null:Object.fromEntries(p.map(e=>[e,new g(s)])),emaPost:o?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:r}),h&&(h.heikenAshi=w)}const p=a.open[t],d=a.high[t],m=a.low[t],f=a.close[t],v=l[c],{crossKey:y,emaPre:w,emaPost:b,getRet:_,outputKeys:$}=v;if(H(p)||H(d)||H(m)||H(f))return;let N,k,x,T;if(null!==w){if(w.open.update(p),w.high.update(d),w.low.update(m),w.close.update(f),!(w.open.isStable&&w.high.isStable&&w.low.isStable&&w.close.isStable))return;N=w.open.getResult(),k=w.high.getResult(),x=w.low.getResult(),T=w.close.getResult()}else N=p,k=d,x=m,T=f;if(H(N)||H(k)||H(x)||H(T))return;const M=(N+k+x+T)/4,S=Number.isNaN(v.prevHaOpen)||Number.isNaN(v.prevHaClose)?(N+T)/2:(v.prevHaOpen+v.prevHaClose)/2,P=Math.max(k,S,M),C=Math.min(x,S,M);let A,F,D,L;if(v.prevHaOpen=S,v.prevHaClose=M,null!==b){if(b.open.update(S),b.high.update(P),b.low.update(C),b.close.update(M),!(b.open.isStable&&b.high.isStable&&b.low.isStable&&b.close.isStable))return;A=b.open.getResult(),F=b.high.getResult(),D=b.low.getResult(),L=b.close.getResult()}else A=S,F=P,D=C,L=M;if(H(A)||H(F)||H(D)||H(L)||A<=0||F<=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>A?1:L<A?-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=A,v.prevSmClose=L;const K=Math.max(A,L),U=Math.min(A,L),z=_(L,A),Z=_(F,K),G=_(U,D),Y=_(F,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,s,{target:i,lag:r,retLogs:o})=>{const{verticalOhlcv:n,instances:a}=e,l="close"===i?"":`_${i}`,h=o?`ret_log_rsi_${s}${l}`:`rsi_${s}${l}`,c=o?`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,{[h]:new y(s),[c]:new f(s)}),I(e,[{key:h},{key:c}],{lag:r})}const p=n[i][t];a[h].update(p);const d=a[h].isStable?a[h].getResult():NaN,m=Number.isNaN(d)?NaN:o?O(d,50):d;e.pushToMain({index:t,key:h,value:m}),Number.isNaN(d)||a[c].update(d);const g=a[c].isStable?a[c].getResult():NaN,v=Number.isNaN(g)?NaN:o?O(g,50):g;e.pushToMain({index:t,key:c,value:v})},mfi:(e,t,s,{lag:i,retLogs:r})=>{const{verticalOhlcv:o,instances:n}=e,a=`${r?"ret_log_":""}mfi_${s}`;0===t&&(u({high:!0,low:!0,close:!0,volume:!0},o,t,"mfi"),I(e,[{key:a}],{lag:i}),n[a]={flows:new Float64Array(s),next:0,count:0,previousTypical:NaN});const l=n[a],h=(o.high[t]+o.low[t]+o.close[t])/3,c=h-l.previousTypical;if(l.previousTypical=h,0===t)return;const p=h*o.volume[t];if(l.flows[l.next]=Number.isFinite(c)&&Number.isFinite(p)&&p>=0?Math.sign(c)*p:NaN,l.next=(l.next+1)%s,l.count<s&&l.count++,l.count<s)return;let d=0,m=0,g=l.next;for(let e=0;e<s;e++){const e=l.flows[g];if(Number.isNaN(e))return;e>0?d+=e:e<0&&(m-=e),++g===s&&(g=0)}if(!Number.isFinite(d)||!Number.isFinite(m))return;const f=0===d&&0===m?NaN:100-100/(1+d/m);e.pushToMain({index:t,key:a,value:Number.isNaN(f)?NaN:r?O(f,50):f})},stochastic:(e,t,s,i,r,{lag:o,retLogs:n})=>{const{verticalOhlcv:a,instances:l,useFullNames:h}=e,c=14!==s||3!==i||3!==r||h?`_${s}_${i}_${r}`:"",p=n?`ret_log_stochastic_d${c}`:`stochastic_d${c}`,d=n?`ret_log_stochastic_k${c}`:`stochastic_k${c}`,m=c;0===t&&(u({high:!0,low:!0,close:!0},a,t,"stochastic"),Object.assign(l,{[m]:new x(s,i,r)}),I(e,[{key:p},{key:d}],{lag:o}));const g=a.close[t],f=a.low[t],v=a.high[t];l[m].update({close:g,low:f,high:v});const y=l[m].isStable?l[m].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:d,value:w}),e.pushToMain({index:t,key:p,value:b})},atr:(e,t,s,{lag:i,retLogs:r})=>{const{verticalOhlcv:o,instances:n}=e,a=r?`ret_log_atr_${s}`:`atr_${s}`;if(0===t){const{instances:o,verticalOhlcv:n}=e;u({high:!0,low:!0,close:!0},n,t,"atr"),o[a]=new b(s,v),I(e,[{key:a,priceBased:!r}],{lag:i})}const l={high:o.high[t],low:o.low[t],close:o.close[t]},h=n[a];h.update(l);const c=h.isStable?h.getResult():NaN;e.pushToMain({index:t,key:a,value:Number.isNaN(c)?NaN:r?O(c,l.close):c})},adx:(e,t,s,{lag:i,retLogs:r})=>{const{verticalOhlcv:o,instances:n,useFullNames:a}=e,l=r?`ret_log_adx_${s}`:`adx_${s}`,h=`adx_${s}`;if(0===t){if(u({high:!0,low:!0,close:!0},o,t,"adx"),!o.hasOwnProperty("high"))throw new Error("Property high not found in verticalOhlcv for adx.");if(!o.hasOwnProperty("low"))throw new Error("Property low not found in verticalOhlcv for adx.");if(!o.hasOwnProperty("close"))throw new Error("Property close not found in verticalOhlcv for adx.");Object.assign(n,{[h]:new $(s)}),I(e,[{key:l}],{lag:i})}const c=o.high[t],p=o.low[t],d=o.close[t];n[h].update({high:c,low:p,close:d});const m=n[h].isStable?n[h].getResult():NaN,g=Number.isNaN(m)?NaN:r?O(m,20):m;e.pushToMain({index:t,key:l,value:g})},ema:j,sma:j,macd:(e,t,s,i,r,{target:o,lag:n,precomputed:a})=>{const{verticalOhlcv:l,instances:h,useFullNames:c}=e,{instanceKey:p}=a;if(0===t){u({[o]:!0},l,t,"macd");const{inputParams:a}=e;if(!l.hasOwnProperty(o))throw new Error(`Target property ${o} not found in verticalOhlcv for macd.`);let d=0;for(const e of a)"macd"===e.key&&d++;const m=d>1||c,f=`${s}_${i}_${r}`,v=e=>o===V?m?`macd_${e}_${f}`:`macd_${e}`:m?`macd_${e}_${o}_${f}`:`macd_${e}_${o}`,y=v("diff"),w=v("dea"),b=v("histogram");h.hasOwnProperty("macd")||(h.macd={numberOfIndicators:d,settings:{}}),h.macd.settings[p]=new k(new g(s),new g(i),new g(r)),I(e,[y,w,b].map(e=>({key:e,priceBased:!0})),{lag:n})}const{numberOfIndicators:d,settings:m}=h.macd,f=d>1||c,v=`${s}_${i}_${r}`,y=e=>o===V?f?`macd_${e}_${v}`:`macd_${e}`:f?`macd_${e}_${o}_${v}`:`macd_${e}_${o}`,w=y("diff"),b=y("dea"),_=y("histogram"),$=m[p],N=l[o][t];$.update(N);const x=$.isStable?$.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:r}=e,o="volume_delta";0===t&&(u({open:!0,close:!0,volume:!0},i,t,"volumeDelta"),r[o]||(r[o]={isBuyVolume:!0,cross:0}),I(e,[`${o}_high`,`${o}_low`,`${o}_close`,`${o}_cross`].map(e=>({key:e})),{lag:s}));const n=r[o],{hasInvalidInputValue:a}=n,l=i.volume[t];if(0===l)return;const h=i.open[t],c=i.close[t],p=t>0?i.close[t-1]:NaN;let d=n.isBuyVolume;c>h?d=!0:c<h?d=!1:c>p?d=!0:c<p&&(d=!1),n.isBuyVolume=d,t<1?n.cross=d?1:-1:d?n.cross>0?n.cross=n.cross+1:n.cross=1:n.cross>0?n.cross=-1:n.cross=n.cross-1;const m=d?l:-l,g=m,f=Math.max(m,0),v=Math.min(m,0);e.pushToMain({index:t,key:`${o}_high`,value:f}),e.pushToMain({index:t,key:`${o}_low`,value:v}),e.pushToMain({index:t,key:`${o}_close`,value:g}),e.pushToMain({index:t,key:`${o}_cross`,value:n.cross})},relativeVolume:(e,t,s,{lag:i,retLogs:r=!1})=>{const o=`${r?"ret_log_":""}relative_volume_${s}`,{instances:n,verticalOhlcv:a}=e;0===t&&(u({volume:!0},a,t,"relativeVolume"),n[o]={instance:new f(s),prevRelativeVolumeSma:NaN},I(e,[{key:o}],{lag:i}));const l=a.volume[t];if(0===l)return;const h=n[o].instance;h.update(l);const c=h.isStable?h.getResult():NaN,p=n[o].prevRelativeVolumeSma;if(n[o].prevRelativeVolumeSma=c,Number.isNaN(c)||Number.isNaN(p))return;const d=l/p,m=r?l>0&&p>0&&d>0&&Number.isFinite(d)?O(d,1):NaN:d;e.pushToMain({index:t,key:o,value:m})},donchianChannels:(e,t,s,i,r)=>{const{verticalOhlcv:o,instances:n,len:a,inputParams:l,useFullNames:h}=e,{lag:c=0,retLogs:p=!1}=r,d=`${s}_${i}`,m=`${p?"ret_log_":""}${d}`,g=(p?"ret_log_":"")+"donchian_channel";if(0===t){u({high:!0,low:!0},o,t,"donchianChannels"),p&&u({close:!0},o,t,"donchianChannels");const s=l.filter(e=>"donchianChannels"===e.key).length,i=s>1||h,r=(p?["width","position"]:["upper","basis","lower"]).map(e=>i?`${g}_${e}_${d}`:`${g}_${e}`);n.donchian_channel||(n.donchian_channel={numberOfIndicators:s,settings:{}}),n.donchian_channel.numberOfIndicators=s,n.donchian_channel.settings[m]={maxDeque:{indices:[],head:0,length:0},minDeque:{indices:[],head:0,length:0}},I(e,r.map(e=>({key:e,priceBased:!p})),{lag:c})}const{numberOfIndicators:f,settings:v}=n.donchian_channel,y=f>1||h,w=e=>y?`${g}_${e}_${d}`:`${g}_${e}`,{maxDeque:b,minDeque:_}=v[m],$=t-i,N=$-s+1;if($<0||$>=a)return;const{high:k,low:x}=o,T=(e,t,i)=>{const{indices:r}=e;for(;e.length&&r[e.head]<N;)e.head=(e.head+1)%s,e.length--;for(;e.length&&i(t[r[(e.head+e.length-1)%s]],t[$]);)e.length--;r[(e.head+e.length)%s]=$,e.length++};if(T(b,k,(e,t)=>e<=t),T(_,x,(e,t)=>e>=t),N<0)return;const M=b.length&&_.length,S=M?k[b.indices[b.head]]:NaN,P=M?x[_.indices[_.head]]:NaN;if(p){let s=NaN,i=NaN;const r=S/P;if(P>0&&S>=P&&Number.isFinite(S)&&Number.isFinite(r)){const e=O(r,1);s=e/2;const n=o.close[t],a=n/P;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 C=M?(S+P)/2:NaN;e.pushToMain({index:t,key:w("upper"),value:S}),e.pushToMain({index:t,key:w("basis"),value:C}),e.pushToMain({index:t,key:w("lower"),value:P})},bollingerBands:(e,t,s,i,{lag:r,retLogs:o=!1}={})=>{const{verticalOhlcv:n,instances:a,useFullNames:l}=e,h=`${s}_${i}`,c=`${o?"ret_log_":""}${h}`,p=(o?"ret_log_":"")+"bollinger_bands",d="close";if(0===t){const{inputParams:n,verticalOhlcv:m,priceBased:g}=e;if(u({[d]:!0},m,t,"bollingerBands"),!(d in m))throw new Error(`bollingerBands could not find target "${d}"`);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[c]=new N(s,i);const v=f>1||l?`_${h}`:"";I(e,(o?[`${p}_width${v}`,`${p}_position${v}`]:[`${p}_upper${v}`,`${p}_middle${v}`,`${p}_lower${v}`]).map(e=>({key:e,priceBased:!o&&g.has(d)})),{lag:r})}const{numberOfIndicators:m}=a.bollinger_bands,g=m>1||l?`_${h}`:"",f=a.bollinger_bands.settings[c],v=n[d][t];f.update(v);const y=f.isStable?f.getResult():null,w=y?.upper??NaN,b=y?.middle??NaN,_=y?.lower??NaN;if(o){let s=NaN,i=NaN;const r=w/_;if(_>0&&w>=_&&Number.isFinite(w)&&Number.isFinite(r)){const e=O(r,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:r,retLogs:o})=>{const{verticalOhlcv:n,instances:a}=e,l=o?`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:r}));const{fastEMA:h,slowEMA:c}=a[l],p=n.volume[t];if(0===p)return;h.update(p),c.update(p);const d=h.isStable?h.getResult():NaN,m=c.isStable?c.getResult():NaN;let f=NaN;Number.isNaN(d)||Number.isNaN(m)||(f=o?O(d,m):100*(d-m)/m,e.pushToMain({index:t,key:l,value:f}))},crossPairs:(e,t,s,{oneHot:i,limit:r})=>{const{verticalOhlcv:o,verticalOhlcvTempCols:n,instances:a,len:l,precision:h,precisionMultiplier:c,priceBased:p}=e;for(const{fast:d,slow:m}of s){const s=`${d}_x_${m}`;if(0===t){if(u({..."price"===d?{high:!0,low:!0,close:!0}:{[d]:!0},..."number"==typeof m?{}:{[m]:!0}},o,t,"crossPairs"),"number"==typeof m){const e=m.toString();n.add(e);const t=h&&("price"===d||p.has(d)),s=t?M(e,c):m,i=m>=-125&&m<=125&&!1===t?"Int8Array":"Float64Array";o[e]=L(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!==r&&r<=125?"Int8Array":"Float64Array",fill:0},{key:`one_hot_${s}`,type:"Array",enabled:i}])}else if(t+1===l){if("price"!==d&&!o.hasOwnProperty(d))throw new Error(`crossPairs invalid param: fast "${d}" not found in "verticalOhlcv": ${JSON.stringify(Object.keys(o))}`);if(!o.hasOwnProperty(m))throw new Error(`crossPairs invalid param: slow "${m}" not found in "verticalOhlcv": ${JSON.stringify(Object.keys(o))}`)}if("price"!==d&&!o.hasOwnProperty(d))return;if(!o.hasOwnProperty(m))return;const{run:g}=a.crossPairs[s];if("price"===d){const e=o.close[t],s=o[m][t];g.update(t,{fast:e,slow:s,high:o.high[t],low:o.low[t]})}else{const e=o[d][t],s=o[m][t];g.update(t,{fast:e,slow:s})}const f=g.getResult(),v=null!==r?Math.min(Math.max(f,-r),r):f;if(e.pushToMain({index:t,key:s,value:v}),i){const i=v+r,o=2*r+1;e.pushToMain({index:t,key:`one_hot_${s}`,value:U(i,o)})}}},lag:(e,t,s,i)=>{const{verticalOhlcv:r,priceBased:o,instances:n}=e;if(0===t){const t=new Map;for(const n of s){if(!r.hasOwnProperty(n))throw new Error(`Lag processing invoked by col "${n}" was not found in "verticalOhlcv".`);const s=o.has(n),a=Array.isArray(r[n])?"Array":"Float64Array",l=[],h=[];for(let e=1;e<=i;e++){const t=`${n}_lag_${e}`;l.push({key:t,type:a,priceBased:s,includeInLag:!1}),h.push(t)}I(e,l),t.set(n,h)}n[K]||(n[K]=new WeakMap),n[K].set(s,t)}const a=n[K]?.get(s);for(const o of s){const s=a?.get(o),n=r[o],l=Array.isArray(n)?null:NaN;for(let r=1;r<=i;r++){const i=s?.[r-1]??`${o}_lag_${r}`,a=t-r,h=a<0||null==n[a]?l:n[a];e.pushToMain({index:t,key:i,value:h})}}}},W=({main:e,skipNull:t=!1,startIndex:s=0,dateFormat:i})=>{const{verticalOhlcv:r,invalidValueIndex:o,len:n,verticalOhlcvKeyNames:a,verticalOhlcvTempCols:l,priceBased:h,precision:c,precisionMultiplier:u}=e;if(0===a.length)return[];const p=c&&"number"==typeof u?T(u):void 0,d=t&&o>=0?o+1:0,m=Math.max(d,s),g=n-m,f=Array.from({length:g},()=>({}));for(const[e,t]of Object.entries(r))if(!l.has(e))if("date"===e){const s=A[i];for(let i=m;i<n;i++)f[i-m][e]=s(t[i])}else if(c&&h.has(e)){const s=P;for(let i=m;i<n;i++){const r=t[i];f[i-m][e]=null==r||Number.isNaN(r)?r:s(r,u,p)}}else for(let s=m;s<n;s++)f[s-m][e]=t[s];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 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=>Q(e,t)):Object.fromEntries(Object.entries(e).map(([e,s])=>[e,Q(s,t)]));return t.delete(e),i},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:s=2e3,config:r={}}){if(null===r||Array.isArray(r)||"object"!=typeof r)throw new TypeError('Constructor "config" must be a plain object.');const n=Q(r),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:d=!1,useFullNames:m=!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"),c(f,"config.dateFormat","constructor"),a(Object.keys(A),f,"config.dateFormat","constructor"),c(y,"config.timeZone","constructor");const w=new Intl.DateTimeFormat("en-US",{timeZone:y}).resolvedOptions().timeZone;if(this.config=Object.freeze({schemaVersion:p,precision:d,useFullNames:m,dateFormat:f,skipNull:v,timeZone:w}),this.timeZone=w,o(e,"input",null!==t?`contructor ${t}`:"constuctor"),0===e.length)throw Error("input OHLCV must not be empty: "+t);h(s,{min:100,max:5e4,allowDecimals:!1},"chunkProcess","constructor"),l(d,"precision","contructor"),l(m,"config.useFullNames","constructor"),this.chunkProcess=s,this.input=[...e],this.len=this.input.length,this.firstRow=this.input[0],this.precision=d,this.useFullNames=m;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 r=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,o=""]=t.split("."),n=Number(s);let a=4;if(0===Math.abs(n)){const e=o.length,t=Math.max(4,e),s=o.search(/[1-9]/);if(-1===s)a=t;else{const e=s+1+5;a=Math.max(t,e)}}const l=10**a;l>r&&(r=l)}return r})(this);const{inputTypes:_,arrayTypes:$}=(e=>{const{firstRow:t,precision:s,initialPriceBased:i}=e,r={},o={},n=new Map;for(const[e,a]of Object.entries(t))if("date"===e)r[e]=D(a),o[e]="Array";else if("volume"===e)r[e]=C(a,!0),o[e]="Float64Array";else if(i.has(e))r[e]=C(a,!0,s),o[e]="Float64Array",n.set(e,r[e]);else{const t=C(a,!1,s);r[e]=t,o[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 o.hasOwnProperty("open")&&o.hasOwnProperty("close")&&(o.mid_price=o.open,r.mid_price=r.open),{inputTypes:r,arrayTypes:o}})(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:s})=>{this.verticalOhlcv[t][e]=s},null!==g?(i(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 r(this),this.inputParams=Object.freeze([...this.inputParams,X(Q(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"),W({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"),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:r,arrayTypes:o,verticalOhlcv:n,verticalOhlcvKeyNames:a,inputTypes:l,chunkProcess:h,precisionMultiplier:c,executionParams:u}=t;i(u,r);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))n[e]=L(o[e],r);const p=Object.entries(l).map(([e,t])=>{const s=S.hasOwnProperty(t);return{key:e,formatter:s?S[t]:F.hasOwnProperty(t)?F[t]:null,numeric:s}}),d="number"==typeof c?T(c):void 0;let m=null;for(let i=0;i<r;i+=h){const o=Math.min(i+h,r);for(let r=i;r<o;r++){const i=e[r];for(const{key:e,formatter:s,numeric:o}of p){const n=i[e];if(void 0===n)continue;const a=null===s?n:o?s(n,c,d):s(n);t.pushToMain({index:r,key:e,value:a})}const o=(n.open[r]+n.close[r])/2;t.pushToMain({index:r,key:"mid_price",value:o});for(const{key:e,params:s}of u)J[e](t,r,...s);e[r]=null,null===m&&(m=Object.values(n)),s(m,r)||(t.invalidValueIndex=r)}}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";r(this),o(e,"arr",s),n(t,"options",s);const{limit:i=null,oneHot:a=!1}=t;null!==i&&h(i,{min:2,max:this.len},"options.limit",s),l(a,"options.oneHot",s);const c=[];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.`);c.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";r(this),o(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 h(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.');r(this),h(e,{min:1,max:this.len,allowDecimals:!1},"size",s),n(t,"options",s);const{lag:i=0,retLogs:o=!1}=t;return h(i,{min:0,max:this.len,allowDecimals:!1},"options.lag",s),l(o,"options.retLogs",s),this._registerIndicator({key:s,order:0,params:[e,{lag:i,retLogs:o}]}),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.');r(this),n(e,"options",t);const{lag:s=0}=e;return h(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";r(this),h(e,{min:1,max:this.len,allowDecimals:!1},"size",s),n(t,"options",s);const{lag:i=0,retLogs:o=!1}=t;return h(i,{min:0,max:this.len,allowDecimals:!1},"options.lag",s),l(o,"options.retLogs",s),this._registerIndicator({key:s,order:0,params:[e,{lag:i,retLogs:o}]}),this}adx(e=14,t={}){const s="adx";r(this),h(e,{min:1,max:this.len,allowDecimals:!1},"size",s),n(t,"options",s);const{lag:i=0,retLogs:o=!1}=t;return h(i,{min:0,max:this.len,allowDecimals:!1},"options.lag",s),l(o,"options.retLogs",s),this._registerIndicator({key:s,order:0,params:[e,{lag:i,retLogs:o}]}),this}ema(e=5,t={}){const s="ema";r(this),h(e,{min:1,max:this.len,allowDecimals:!1},"size",s),n(t,"options",s);const{target:i="close",lag:o=0,retLogs:a=!1}=t;return c(i,"options.target",s),h(o,{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:o,retLogs:a}]}),this}sma(e=5,t={}){const s="sma";r(this),h(e,{min:1,max:this.len,allowDecimals:!1},"size",s),n(t,"options",s);const{target:i="close",lag:o=0,retLogs:a=!1}=t;return c(i,"options.target",s),h(o,{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:o,retLogs:a}]}),this}heikenAshi(e=null,t=null,s={}){const i="heikenAshi";r(this);const o=null===e&&null===t;!1===o&&(h(e,{min:1,max:this.len,allowDecimals:!1},"smoothLength",i),h(t,{min:1,max:this.len,allowDecimals:!1},"afterSmoothLength",i)),n(s,"options",i);const{lag:a=0,retLogs:c=!1}=s;return h(a,{min:0,max:this.len,allowDecimals:!1},"options.lag",i),l(c,"option.retLogs",i),this._registerIndicator({key:i,order:0,params:[e,t,{lag:a,noSmoothing:o,retLogs:c}]}),this}stochastic(e=14,t=3,s=3,i={}){const o="stochastic";r(this);const{len:a}=this;h(e,{min:1,max:a,allowDecimals:!1},"kPeriod",o),h(t,{min:1,max:a,allowDecimals:!1},"kSlowingPeriod",o),h(s,{min:1,max:a,allowDecimals:!1},"dPeriod",o),n(i,"options",o);const{lag:c=0,retLogs:u}=i;return h(c,{min:0,max:a,allowDecimals:!1},"options.lag",o),l(u,"retLogs",o),this._registerIndicator({key:o,params:[e,t,s,{lag:c,retLogs:u}]}),this}macd(e=12,t=26,s=9,i={}){const o="macd";r(this),h(e,{min:1,max:this.len,allowDecimals:!1},"fast",o),h(t,{min:1,max:this.len,allowDecimals:!1},"slow",o),h(s,{min:1,max:this.len,allowDecimals:!1},"signal",o),n(i,"options",o);const{target:a="close",lag:l=0}=i;c(a,"options.target",o),h(l,{min:0,max:this.len,allowDecimals:!1},"options.lag",o);const u={instanceKey:`${e}_${t}_${s}${"close"===a?"":`_${a}`}`};return this._registerIndicator({key:o,params:[e,t,s,{target:a,lag:l,precomputed:u}]}),this}bollingerBands(e=20,t=2,s={}){const i="bollingerBands";r(this),h(e,{min:1,max:this.len,allowDecimals:!1},"size",i),h(t,{min:.01,max:50,allowDecimals:!0},"stdDev",i),n(s,"options",i);const{lag:o=0,retLogs:a=!1}=s;return h(o,{min:0,max:this.len,allowDecimals:!1},"options.lag",i),l(a,"options.retLogs",i),this._registerIndicator({key:i,params:[e,t,{lag:o,retLogs:a}]}),this}rsi(e=14,t={}){const s="rsi";r(this),h(e,{min:1,max:this.len,allowDecimals:!1},"size",s),n(t,"options",s);const{target:i="close",lag:o=0,retLogs:a=!1}=t;return c(i,"options.target",s),h(o,{min:0,max:this.len,allowDecimals:!1},"options.lag",s),l(a,"retLogs",s),this._registerIndicator({key:s,params:[e,{target:i,lag:o,retLogs:a}]}),this}mfi(e=14,t={}){const s="mfi";r(this),h(e,{min:1,max:this.len,allowDecimals:!1},"size",s),n(t,"options",s);const{lag:i=0,retLogs:o=!1}=t;return h(i,{min:0,max:this.len,allowDecimals:!1},"options.lag",s),l(o,"options.retLogs",s),this._registerIndicator({key:s,params:[e,{lag:i,retLogs:o}]}),this}donchianChannels(e=20,t=0,s={}){const i="donchianChannels";r(this),h(e,{min:1,max:this.len,allowDecimals:!1},"size",i),h(t,{min:0,max:this.len,allowDecimals:!1},"offset",i),n(s,"options",i);const{lag:o=0,retLogs:a=!1}=s;return h(o,{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:o,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.');r(this),h(e,{min:1,max:this.len,allowDecimals:!1},"fastsize",i),h(t,{min:e,max:this.len,allowDecimals:!1},"slowsize",i),n(s,"options",i);const{lag:o=0,retLogs:a=!1}=s;return h(o,{min:0,max:this.len,allowDecimals:!1},"options.lag",i),l(a,"retLogs",i),this._registerIndicator({key:i,order:0,params:[e,t,{lag:o,retLogs:a}]}),this}dateTime(e={}){const t="dateTime";r(this),n(e,"options",t);const{lag:s=0,oneHot:i=!1}=e;h(s,{min:0,max:this.len,allowDecimals:!1},"options.lag",t),l(i,"options.oneHot",t);const o=i?"one_hot_":"",a={[`${o}month`]:12,[`${o}day_of_the_month`]:31,[`${o}day_of_the_week`]:7,[`${o}hour`]:24,[`${o}minute`]:60},c={prefix:o,colKeySizes:a,colKeys:Object.keys(a)};return this._registerIndicator({key:t,order:0,params:[{lag:s,oneHot:i,precompute:c}]}),this}candleFeatures(e={}){let t="candleFeatures";r(this),n(e,"options",t);const{lag:s=0,colKeys:i=[],retLogs:a=!1}=e;return h(s,{min:0,max:this.len,allowDecimals:!1},"options.lag",t),o(i,"options.colKeys",t),l(a,"retLogs",t),this._registerIndicator({key:t,params:[{lag:s,colKeys:i,retLogs:a}]}),this}}})(),OHLCV_INDICATORS=t.default})();
|
|
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})();
|
package/index.js
CHANGED
|
@@ -510,6 +510,27 @@ export default class OHLCV_INDICATORS {
|
|
|
510
510
|
return this
|
|
511
511
|
}
|
|
512
512
|
|
|
513
|
+
cmf(size = 20, options = {}) {
|
|
514
|
+
const methodName = 'cmf'
|
|
515
|
+
|
|
516
|
+
if(!this.inputTypes.hasOwnProperty('volume')) {
|
|
517
|
+
throw new Error('If "cmf" is called the input ohlcv must contain valid volume properties.')
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
isAlreadyComputed(this)
|
|
521
|
+
validateNumber(size, {min: 1, max: this.len, allowDecimals: false}, 'size', methodName)
|
|
522
|
+
validateObject(options, 'options', methodName)
|
|
523
|
+
|
|
524
|
+
const unsupportedOption = Object.keys(options).find(key => key !== 'lag')
|
|
525
|
+
if (unsupportedOption) throw new Error(`Unsupported option "${unsupportedOption}" in "cmf"; only "lag" is available.`)
|
|
526
|
+
|
|
527
|
+
const {lag = 0} = options
|
|
528
|
+
validateNumber(lag, {min: 0, max: this.len, allowDecimals: false}, 'options.lag', methodName)
|
|
529
|
+
|
|
530
|
+
this._registerIndicator({key: methodName, params: [size, {lag}]})
|
|
531
|
+
return this
|
|
532
|
+
}
|
|
533
|
+
|
|
513
534
|
donchianChannels(size = 20, offset = 0, options = {}) {
|
|
514
535
|
|
|
515
536
|
const methodName = 'donchianChannels'
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ohlcv-indicators",
|
|
3
|
-
"version": "3.5.
|
|
3
|
+
"version": "3.5.85",
|
|
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",
|
|
@@ -2,6 +2,7 @@ import { areKeyValuesValid } from "./pushToMain.js";
|
|
|
2
2
|
import { validateInputParams } from "../utilities/validators.js";
|
|
3
3
|
import { rsi } from "../oscillators/rsi.js";
|
|
4
4
|
import { mfi } from "../oscillators/mfi.js";
|
|
5
|
+
import { cmf } from "../oscillators/cmf.js";
|
|
5
6
|
import { stochastic } from "../oscillators/stochastic.js";
|
|
6
7
|
import { movingAverages } from "../moving-averages/movingAverages.js";
|
|
7
8
|
import { heikenAshi } from "../moving-averages/heikenAshi.js";
|
|
@@ -31,6 +32,7 @@ const mainFunctions = {
|
|
|
31
32
|
heikenAshi,
|
|
32
33
|
rsi,
|
|
33
34
|
mfi,
|
|
35
|
+
cmf,
|
|
34
36
|
stochastic,
|
|
35
37
|
atr,
|
|
36
38
|
adx,
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { initializeColumns } from '../core-functions/initializeColumns.js';
|
|
2
|
+
import { validateInputValues } from '../utilities/validators.js';
|
|
3
|
+
|
|
4
|
+
export const cmf = (main, index, size, options = {}) => {
|
|
5
|
+
const { verticalOhlcv, instances } = main;
|
|
6
|
+
const { lag = 0 } = options;
|
|
7
|
+
const key = `cmf_${size}`;
|
|
8
|
+
|
|
9
|
+
if (index === 0) {
|
|
10
|
+
// CMF is bounded and already centered on zero. A log ratio has no
|
|
11
|
+
// valid zero reference; a signed log1p changes its magnitudes without
|
|
12
|
+
// a mathematical need before downstream feature scaling.
|
|
13
|
+
const unsupportedOption = Object.keys(options).find(name => name !== 'lag');
|
|
14
|
+
if (unsupportedOption) throw new Error(`Unsupported option "${unsupportedOption}" in "cmf"; only "lag" is available.`);
|
|
15
|
+
|
|
16
|
+
validateInputValues({ high: true, low: true, close: true, volume: true }, verticalOhlcv, index, 'cmf');
|
|
17
|
+
initializeColumns(main, [{ key }], { lag });
|
|
18
|
+
instances[key] = {
|
|
19
|
+
moneyFlowVolumes: new Float64Array(size),
|
|
20
|
+
volumes: new Float64Array(size),
|
|
21
|
+
next: 0,
|
|
22
|
+
count: 0
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const state = instances[key];
|
|
27
|
+
const high = verticalOhlcv.high[index];
|
|
28
|
+
const low = verticalOhlcv.low[index];
|
|
29
|
+
const close = verticalOhlcv.close[index];
|
|
30
|
+
const volume = verticalOhlcv.volume[index];
|
|
31
|
+
const range = high - low;
|
|
32
|
+
|
|
33
|
+
let moneyFlowVolume = NaN;
|
|
34
|
+
let windowVolume = NaN;
|
|
35
|
+
|
|
36
|
+
// Invalid or malformed candles occupy a window slot and keep CMF unavailable
|
|
37
|
+
// until they roll out. A flat candle has a neutral multiplier of zero.
|
|
38
|
+
if (
|
|
39
|
+
Number.isFinite(high) && Number.isFinite(low) && Number.isFinite(close) &&
|
|
40
|
+
Number.isFinite(volume) && volume >= 0 && high >= low &&
|
|
41
|
+
close >= low && close <= high && Number.isFinite(range)
|
|
42
|
+
) {
|
|
43
|
+
const multiplier = range === 0 ? 0 : ((close - low) - (high - close)) / range;
|
|
44
|
+
const flow = multiplier * volume;
|
|
45
|
+
if (Number.isFinite(multiplier) && Number.isFinite(flow)) {
|
|
46
|
+
moneyFlowVolume = flow;
|
|
47
|
+
windowVolume = volume;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
state.moneyFlowVolumes[state.next] = moneyFlowVolume;
|
|
52
|
+
state.volumes[state.next] = windowVolume;
|
|
53
|
+
state.next = (state.next + 1) % size;
|
|
54
|
+
if (state.count < size) state.count++;
|
|
55
|
+
if (state.count < size) return;
|
|
56
|
+
|
|
57
|
+
// Sum in chronological order and retain only this fixed-size window.
|
|
58
|
+
let totalMoneyFlowVolume = 0;
|
|
59
|
+
let totalVolume = 0;
|
|
60
|
+
let slot = state.next;
|
|
61
|
+
for (let step = 0; step < size; step++) {
|
|
62
|
+
const flow = state.moneyFlowVolumes[slot];
|
|
63
|
+
const candleVolume = state.volumes[slot];
|
|
64
|
+
if (!Number.isFinite(flow) || !Number.isFinite(candleVolume)) return;
|
|
65
|
+
totalMoneyFlowVolume += flow;
|
|
66
|
+
totalVolume += candleVolume;
|
|
67
|
+
if (++slot === size) slot = 0;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// A zero-volume window has no defined ratio. A zero CMF from positive
|
|
71
|
+
// volume is valid and remains at the neutral center.
|
|
72
|
+
if (!Number.isFinite(totalMoneyFlowVolume) || !Number.isFinite(totalVolume) || totalVolume === 0) return;
|
|
73
|
+
|
|
74
|
+
const value = totalMoneyFlowVolume / totalVolume;
|
|
75
|
+
if (!Number.isFinite(value)) return;
|
|
76
|
+
|
|
77
|
+
main.pushToMain({ index, key, value });
|
|
78
|
+
};
|
|
@@ -43,6 +43,9 @@ export const volumeOscillator = (main, index, fast, slow, {lag, retLogs}) => {
|
|
|
43
43
|
return;
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
+
// The raw percentage is 100 * (fast / slow - 1). Its log ratio has a
|
|
47
|
+
// natural neutral reference of fast / slow = 1 and handles both signs
|
|
48
|
+
// of the resulting oscillator without logging a signed value.
|
|
46
49
|
volumeOscValue = retLogs
|
|
47
50
|
? mathLog(fastValue, slowValue)
|
|
48
51
|
: 100 * (fastValue - slowValue) / slowValue
|
|
@@ -18,7 +18,6 @@ export const candleFeatures = (main, index, {lag, colKeys, retLogs}) => {
|
|
|
18
18
|
].map(name => ({ key: `${prefix}${name}` }))
|
|
19
19
|
|
|
20
20
|
for(const target of colKeys) {
|
|
21
|
-
validateInputValues({ [target]: true }, verticalOhlcv, index, 'candleFeatures')
|
|
22
21
|
|
|
23
22
|
if(!verticalOhlcv.hasOwnProperty(target)) {
|
|
24
23
|
throw new Error(
|
|
@@ -138,16 +138,6 @@ export const crossPairs = (main, index, crossPairsList, {oneHot, limit}) => {
|
|
|
138
138
|
|
|
139
139
|
if(index === 0)
|
|
140
140
|
{
|
|
141
|
-
validateInputValues(
|
|
142
|
-
{
|
|
143
|
-
...(fast === 'price' ? { high: true, low: true, close: true } : { [fast]: true }),
|
|
144
|
-
...(typeof slow === 'number' ? {} : { [slow]: true })
|
|
145
|
-
},
|
|
146
|
-
verticalOhlcv,
|
|
147
|
-
index,
|
|
148
|
-
'crossPairs'
|
|
149
|
-
)
|
|
150
|
-
|
|
151
141
|
// allow numeric 'slow' as a constant column
|
|
152
142
|
if (typeof slow === 'number') {
|
|
153
143
|
|