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图形联动

相关文章
|
2月前
|
数据可视化 数据挖掘 Python
箱线图(Boxplot)
箱线图(Boxplot)
|
数据挖掘
这图怎么画| 箱线图+散点+中位数连线
这图怎么画| 箱线图+散点+中位数连线
119 0
|
数据挖掘
这图怎么画| 批量小提琴图+箱线图+散点+差异分析
这图怎么画| 批量小提琴图+箱线图+散点+差异分析
294 0
|
数据挖掘
ggplot2|从0开始绘制箱线图
ggplot2|从0开始绘制箱线图
159 0
|
数据可视化
R|散点图+边际图(柱形图,小提琴图),颜值UP
R|散点图+边际图(柱形图,小提琴图),颜值UP
338 0
|
数据可视化
R|散点图+边际图(柱形图,小提琴图),颜值区UP
R|散点图+边际图(柱形图,小提琴图),颜值区UP
143 0
|
数据可视化
R可视化学习(2)--箱线图
箱线图由箱和“须”(whisker)两部分组成。箱的范围是从数据的下四分位数到上四分位数,也就是常说的四分位距(IQR)。箱的中间有一条表示中位数,或者说50%分位数的线。须则是从箱子的边缘出发延伸至1.5倍四分位距内的最远的点。如果图中有超过须的数据点,则其被视为异常值,并以点来表示。如下图使用偏态的数据展示了直方图、密度曲线和箱线图之间的关系。
125 0
|
数据可视化 数据挖掘 Python
跟着Nature学作图:R语言ggplot2柱形图添加误差线和频率分布直方图
跟着Nature学作图:R语言ggplot2柱形图添加误差线和频率分布直方图
|
数据可视化 数据挖掘 Python
跟着Nature学作图:R语言ggplot2频率分布直方图和散点图添加误差线
跟着Nature学作图:R语言ggplot2频率分布直方图和散点图添加误差线
|
数据可视化 数据格式
跟着 Cell 学作图 | 3.箱线图+散点+差异显著性检验
这篇2020年发表在cell上关于新冠的组学文章里面有大量的生信内容。今天带大家复现其中的一个Supplemental Figure:带散点的箱线图。
1521 1
跟着 Cell 学作图 | 3.箱线图+散点+差异显著性检验