123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934 |
- /*
- copyright (c) 2018 jones
- http://www.apache.org/licenses/LICENSE-2.0
- 开源项目 https://github.com/jones2000/HQChart
- jones_2000@163.com
- 指标计算方法 2.0 版本使用的算法
- */
- function HQIndexFormula()
- {
- }
- //指数平均数指标 EMA(close,10)
- HQIndexFormula.EMA=function(data,dayCount)
- {
- var result = [];
- var offset=0;
- if (offset>=data.length) return result;
- //取首个有效数据
- for(;offset<data.length;++offset)
- {
- if (data[offset]!=null && !isNaN(data[offset]))
- break;
- }
- var p1Index=offset;
- var p2Index=offset+1;
- result[p1Index]=data[p1Index];
- for(var i=offset+1;i<data.length;++i,++p1Index,++p2Index)
- {
- result[p2Index]=((2*data[p2Index]+(dayCount-1)*result[p1Index]))/(dayCount+1);
- }
- return result;
- }
- HQIndexFormula.SMA=function(data,n,m)
- {
- var result = [];
- var i=0;
- var lastData=null;
- for(;i<data.length; ++i)
- {
- if (data[i]==null || isNaN(data[i])) continue;
- lastData=data[i];
- result[i]=lastData; //第一天的数据
- break;
- }
- for(++i;i<data.length;++i)
- {
- result[i]=(m*data[i]+(n-m)*lastData)/n;
- lastData=result[i];
- }
- return result;
- }
- /*
- 求动态移动平均.
- 用法: DMA(X,A),求X的动态移动平均.
- 算法: 若Y=DMA(X,A)则 Y=A*X+(1-A)*Y',其中Y'表示上一周期Y值,A必须小于1.
- 例如:DMA(CLOSE,VOL/CAPITAL)表示求以换手率作平滑因子的平均价
- */
- HQIndexFormula.DMA=function(data,data2)
- {
- var result = [];
- if (data.length<0 || data.length!=data2.length) return result;
- var index=0;
- for(;index<data.length;++index)
- {
- if (data[index]!=null && !isNaN(data[index]) && data2[index]!=null && !isNaN(data2[index]))
- {
- result[index]=data[index];
- break;
- }
- }
- for(index=index+1;index<data.length;++index)
- {
- if (data[index]==null || data2[index]==null)
- result[index]=null;
- else
- {
- if (data[index]<1)
- result[index]=(data2[index]*data[index])+(1-data2[index])*result[index-1];
- else
- result[index]= data[index];
- }
- }
- return result;
- }
- HQIndexFormula.HHV=function(data,n)
- {
- var result = [];
- if (n>data.length) return result;
- var max=-10000;
- for(var i=n,j=0;i<data.length;++i,++j)
- {
- if(i<n+max)
- {
- max=data[i]<data[max]?max:i;
- }
- else
- {
- for(j=(max=i-n+1)+1;j<=i;++j)
- {
- if(data[j]>data[max])
- max = j;
- }
- }
- result[i] = data[max];
- }
- return result;
- }
- HQIndexFormula.LLV=function(data,n)
- {
- var result = [];
- if (n>data.length) return result;
- var min=-10000;
- for(var i=n;i<data.length;++i,++j)
- {
- if(i<n+min)
- {
- min=data[i]>data[min]?min:i;
- }
- else
- {
- for(var j=(min=i-n+1)+1;j<=i;++j)
- {
- if(data[j]<data[min])
- min = j;
- }
- }
- result[i] = data[min];
- }
- return result;
- }
- HQIndexFormula.REF=function(data,n)
- {
- var result=[];
- if (data.length<=0) return result;
- if (n>=data.length) return result;
- result=data.slice(0,data.length-n);
- for(var i=0;i<n;++i)
- result.unshift(null);
- return result;
- }
- HQIndexFormula.REFDATE=function(data,n)
- {
- var result=[];
- if (data.length<=0) return result;
- //暂时写死取最后一个
- n=data.length-1;
- for(var i in data)
- {
- result[i]=data[n];
- }
- return result;
- }
- HQIndexFormula.SUM=function(data,n)
- {
- var result=[];
- if (n==0)
- {
- result[0]=data[0];
- for (var i=1; i<data.length; ++i)
- {
- result[i] = result[i-1]+data[i];
- }
- }
- else
- {
- for(var i=n-1,j=0;i<data.length;++i,++j)
- {
- for(var k=0;k<n;++k)
- {
- if (k==0) result[i]=data[k+j];
- else result[i]+=data[k+j];
- }
- }
- }
- return result;
- }
- //两个数组相减
- HQIndexFormula.ARRAY_SUBTRACT=function(data,data2)
- {
- var result=[];
- var IsNumber=typeof(data2)=="number";
- if (IsNumber)
- {
- for(var i in data)
- {
- if (data[i]==null || isNaN(data[i]))
- result[i]=null;
- else
- result[i]=data[i]-data2;
- }
- }
- else
- {
- var count=Math.max(data.length,data2.length)
- for(var i=0;i<count;++i)
- {
- if (i<data.length && i<data2.length)
- {
- if (data[i]==null || data2[i]==null) result[i]=null;
- else result[i]=data[i]-data2[i];
- }
- else
- result[i]=null;
- }
- }
- return result;
- }
- //数组 data>data2比较 返回 0/1 数组
- HQIndexFormula.ARRAY_GT=function(data,data2)
- {
- var result=[];
- var IsNumber=typeof(data2)=="number";
- if (IsNumber)
- {
- for(var i in data)
- {
- result[i]=(data[i]>data2 ? 1:0);
- }
- }
- else
- {
- var count=Math.max(data.length,data2.length)
- for(var i=0;i<count;++i)
- {
- if (i<data.length && i<data2.length)
- result[i]=data[i]>data2[i] ? 1:0;
- else
- result[i]=null;
- }
- }
- return result;
- }
- //数组 data>=data2比较 返回 0/1 数组
- HQIndexFormula.ARRAY_GTE=function(data,data2)
- {
- var result=[];
- var IsNumber=typeof(data2)=="number";
- if (IsNumber)
- {
- for(var i in data)
- {
- result[i]=(data[i]>=data2 ? 1:0);
- }
- }
- else
- {
- var count=Math.max(data.length,data2.length)
- for(var i=0;i<count;++i)
- {
- if (i<data.length && i<data2.length)
- result[i]=data[i]>=data2[i] ? 1:0;
- else
- result[i]=null;
- }
- }
- return result;
- }
- //数组 data<data2比较 返回 0/1 数组
- HQIndexFormula.ARRAY_LT=function(data,data2)
- {
- var result=[];
- var IsNumber=typeof(data2)=="number";
- if (IsNumber)
- {
- for(var i in data)
- {
- result[i]=(data[i]<data2 ? 1:0);
- }
- }
- else
- {
- var count=Math.max(data.length,data2.length)
- for(var i=0;i<count;++i)
- {
- if (i<data.length && i<data2.length)
- result[i]=data[i]<data2[i] ? 1:0;
- else
- result[i]=null;
- }
- }
- return result;
- }
- //数组 data<=data2比较 返回 0/1 数组
- HQIndexFormula.ARRAY_LTE=function(data,data2)
- {
- var result=[];
- var IsNumber=typeof(data2)=="number";
- if (IsNumber)
- {
- for(var i in data)
- {
- result[i]=(data[i]<=data2 ? 1:0);
- }
- }
- else
- {
- var count=Math.max(data.length,data2.length)
- for(var i=0;i<count;++i)
- {
- if (i<data.length && i<data2.length)
- result[i]=data[i]<=data2[i] ? 1:0;
- else
- result[i]=null;
- }
- }
- return result;
- }
- //数组 data==data2比较 返回 0/1 数组
- HQIndexFormula.ARRAY_EQ=function(data,data2)
- {
- var result=[];
- var IsNumber=typeof(data2)=="number";
- if (IsNumber)
- {
- for(var i in data)
- {
- result[i]=(data[i]==data2 ? 1:0);
- }
- }
- else
- {
- var count=Math.max(data.length,data2.length)
- for(var i=0;i<count;++i)
- {
- if (i<data.length && i<data2.length)
- result[i]=(data[i]==data2[i] ? 1:0);
- else
- result[i]=null;
- }
- }
- return result;
- }
- HQIndexFormula.ARRAY_IF=function(data,trueData,falseData)
- {
- var result=[];
- var IsNumber=[typeof(trueData)=="number",typeof(falseData)=="number"];
- for(var i in data)
- {
- if (data[i])
- {
- if (IsNumber[0]) result[i]=trueData;
- else result[i]=trueData[i];
- }
- else
- {
- if (IsNumber[1]) result[i]=falseData;
- else result[i]=falseData[i];
- }
- }
- return result;
- }
- HQIndexFormula.ARRAY_AND=function(data,data2)
- {
- var result=[];
- var IsNumber=typeof(trueData)=="number";
- if (IsNumber)
- {
- for(var i in data)
- {
- result[i]=(data[i] && data2? 1:0);
- }
- }
- else
- {
- var count=Math.max(data.length,data2.length)
- for(var i=0;i<count;++i)
- {
- if (i<data.length && i<data2.length)
- result[i]=(data[i] && data2[i] ? 1:0);
- else
- result[i]=0;
- }
- }
- return result;
- }
- HQIndexFormula.ARRAY_OR=function(data, data2)
- {
- var result=[];
- var IsNumber=typeof(data2)=="number";
- if (IsNumber)
- {
- for(var i in data)
- {
- result[i]=(data[i] || data2? 1:0);
- }
- }
- else
- {
- var count=Math.max(data.length,data2.length)
- for(var i=0;i<count;++i)
- {
- if (i < data.length && data[i])
- {
- result[i] = 1;
- continue;
- }
- if (i < data2.length && data2[i])
- {
- result[i] = 1;
- continue;
- }
- result[i] = 0;
- }
- }
- return result;
- }
- //数组相乘
- //支持多个参数累乘 如:HQIndexFormula.ARRAY_MULTIPLY(data,data2,data3,data3) =data*data2*data3*data4
- HQIndexFormula.ARRAY_MULTIPLY=function(data,data2)
- {
- if (arguments.length==2)
- {
- var result=[];
- var IsNumber=typeof(data2)=="number";
- if (IsNumber)
- {
- for(var i in data)
- {
- if (data[i]==null || isNaN(data[i]))
- result[i]=null;
- else
- result[i]=data[i]*data2;
- }
- }
- else
- {
- var count=Math.max(data.length,data2.length);
- for(var i=0;i<count;++i)
- {
- if (i<data.length && i<data2.length)
- result[i]=data[i]*data2[i];
- else
- result[i]=null;
- }
- }
- return result;
- }
- var result=HQIndexFormula.ARRAY_MULTIPLY(arguments[0],arguments[1]);
- for(var i=2;i<arguments.length;++i)
- {
- result=HQIndexFormula.ARRAY_MULTIPLY(result,arguments[i]);
- }
- return result;
- }
- //数组相除
- HQIndexFormula.ARRAY_DIVIDE=function(data,data2)
- {
- var result=[];
- var IsNumber=typeof(data2)=="number";
- if (IsNumber)
- {
- for(var i in data)
- {
- result[i]=data[i]/data2;
- }
- }
- else
- {
- var count=Math.max(data.length,data2.length);
- for(var i=0;i<count;++i)
- {
- if (i<data.length && i<data2.length)
- {
- if(data[i]==null || data2[i]==null || isNaN(data[i]) || isNaN(data2[i]))
- result[i]=null;
- else if (data2[i]==0)
- result[i]=null;
- else
- result[i]=data[i]/data2[i];
- }
- else
- result[i]=null;
- }
- }
- return result;
- }
- //数组相加
- //支持多个参数累加 如:HQIndexFormula.ARRAY_ADD(data,data2,data3,data3) =data+data2+data3+data4
- HQIndexFormula.ARRAY_ADD=function(data,data2)
- {
- if (arguments.length==2)
- {
- var result=[];
- var IsNumber=typeof(data2)=="number";
- if (IsNumber)
- {
- for(var i in data)
- {
- result[i]=data[i]+data2;
- }
- }
- else
- {
- var count=Math.max(data.length,data2.length);
- for(var i=0;i<count;++i)
- {
- if (i<data.length && i<data2.length)
- {
- if (data[i]==null || data2[i]==null || isNaN(data[i]) || isNaN(data2[i])) result[i]=null
- else result[i]=data[i]+data2[i];
- }
- else
- {
- result[i]=null;
- }
- }
- }
- return result;
- }
- var result=HQIndexFormula.ARRAY_ADD(arguments[0],arguments[1]);
- for(var i=2;i<arguments.length;++i)
- {
- result=HQIndexFormula.ARRAY_ADD(result,arguments[i]);
- }
- return result;
- }
- HQIndexFormula.MAX=function(data,data2)
- {
- var result=[];
- var IsNumber=typeof(data2)=="number";
- if (IsNumber)
- {
- for(var i in data)
- {
- if (data[i]==null) result[i]=null;
- else result[i]=Math.max(data[i],data2);
- }
- }
- else
- {
- var count=Math.max(data.length,data2.length);
- for(var i=0;i<count;++i)
- {
- if (i<data.length && i<data2.length)
- {
- if (data[i]==null || data2[i]==null) result[i]=null;
- else result[i]=Math.max(data[i],data2[i]);
- }
- else
- result[i]=null;
- }
- }
- return result;
- }
- HQIndexFormula.MIN=function(data,data2)
- {
- var result=[];
- var IsNumber=typeof(data2)=="number";
- if (IsNumber)
- {
- for(var i in data)
- {
- if (data[i]==null) result[i]=null;
- else result[i]=Math.min(data[i],data2);
- }
- }
- else
- {
- var count=Math.max(data.length,data2.length);
- for(var i=0;i<count;++i)
- {
- if (i<data.length && i<data2.length)
- {
- if (data[i]==null || data2[i]==null) result[i]=null;
- else result[i]=Math.min(data[i],data2[i]);
- }
- else
- result[i]=null;
- }
- }
- return result;
- }
- HQIndexFormula.ABS=function(data)
- {
- var result=[];
- for(var i in data)
- {
- if (data[i]==null) result[i]=null;
- else result[i]=Math.abs(data[i]);
- }
- return result;
- }
- HQIndexFormula.MA=function(data,dayCount)
- {
- var result=[];
- for (var i = 0, len = data.length; i < len; i++)
- {
- if (i < dayCount)
- {
- result[i]=null;
- continue;
- }
- var sum = 0;
- for (var j = 0; j < dayCount; j++)
- {
- sum += data[i - j];
- }
- result[i]=sum / dayCount;
- }
- return result;
- }
- /*
- 加权移动平均
- 返回加权移动平均
- 用法:EXPMA(X,M):X的M日加权移动平均
- EXPMA[i]=buffer[i]*para+(1-para)*EXPMA[i-1] para=2/(1+__para)
- */
- HQIndexFormula.EXPMA=function(data,dayCount)
- {
- var result=[];
- if (dayCount>=data.length) return result;
- var i=dayCount;
- for(;i<data.length;++i) //获取第1个有效数据
- {
- if (data[i]!=null)
- {
- result[i]=data[i];
- break;
- }
- }
- for (i=i+1; i < data.length; ++i)
- {
- if (result[i-1]!=null && data[i]!=null)
- result[i]=(2*data[i]+(dayCount-1)*result[i-1])/(dayCount+1);
- else if (result[i-1]!=null)
- result[i]=result[i-1];
- }
- return result;
- }
- //加权平滑平均,MEMA[i]=SMA[i]*para+(1-para)*SMA[i-1] para=2/(1+__para)
- HQIndexFormula.EXPMEMA=function(data,dayCount)
- {
- var result=[];
- if (dayCount>=data.length) return result;
- var index=0;
- for(;index<data.length;++index)
- {
- if (data[index] && !isNaN(data[index])) break;
- }
- var sum=0;
- for(var i=0; index<data.length && i<dayCount;++i, ++index)
- {
- if (data[index] && !isNaN(data[index]))
- sum+=data[index];
- else
- sum+=data[index-1];
- }
- result[index-1]=sum/dayCount;
- for(;index<data.length;++index)
- {
- if(result[index-1]!=null && data[index]!=null)
- result[index]=(2*data[index]+(dayCount-1)*result[index-1])/(dayCount+1);
- else if(result[index-1]!=null)
- result[index] = result[index-1];
- }
- return result;
- }
- HQIndexFormula.STD=function(data,n)
- {
- var result=[];
- var total=0;
- var averageData=[]; //平均值
- for(var i=n-1;i<data.length;++i)
- {
- total=0;
- for(var j=0;j<n;++j)
- {
- total+=data[i-j];
- }
- averageData[i]=total/n;
- }
- for(var i=n-1;i<data.length;++i)
- {
- total=0;
- for(var j=0;j<n;++j)
- {
- total+=Math.pow((data[i-j]-averageData[i]),2);
- }
- result[i]=Math.sqrt(total/n);
- }
- return result;
- }
- //平均绝对方差
- HQIndexFormula.AVEDEV=function(data,n)
- {
- var result=[];
- var total=0;
- var averageData=[]; //平均值
- for(var i=n-1;i<data.length;++i)
- {
- total=0;
- for(var j=0;j<n;++j)
- {
- total+=data[i-j];
- }
- averageData[i]=total/n;
- }
- for(var i=n-1;i<data.length;++i)
- {
- total=0;
- for(var j=0;j<n;++j)
- {
- total+=Math.abs(data[i-j]-averageData[i]);
- }
- result[i]=total/n;
- }
- return result;
- }
- HQIndexFormula.COUNT=function(data,n)
- {
- var result=[];
- for(var i=n-1;i<data.length;++i)
- {
- var count=0;
- for(var j=0;j<n;++j)
- {
- if (data[i-j]) ++count;
- }
- result[i]=count;
- }
- return result;
- }
- //上穿
- HQIndexFormula.CROSS=function(data,data2)
- {
- var result=[];
- if (data.length!=data2.length) return result=[];
- var index=0;
- for(;index<data.length;++index)
- {
- if (data[index]!=null && !isNaN(data[index]) && data2[index]!=null && isNaN(data2[index]))
- break;
- }
- for(++index;index<data.length;++index)
- {
- result[index]= (data[index]>data2[index]&&data[index-1]<data2[index-1])?1:0;
- }
- return result;
- }
- //累乘
- HQIndexFormula.MULAR=function(data,n)
- {
- var result=[];
- if(data.length<n) return result;
- var index=n;
- for(;index<data.length;++index)
- {
- if (data[index]!=null && !isNaN(data[index]))
- {
- result[index]=data[index];
- break;
- }
- }
- for(++index;index<data.length;++index)
- {
- result[index]=result[index-1]*data[index];
- }
- return result;
- }
- HQIndexFormula.STICKLINE=function(data,price1,price2)
- {
- var result=[];
- if(data.length<=0) return result;
- var IsNumber=typeof(price1)=="number";
- var IsNumber2=typeof(price2)=="number";
- for(var i in data)
- {
- result[i]=null;
- if (isNaN(data[i])) continue;
- if (!data[i]) continue;
- if (IsNumber && IsNumber2)
- {
- result[i]={Value:price1,Value2:price2};
- }
- else if (IsNumber && !IsNumber2)
- {
- if (isNaN(price2[i])) continue;
- result[i]={Value:price1,Value2:price2[i]};
- }
- else if (!IsNumber && IsNumber2)
- {
- if (isNaN(price1[i])) continue;
- result[i]={Value:price1[i],Value2:price2};
- }
- else
- {
- if (isNaN(price1[i]) || isNaN(price2[i])) continue;
- result[i]={Value:price1[i],Value2:price2[i]};
- }
- }
- return result;
- }
- //导出统一使用JSCommon命名空间名
- module.exports =
- {
- //单个类导出
- JSCommon_HQIndexFormula: HQIndexFormula
- };
|