先看下最终实现的效果
简单介绍一下,K线图功能方面主要是几个部分:
- 绘图 根据数据源绘制展示在屏幕上的图标,实际上主要就是连线,柱状图,绘制一些文字,有时候会有些圆点或者不规则图形 比较少见。
- 图表操作,一般只有平移,缩放,点选三种。
- 指标操作,包含指标的参数调整,指标切换。
所以这个DEMO从功能上来说,已经是一个“全功能”的K线图了(因为点选实际上非常简单而且随着不同应用业务逻辑变化也比较大,有的需要自由移动有的需要吸附某个指标等等因此,这个K线只是个参考DEMO就不做这个功能了)
因此K线模块主要需要用到的框架功能就是:绘图方法,手势,以及基本的计算,非常简单。
K线相对比较复杂的地方在于:数据安全方面的处理,包含数据访问边界,异常数字的处理和指标计算。在指标计算以及图表操作的过程中非常容易出现错误计算,一旦发生错误,相对来说是比较难以排查的,因此在实际工作的项目中为了大家好合作,对数据层的做好的抽象实际上会花费更长时间。当然这里作为一个DEMO就不考虑那么多了。
接下来一步一步学习一下如何搭建K线
先看一下K线的主要构成 。
蜡烛图:K线本身至少是有一条均线和一个蜡烛图构成的。均线就是当日的成交均价,通常是加权平均值,而蜡烛图就是一天的开盘收盘(实体,粗线柱),最高最低(影线,细线柱)四个数字表示而成。
主要指标:主要指标一般与均价相关因此通常与蜡烛图绘制在一起,这里的主视图辅助指标我在DEMO中提供了一个最基本的MA线,也就是N日均线。指标的参数可以手动调整。
辅助指标:辅助指标一般是综合性指标,参数较多范围比较复杂,有些还会包含柱状图因此一般不与主视图放在一起,最常见的有MACD,KDJ,BOLL等,通常会牵扯到一些平方差,标注差,移动平均值,N日极值等,最终表现方式仍然是柱状,连线等等。难度不高,只是比较费时,DEMO中就不去具体实现了,在底部放了一个表示成交额的柱状图。
因此我们最少最少需要5个数字。开盘,收盘,最高,最低,成交量,通常由服务器给出日均价,DEMO中是假数据,直接用(最高+最低)/2 计算的,实际不会这么做。通常K线的数据中还包含品种,日期等信息。
有了以上几个基本数据后,其他的指标数据几乎都是用以上几个基本数据计算而来的,而且指标存在可调节的参数。因此一个完整的K线模块是需要客户端本地进行计算的。而如果在服务端进行计算则实现可调参数的代价比较高。复杂度甚至高于本地运算。
因此绘制K线的简单流程图如下
处理数据
- 先建立数据模型
class KLineModel {
//原始数据
String info;
double top;
double bottom;
double open;
double close;
double avg;
double vol;
//计算生成
double ma1;
@override
KLineModel({
Key key,this.info
,this.top
,this.bottom
,this.open
,this.close
,this.avg
,this.vol
,this.ma1
});
}
DEMO中没用到诸如品种,日期之类的信息,就建了一个精简的模型。除了包含原始数据以外,添加了一个MA参数用来存储MA的数据,由于通常MA线有三条。这里命名为MA1 。
2. 参数计算方法。
MA代表的是所选数据前N日的均价的简单平均数。
//parmDays:均线周期
void calcuateMa1(int parmDays, List<KLineModel> datalist){
//输入数据安全
if(datalist == null || parmDays == null || parmDays < 1){
return;
}
//循环取应算模型
for(int i = 0 ; i < datalist.length;i++){
KLineModel model = datalist[i];
if(i < parmDays){
//排除应空模型
model.ma1 = null;
}else{
//应算模型
double total = 0;
int unUseableCount = 0;
for(int j = i- (parmDays - 1);j<=i;j++){
//获取前置模型
KLineModel model = datalist[j];
if(model.avg == null){
//排除空值
total+=0;
unUseableCount++;
}else{
total+=model.avg;
}
}
if(parmDays - unUseableCount == 0){
//防止0做分母
model.ma1 = null;
}else{
model.ma1 = total / (parmDays - unUseableCount);}
}
}
}
}
实际上关于数据源的问题到此就结束了,实际工作中只需要扩展模型的属性和相应的计算方法即可接下来我们需要一个容器来存放K线模型。
不过这里我要补充一点内容
从上面MA的计算应该可以看出来,指标计算牵扯到非常多的数组操作,乘除操作等,一个不小心非常容易出错,用例的数据也比较多,因此做安全处理是非常重要的。因此我们可以先大概写一下逻辑,然后根据逻辑画一下流程图然后从图上寻找优化方案和做安全处理的位置。
计算过程如下
循环数组取当前模型->根据参数取前置组->计算前置组->对当前模型赋值