MPAndroidChart的K线图上添加均线

简介: MPAndroidChart的K线图上添加均线效果图 均线计算方法: 通常说的5日均线,10日均线,其实就是根据当前K线节点的时间维度来说的,当前每个节点代表一天,那么上面...

MPAndroidChart的K线图上添加均线

  • 效果图
    这里写图片描述

均线计算方法:

通常说的5日均线,10日均线,其实就是根据当前K线节点的时间维度来说的,当前每个节点代表一天,那么上面的均线就叫做日均线(几日均线),下面就统一说成几节点均线

那么5节点均线,10节点均线等等,是怎么计算出来的呢

5节点均线为例,5节点均线是从第五根柱子开始画,一直画到最后一柱子(10节点均线就是从第10根柱子开始画,画到最后一根)

用第1、2、3、4、5个节点的收盘价之和,算出一个平均值,点在第5个节点上
用第2、3、4、5、6个节点的收盘价之和,算出一个平均值,点在低6个节点上
依此类推……

最后将画在5、6、7、8……上的点连起来,就是5节点均线。(如果当前一个节点代表一天,那这条线就是5日均线)


源码

MPAndroidChart地址:https://github.com/PhilJay/MPAndroidChart

在CandleStickChartRenderer.java下添加画均线的方法

思路:在draw K线柱子的时候获取每个柱子的收盘值,根据收盘值,计算均值

Demo Code

均线的实现,请移步到在MPAndroidChart库K线图的基础上画均线

下面实现的均线是第一版,见效果图,实现逻辑上略有问题,可直接忽略

@Override
public void drawData(Canvas c) {

    CandleData candleData = mChart.getCandleData();

    for (CandleDataSet set : candleData.getDataSets()) {

        if (set.isVisible() && set.getEntryCount() > 0)
            drawDataSet(c, set);
    }
}

protected void drawDataSet(Canvas c, CandleDataSet dataSet) {

    Transformer trans = mChart.getTransformer(dataSet.getAxisDependency());

    float phaseX = mAnimator.getPhaseX();
    float phaseY = mAnimator.getPhaseY();

    int dataSetIndex = mChart.getCandleData().getIndexOfDataSet(dataSet);

    List<CandleEntry> entries = dataSet.getYVals();

    int minx = Math.max(mMinX, 0);
    int maxx = Math.min(mMaxX + 1, entries.size());

    int range = (maxx - minx) * 4;
    int to = (int) Math.ceil((maxx - minx) * phaseX + minx);

    CandleBodyBuffer bodyBuffer = mBodyBuffers[dataSetIndex];
    bodyBuffer.setBodySpace(dataSet.getBodySpace());
    bodyBuffer.setPhases(phaseX, phaseY);
    bodyBuffer.limitFrom(minx);
    bodyBuffer.limitTo(maxx);
    bodyBuffer.feed(entries);

    trans.pointValuesToPixel(bodyBuffer.buffer);

    CandleShadowBuffer shadowBuffer = mShadowBuffers[dataSetIndex];
    shadowBuffer.setPhases(phaseX, phaseY);
    shadowBuffer.limitFrom(minx);
    shadowBuffer.limitTo(maxx);
    shadowBuffer.feed(entries);

    trans.pointValuesToPixel(shadowBuffer.buffer);

    mRenderPaint.setStrokeWidth(dataSet.getShadowWidth());

    ArrayList<Float> closes = new ArrayList<Float>();
    ArrayList<Float> jx = new ArrayList<Float>();
    // draw the body
    for (int j = 0; j < range; j += 4) {

        // get the entry
        CandleEntry e = entries.get(j / 4 + minx);

        if (!fitsBounds(e.getXIndex(), mMinX, to))
            continue;

        if (dataSet.getShadowColorSameAsCandle()) {

            if (e.getOpen() > e.getClose())
                mRenderPaint.setColor(
                        dataSet.getDecreasingColor() == ColorTemplate.COLOR_NONE ?
                                dataSet.getColor(j) :
                                dataSet.getDecreasingColor()
                );

            else if (e.getOpen() < e.getClose())
                mRenderPaint.setColor(
                        dataSet.getIncreasingColor() == ColorTemplate.COLOR_NONE ?
                                dataSet.getColor(j) :
                                dataSet.getIncreasingColor()
                );

            else
                mRenderPaint.setColor(
                        dataSet.getShadowColor() == ColorTemplate.COLOR_NONE ?
                                dataSet.getColor(j) :
                                dataSet.getShadowColor()
                );

        } else {
            mRenderPaint.setColor(
                    dataSet.getShadowColor() == ColorTemplate.COLOR_NONE ?
                            dataSet.getColor(j) :
                            dataSet.getShadowColor()
            );
        }

        mRenderPaint.setStyle(Paint.Style.STROKE);

        // draw the shadow
        c.drawLine(shadowBuffer.buffer[j], shadowBuffer.buffer[j + 1],
                shadowBuffer.buffer[j + 2], shadowBuffer.buffer[j + 3],
                mRenderPaint);

        float leftBody = bodyBuffer.buffer[j];
        float open = bodyBuffer.buffer[j + 1];
        float rightBody = bodyBuffer.buffer[j + 2];
        float close = bodyBuffer.buffer[j + 3];
        closes.add(close);
        jx.add((leftBody + rightBody) / 2);

        // draw body differently for increasing and decreasing entry
        if (open > close) { // decreasing

            if (dataSet.getDecreasingColor() == ColorTemplate.COLOR_NONE) {
                mRenderPaint.setColor(dataSet.getColor(j / 4 + minx));
            } else {
                mRenderPaint.setColor(dataSet.getDecreasingColor());
            }

            mRenderPaint.setStyle(dataSet.getDecreasingPaintStyle());
            // draw the body
            c.drawRect(leftBody, close, rightBody, open, mRenderPaint);

        } else if (open < close) {

            if (dataSet.getIncreasingColor() == ColorTemplate.COLOR_NONE) {
                mRenderPaint.setColor(dataSet.getColor(j / 4 + minx));
            } else {
                mRenderPaint.setColor(dataSet.getIncreasingColor());
            }

            mRenderPaint.setStyle(dataSet.getIncreasingPaintStyle());
            // draw the body
            c.drawRect(leftBody, open, rightBody, close, mRenderPaint);
        } else { // equal values

            mRenderPaint.setColor(dataSet.getShadowColor());
            c.drawLine(leftBody, open, rightBody, close, mRenderPaint);
        }

        // 5节点均线
        drawLine(c, 5, closes, jx);
        // 10节点均线
        drawLine(c, 10, closes, jx);
        // 30节点均线
        drawLine(c, 30, closes, jx);
    }
}

/**
 * 画均线
 * @param c
 * @param i
 * @param closes
 * @param jx
 */
private void drawLine(Canvas c, int i, ArrayList<Float> closes, ArrayList<Float> jx) {
    Paint paint = new Paint();
    // 画线宽度
    paint.setStrokeWidth(1);
    // 画线颜色
    if (5 == i) {
        paint.setColor(Color.BLUE);
    } else if (10 == i) {
        paint.setColor(Color.RED);
    } else if (30 == i) {
        paint.setColor(Color.BLACK);
    } else {
        paint.setColor(Color.GREEN);
    }

    if (closes.size() >= i + 1) {
        float startX = jx.get(closes.size() - 2);
        float startY = 0;
        for (int x = 0; x < i; x++) {
            startY += closes.get(closes.size() - 2 - x);
        }
        startY = startY / i;
        float endX = jx.get(closes.size() - 1);
        float endY = 0;
        for (int y = 0; y < i; y++) {
            endY += closes.get(closes.size() - 1 - y);
        }
        endY = endY / i;
        c.drawLine(startX, startY, endX, endY, paint);
    }
}

图形联动

博客MPAndroidChart图形联动

相关文章
|
机器学习/深度学习
这图怎么画| 相关性热图+柱状图
这图怎么画| 相关性热图+柱状图
130 0
|
2月前
|
数据可视化 数据挖掘 Python
箱线图(Boxplot)
箱线图(Boxplot)
|
2月前
|
数据可视化 数据挖掘 Python
绘制带误差分析的柱状图
【9月更文挑战第1天】在数据分析与科研中,带误差分析的柱状图能直观展示数据分布与不确定性。本文介绍使用Python的Matplotlib库和Excel绘制此类图表的方法,包括安装库、准备数据、绘制图表及添加误差线等步骤,帮助用户根据需求进行调整与定制。
|
数据挖掘
这图怎么画| 箱线图+散点+中位数连线
这图怎么画| 箱线图+散点+中位数连线
130 0
|
数据可视化
R|散点图+边际图(柱形图,小提琴图),颜值区UP
R|散点图+边际图(柱形图,小提琴图),颜值区UP
148 0
|
数据可视化
R|散点图+边际图(柱形图,小提琴图),颜值UP
R|散点图+边际图(柱形图,小提琴图),颜值UP
343 0
|
数据挖掘
ggplot2|从0开始绘制箱线图
ggplot2|从0开始绘制箱线图
167 0
|
算法
对分类数据绘制对应的ROC曲线和AUC面积指标
对分类数据绘制对应的ROC曲线和AUC面积指标
278 0
对分类数据绘制对应的ROC曲线和AUC面积指标
|
数据可视化 数据挖掘 Python
跟着Nature学作图:R语言ggplot2柱形图添加误差线和频率分布直方图
跟着Nature学作图:R语言ggplot2柱形图添加误差线和频率分布直方图
|
数据可视化 数据挖掘 Python
跟着Nature学作图:R语言ggplot2频率分布直方图和散点图添加误差线
跟着Nature学作图:R语言ggplot2频率分布直方图和散点图添加误差线