基于AChartEngine绘制股票走势图----分时图一(走势柱状)

来源:互联网 发布:sql批量insert 编辑:程序博客网 时间:2024/05/01 05:53

概述(项目地址:https://github.com/JiangYueA/android_aps)

使用AChartEngine实现股票分时、五日、k线图,分时图主要有均线,时价的走势和成交量的柱状图,可以使用AChartEngine的CombinedTemperatureChart这个图表类型作为demo,主要是混合Line,Bar这两种图;后期可以加入手势移动显示xy坐标值,实现思路是在GraphicView里面监听onTouchEvent,传递到各个Chart类型的图里面去;
下面先贴上最终要实现的效果图:
这里写图片描述


第一阶段先从简单的分时图开始,主要要考虑的是柱状图和线图数据的处理,AChartEngine支持多图型绘制在同一面板,这样我通过数据的处理把时价线,均价线,成交量柱状图画在同一画布上;

        //数据处理        XYSeries series01 = new XYSeries("Line", 0);//均线        XYSeries series02 = new XYSeries("Line", 0);//时实走势        XYSeries series03 = new XYSeries("RangeBar", 0);//成交量柱状图        //极值        double minValue = 1000000000;        double maxValue = -1000000000;        double minTradeValue = 1000000000;        double maxTradeValue = -1000000000;        //数据填装        for (int i = 0, size = minuteSize; i < size; i++) {            series01.add(i, minuteLine.get(i).cjprice);            series02.add(i, minuteLine.get(i).avprice);            //求最小值            if (minValue > minuteLine.get(i).cjprice) {                minValue = minuteLine.get(i).cjprice;            }            if (minValue > minuteLine.get(i).avprice) {                minValue = minuteLine.get(i).avprice;            }            if (minTradeValue > minuteLine.get(i).cjnum) {                minTradeValue = minuteLine.get(i).cjnum;            }            //求最大值            if (maxValue < minuteLine.get(i).cjprice) {                maxValue = minuteLine.get(i).cjprice;            }            if (maxValue < minuteLine.get(i).avprice) {                maxValue = minuteLine.get(i).avprice;            }            if (maxTradeValue < minuteLine.get(i).cjnum) {                maxTradeValue = minuteLine.get(i).cjnum;            }        }        //重新设置极小值,留涨幅空隙        double temp = maxValue - minValue > minValue ? minValue : maxValue - minValue;        maxValue = maxValue + (temp) * 0.2;        minValue = minValue - (temp) * 0.2;        if (maxValue - entity.shareRtData.dRtPreClose > entity.shareRtData.dRtPreClose - minValue) {            minValue = entity.shareRtData.dRtPreClose - (maxValue - entity.shareRtData.dRtPreClose) * 5 / 7;        } else {            maxValue = entity.shareRtData.dRtPreClose + (entity.shareRtData.dRtPreClose - minValue) * 5 / 7;        }        //获取成交量基数        temp = maxValue - minValue > minValue ? minValue : maxValue - minValue;        double baseTradeValue = 1 / (maxTradeValue - minTradeValue) * (temp) * (0.4 - 0.1);        minValue = minValue - (temp) * 0.4;        //设置成交量柱状图数据        for (int i = 0, size = entity.shareFsDatas.size(); i < size; i++) {            series03.add(i, minValue + (entity.shareFsDatas.get(i).dFsVolume - minTradeValue) * baseTradeValue);        }

均线数据在分钟model的时候已经处理过,AChartEngine绘图有最高最小值,可通过滑分Y轴的数值范围去切割开时价线于成交量柱状图的绘制区间。
解析数据步骤:
- 获取均线和时价线的最大最小值,chart设定y轴的高度,在均线和时价线最大最小值的基础上,留0.4的高度来放置成交量,成交量的值通过与最大最小值的比换算;
- XYSeries值换算坐标点,在XYChart的draw里换算
- 生成的坐标值,传递到对应的图标类型LineChart,BarChart绘制,BarChart有两个坐标,左右,同时需要根据间隔系数获取间隔
坐标换算代码:

synchronized (series) {        SortedMap<Double, Double> range = series.getRange(minX[scale], maxX[scale],            seriesRenderer.isDisplayBoundingPoints());        int startIndex = -1;        for (Entry<Double, Double> value : range.entrySet()) {          double xValue = value.getKey();          double yValue = value.getValue();          if (startIndex < 0 && (!isNullValue(yValue) || isRenderNullValues())) {            startIndex = series.getIndexForKey(xValue);          }          // points.add((float) (left + xPixelsPerUnit[scale]          // * (value.getKey().floatValue() - minX[scale])));          // points.add((float) (bottom - yPixelsPerUnit[scale]          // * (value.getValue().floatValue() - minY[scale])));          values.add(value.getKey());          values.add(value.getValue());          if (!isNullValue(yValue)) {            points.add((float) (left + xPixelsPerUnit[scale] * (xValue - minX[scale])));            points.add((float) (bottom - yPixelsPerUnit[scale] * (yValue - minY[scale])));          } else if (isRenderNullValues()) {            points.add((float) (left + xPixelsPerUnit[scale] * (xValue - minX[scale])));            points.add((float) (bottom - yPixelsPerUnit[scale] * (-minY[scale])));          } else {            if (points.size() > 0) {              drawSeries(series, canvas, paint, points, seriesRenderer, yAxisValue, i, or,                  startIndex);              ClickableArea[] clickableAreasForSubSeries = clickableAreasForPoints(points, values,                  yAxisValue, i, startIndex);              clickableArea.addAll(Arrays.asList(clickableAreasForSubSeries));              points.clear();              values.clear();              startIndex = -1;            }            clickableArea.add(null);          }        }        int count = series.getAnnotationCount();        if (count > 0) {          paint.setColor(seriesRenderer.getAnnotationsColor());          paint.setTextSize(seriesRenderer.getAnnotationsTextSize());          paint.setTextAlign(seriesRenderer.getAnnotationsTextAlign());          Rect bound = new Rect();          for (int j = 0; j < count; j++) {            float xS = (float) (left + xPixelsPerUnit[scale]                * (series.getAnnotationX(j) - minX[scale]));            float yS = (float) (bottom - yPixelsPerUnit[scale]                * (series.getAnnotationY(j) - minY[scale]));            paint.getTextBounds(series.getAnnotationAt(j), 0, series.getAnnotationAt(j).length(),                bound);            if (xS < (xS + bound.width()) && yS < canvas.getHeight()) {              drawString(canvas, series.getAnnotationAt(j), xS, yS, paint);            }          }        }        if (points.size() > 0) {          drawSeries(series, canvas, paint, points, seriesRenderer, yAxisValue, i, or, startIndex);          ClickableArea[] clickableAreasForSubSeries = clickableAreasForPoints(points, values,              yAxisValue, i, startIndex);          clickableArea.addAll(Arrays.asList(clickableAreasForSubSeries));        }      }    }

最后得到的List points既是坐标集合,(ps,在遇到NaN或无效值是会断开计算直接绘制,这种情况,绘制bar会有误差);

0 0
原创粉丝点击