import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.DashPathEffect;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Path;
import android.graphics.PointF;
import android.graphics.Rect;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.animation.AnimationUtils;
import com.dlj.library.util.Log;
import com.dlj.library.util.Utils;
import java.util.Vector;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import static com.kedll.kedelllibrary.utils.StockDateUtil.judgeTDNextDay;
public class KLineChartView extends GridChartView {
    public static final int T_D_TYPE = 18259;  //上海T+D等品种
    /**
     * 接口
     */
    private KLineListener l;
    private OnKLineChartClickListener clickL;// 单击接口
    private OnLoadMoreListener onLoadMoreListener;// 加载更多接口
    private boolean isLoadMore;// 是否加载更多
    /**
     * 数据
     */
    private Vector<KLineData> data;
    /**
     * 左边要显示当前十字光标中心点的数据
     */
    private float leftData;
    /**
     * 对应的时间
     */
    private long date;
    /**
     * 默认上表纬线条数
     */
    private final int DEFAULT_LATITUDE_UP_NUM = 4;
    /**
     * 默认下表纬线条数
     */
    private final int DEFAULT_LATITUDE_DOWN_NUM = 2;
    /**
     * 默认经线条数
     */
    private final int DEFAULT_LONGITUDE_NUM = 3;
    /**
     * 默认上表高度与总高度比例
     */
    private final float DEFAULT_UP_RATIO = 0.75f;
    /**
     * 默认纬线颜色
     */
    private final int DEFAULT_LATITUDE_COLOR = 0xffb7b7b7;
    /**
     * 默认经纬线宽
     */
    private final float DEFAULT_LATLONGWIDTH = 0.8f;
    /**
     * 默认字体大小
     */
    private final float DEFAULT_TEXT_SIZE = 9;
    /**
     * 默认最多显示数
     */
    private final int DEFAULT_CANDLE_NUM = 20 * 3;
    /**
     * 控件高度
     */
    private float viewHeight;
    /**
     * 控件宽度
     */
    private float viewWidth;
    /**
     * 上表纬线条数
     */
    protected int latitudesUpNum = DEFAULT_LATITUDE_UP_NUM;
    /**
     * 下表纬线条数
     */
    protected int latitudesDownNum = DEFAULT_LATITUDE_DOWN_NUM;
    /**
     * 经线条数
     */
    protected int longitudesNum = DEFAULT_LONGITUDE_NUM;
    /**
     * 上表纬线间距
     */
    private float upLatitudesSpacing;
    /**
     * 下表纬线间距
     */
    private float downLatitudesSpacing;
    /**
     * 经线间距
     */
    private float longitudesSpacing;
    /**
     * 上表与下表间距
     */
    private float spacing;
    /**
     * 经、纬线颜色
     */
    private int latLngColor = DEFAULT_LATITUDE_COLOR;
    /**
     * 经纬线宽
     */
    private float latLongWidth = DEFAULT_LATLONGWIDTH;
    /**
     * 字体大小
     */
    private float textSize;
    /**
     * 上表底部
     */
    protected float upChartBottom;
    /**
     * 下表底部
     */
    protected float downChartBottom;
    /**
     * 上表高度
     */
    protected float upChartHeight;
    /**
     * 下表高度
     */
    protected float downChartHeight;
    /**
     * 上表高度与控件高度比
     */
    private float upRatio = DEFAULT_UP_RATIO;
    /**
     * 上表最大数据
     */
    private float upMaxData;
    /**
     * 上表最小数据
     */
    private float upMinData;
    /**
     * 下表最大数据
     */
    private float downMaxData;
    /**
     * 下表最小数据
     */
    private float downMinData;
    /**
     * 上表的尺寸与数据比例
     */
    private float upDataRatio;
    /**
     * 下表的尺寸与数据比例
     */
    private float downDataRatio;
    /**
     * 最多显示数
     */
    private int candleNum = DEFAULT_CANDLE_NUM;
    /**
     * 最多显示数上限
     */
    private int maxCandleNum = DEFAULT_CANDLE_NUM * 4;
    /**
     * 最多显示数下限
     */
    private int minCandleNum = DEFAULT_CANDLE_NUM / 4;
    /**
     * 数据间距
     */
    private float dataSpacing;
    /**
     * 记录当前滚动到的位置
     */
    private int position;
    /**
     * 加载更多的个数
     */
    private int oldSize = 0;
    /**
     * 是否显示十字光标
     */
    private boolean isShowCrossLine;
    /**
     * 主图指标
     */
    private MainIndexType mMainIndexType;
    /**
     * 指标
     */
    private IndexType mIndexType;
    /**
     *
     */
    /**
     * 手势相关
     */
    private float downX;// 按下X坐标
    private float downY;// 按下Y坐标
    private float moveX;// 触摸中的X坐标
    private float moveY;// 触摸中的Y坐标
    private int touchMode;// 触摸模式
    /**
     * 拖拽模式
     */
    private final int TOUCH_DRAG = 1;// 左右滑动模式
    /**
     * 缩放模式
     */
    private final int TOUCH_ZOOM = 2;// 捏合模式
    /**
     * 吸附模式,即长按内容不滚动,仅光标滚动
     */
    private final int TOUCH_ADSORPTION = 3;// 十字光标模式
    // private float oldDistance;// 旧的移动距离
    // private float newDistance;// 新的移动距离
    private Runnable mRunnable;// 长按事件的线程
    private boolean isMoved;// 是否触摸中
    private boolean isReleased;// 手指是否离开屏幕
    private boolean isStartMoved;// 是否可以执行OnTouch中的Move事件了
    // private boolean isLeftRightMoved;// 是否在左右滑动
    // private float distance;// 捏合事件中的捏合距离
    private float crossX;// 十字光标X坐标
    private float crossY;// 十字光标Y坐标
    private ExecutorService executorService = Executors.newCachedThreadPool();
    private NotifyRunnable notifyRunnable = new NotifyRunnable();// 更新数据的线程
    /**
     * 记录多点触摸时中点坐标
     */
    private PointF mTouchPointCenter = new PointF();
    /**
     * 记录触摸时按下的起始坐标
     */
    private PointF mTouchStartPoint = new PointF();
    /**
     * 分别记录触摸时中间坐标索引、触摸时candleNum、触摸时起始索引
     */
    private int mTouchPosition = -1, mTouchCandleNum = 15,
            mTouchStartPosition = 0;
    /**
     * 记录触摸起始x方向两点距离、两点原始距离
     */
    private float mSavedXDist = 1f, mSavedDist = 1f;
    /**
     * 记录快速手势处理过程中,上一次手势的位移
     */
    private float mLastFlingDist = 0;
    /**
     * 快速手势事件检测者
     */
    private VelocityTracker mVelocityTracker;
    /**
     * 减速度运行上一次时间戳
     */
    private long mDecelerationLastTime = 0;
    /**
     * 减速度运行过程中的当前坐标
     */
    private PointF mDecelerationCurrentPoint = new PointF();
    /**
     * 记录减速度运行过程中的位移值
     */
    private PointF mDecelerationVelocity = new PointF();
    /**
     * 设置是否将两边坐标值绘制在边框线外(注:如果设置成true,必须设置strokeLeft和strokeRight)
     */
    private boolean isDrawOutside;
    /**
     * 记录上表各种颜色
     */
    private int[] upColors;
    /**
     * 记录下表各种颜色
     */
    private int[] downColors;
    /**
     * 是否显示小时分钟(true:显示yyyy/MM/dd HH:mm;false:显示yyyy/MM/dd)
     */
    private boolean isShowTime;
    /**
     * 小数保留位数
     */
    private int num = 2;// 默认保留2位
    private Handler handler = new Handler() {
        public void handleMessage(android.os.Message msg) {
            switch (msg.what) {
                case 0x1:
                    data = (Vector<KLineData>) msg.getData().getSerializable(
                            "data");
                    int mainIndex = msg.getData().getInt("mainindex");
                    if(mainIndex == 0){
                        mMainIndexType = MainIndexType.MA;
                    }else if(mainIndex == 1){
                        mMainIndexType = MainIndexType.BOLL;
                    }
                    mIndexType = (IndexType) msg.obj;
                    if (touchMode == 0) {
                        Log.i("KLineChartView", "postInvalidate============" + data.size());
                        postInvalidate();
                    }
                    break;
                default:
                    break;
            }
        }
    };
    /**
     * 主图指标类型
     *
     * @author dingrui
     */
    public enum MainIndexType {
        /**
         * 均线
         */
        MA("MA"),
        /**
         * 布林指标
         */
        BOLL("BOLL");
        private String value;
        private boolean isSelected = false;
        MainIndexType(String value) {
            this.value = value;
        }
        public String getValue() {
            return value;
        }
        public boolean isSelected() {
            return isSelected;
        }
        public void setSelected(boolean selected) {
            isSelected = selected;
        }
    }
    /**
     * 指标类型
     *
     * @author dingrui
     */
    public enum IndexType {
        /**
         * 成交量
         */
        VOL("VOL"),
        /**
         * 指数平滑异同平均线(MACD指标)
         */
        MACD("MACD"),
        /**
         * 随机指标(KDJ)
         */
        KDJ("KDJ"),
        /**
         * 随机指标(KD),同KDJ,只输出KD
         */
        KD("KD"),
        /**
         * 强弱指标
         */
        RSI("RSI"),
        /**
         * 乖离率(BIAS)是测量股价偏离均线大小程度的指标
         */
        BIAS("BIAS"),
        /**
         * 情绪指标(BRAR)也称为人气意愿指标
         */
        BRAR("BRAR"),
        /**
         * 顺势指标
         */
        CCI("CCI"),
        /**
         * 动向指标
         */
        DMI("DMI"),
        /**
         * 能量指标
         */
        CR("CR"),
        /**
         * 心理线(PSY)指标是研究投资者对股市涨跌产生心理波动的情绪指标
         */
        PSY("PSY"),
        /**
         * 平行线差指标
         */
        DMA("DMA"),
        /**
         * 三重指数平滑平均线(TRIX)属于长线指标
         */
        TRIX("TRIX");
        private String value;
        private boolean isSelected = false;
        IndexType(String value) {
            this.value = value;
        }
        public String getValue() {
            return value;
        }
        public boolean isSelected() {
            return isSelected;
        }
        public void setSelected(boolean selected) {
            isSelected = selected;
        }
    }
    public KLineChartView(Context context) {
        super(context);
        // TODO Auto-generated constructor stub
        init();
    }
    public KLineChartView(Context context, AttributeSet attrs) {
        super(context, attrs);
        // TODO Auto-generated constructor stub
        init();
    }
    public KLineChartView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        // TODO Auto-generated constructor stub
        init();
    }
    /**
     * 初始化
     */
    private void init() {
        this.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
        touchMode = 0;
        textSize = MyUtils.getInstance().dp2px(getContext(), DEFAULT_TEXT_SIZE);
        spacing = textSize * 2;
        position = 0;
        isShowCrossLine = false;
        mIndexType = IndexType.VOL;
        mMainIndexType = MainIndexType.MA;
        isDrawOutside = false;
        isLoadMore = true;
        mRunnable = new Runnable() {
            @Override
            public void run() {
                // TODO Auto-generated method stub
                if (isMoved || isReleased)
                    return;
                isStartMoved = true;
                touchMode = TOUCH_ADSORPTION;
            }
        };
    }
    @Override
    protected void onDraw(Canvas canvas) {
        // TODO Auto-generated method stub
        super.onDraw(canvas);
        try {
            viewHeight = getHeight();
            viewWidth = getWidth();
            Log.w("KLineChartView", "viewHeight===" + viewHeight + "   viewWidth=" + viewWidth);
            // 计算上表高度
            upChartHeight = (viewHeight - getStrokeWidth() * 2 - getStrokeTop()
                    - getStrokeBottom() - spacing)
                    * upRatio;
            // 计算上表底部位置
            upChartBottom = upChartHeight + getStrokeWidth() + getStrokeTop();
            // 计算经线间距
            longitudesSpacing = (viewWidth - (getStrokeWidth() * 2
                    + getStrokeLeft() + getStrokeRight()))
                    / (longitudesNum + 1);
            // 计算上表纬线间距
            upLatitudesSpacing = upChartHeight / latitudesUpNum;
            // 计算下表高度
            downChartHeight = (viewHeight - getStrokeWidth() * 2 - getStrokeTop()
                    - getStrokeBottom() - spacing)
                    * (1 - upRatio);
            // 计算下表底部位置
            downChartBottom = viewHeight - getStrokeWidth() - getStrokeBottom();
            // 计算下表纬线间距
            downLatitudesSpacing = downChartHeight / latitudesDownNum;
            // 计算数据(蜡烛)间距
            dataSpacing = (viewWidth - getStrokeWidth() * 2 - getStrokeLeft() - getStrokeRight())
                    / candleNum;
            // 计算上表最大、最小数值
            upMaxData = 0;
            upMinData = 0;
            downMaxData = 0;
            Log.i("KLineChart", "onDraw....viewHeight=" + viewHeight + "  viewWidth=" + viewWidth);
            if (data != null && data.size() > 0 && position < data.size() && position >= 0) {
                upMaxData = (float) data.get(position).getHighPrice();// 最高价
                upMinData = (float) data.get(position).getLowPrice();// 最低价
                for (int i = position; i < data.size() && i < candleNum + position; i++) {
                    upMaxData = upMaxData < (float) data.get(i).getHighPrice() ? (float) data
                            .get(i).getHighPrice() : upMaxData;
                    upMinData = (float) (upMinData < data.get(i).getLowPrice() ? upMinData
                            : data.get(i).getLowPrice());
                    if (mMainIndexType == MainIndexType.BOLL) {
                        if (i >= 25) {
                            upMaxData = upMaxData < (float) data.get(i).getBoll()
                                    .getUpper() ? (float) data.get(i).getBoll()
                                    .getUpper() : upMaxData;
                            upMinData = (float) (upMinData < data.get(i).getBoll()
                                    .getLower() ? upMinData : data.get(i).getBoll()
                                    .getLower());
                        }
                    } else {
                        if (i >= 4) {
                            upMaxData = (float) (upMaxData < data.get(i)
                                    .getDayMovingAverage().getMa5() ? data.get(i)
                                    .getDayMovingAverage().getMa5() : upMaxData);
                            upMinData = (float) (upMinData < data.get(i)
                                    .getDayMovingAverage().getMa5() ? upMinData
                                    : data.get(i).getDayMovingAverage().getMa5());
                            if (i >= 9) {
                                upMaxData = (float) (upMaxData < data.get(i)
                                        .getDayMovingAverage().getMa10() ? data
                                        .get(i).getDayMovingAverage().getMa10()
                                        : upMaxData);
                                upMinData = (float) (upMinData < data.get(i)
                                        .getDayMovingAverage().getMa10() ? upMinData
                                        : data.get(i).getDayMovingAverage()
                                        .getMa10());
                                if (i >= 19) {
                                    upMaxData = (float) (upMaxData < data.get(i)
                                            .getDayMovingAverage().getMa20() ? data
                                            .get(i).getDayMovingAverage().getMa20()
                                            : upMaxData);
                                    upMinData = (float) (upMinData < data.get(i)
                                            .getDayMovingAverage().getMa20() ? upMinData
                                            : data.get(i).getDayMovingAverage()
                                            .getMa20());
                                }
                            }
                        }
                    }
                }
                if (mIndexType == IndexType.VOL ) {
        //        if (mIndexType == IndexType.VOL || mMainIndexType == MainIndexType.BOLL) {
                    // 计算成交量最大、最小
                    downMaxData = (float) data.get(position).getVolume().getNum();
                    downMinData = 0.0f;
                    for (int i = position; i < data.size()
                            && i < candleNum + position; i++) {
                        downMaxData = (float) (downMaxData < data.get(i)
                                .getVolume().getNum() ? data.get(i).getVolume()
                                .getNum() : downMaxData);
                        downMaxData = (float) (downMaxData < data.get(i)
                                .getVolume().getMa5() ? data.get(i).getVolume()
                                .getMa5() : downMaxData);
                        downMaxData = (float) (downMaxData < data.get(i)
                                .getVolume().getMa10() ? data.get(i).getVolume()
                                .getMa10() : downMaxData);
                        downMaxData = (float) (downMaxData < data.get(i)
                                .getVolume().getMa20() ? data.get(i).getVolume()
                                .getMa20() : downMaxData);
                    }
                } else if (mIndexType == IndexType.MACD) {
                    // 计算MACD最大、最小
                    downMaxData = (float) data.get(position).getMacd().getDiff();
                    downMinData = downMaxData;
                    for (int i = position; i < data.size()
                            && i < candleNum + position; i++) {
                        downMaxData = (float) (downMaxData < data.get(i).getMacd()
                                .getDiff() ? data.get(i).getMacd().getDiff()
                                : downMaxData);
                        downMaxData = (float) (downMaxData < data.get(i).getMacd()
                                .getDea() ? data.get(i).getMacd().getDea()
                                : downMaxData);
                        downMaxData = (float) (downMaxData < data.get(i).getMacd()
                                .getMacd() ? data.get(i).getMacd().getMacd()
                                : downMaxData);
                        downMinData = (float) (downMinData > data.get(i).getMacd()
                                .getDiff() ? data.get(i).getMacd().getDiff()
                                : downMinData);
                        downMinData = (float) (downMinData > data.get(i).getMacd()
                                .getDea() ? data.get(i).getMacd().getDea()
                                : downMinData);
                        downMinData = (float) (downMinData > data.get(i).getMacd()
                                .getMacd() ? data.get(i).getMacd().getMacd()
                                : downMinData);
                        if (downMaxData >= 0.0 && downMinData <= 0.0) {
                            if (downMaxData - 0.0f >= 0.0f - downMinData) {
                                downMinData = 0.0f - (downMaxData - 0.0f);
                            } else {
                                downMaxData = 0.0f + (0.0f - downMinData);
                            }
                        } else if (downMaxData >= 0.0f && downMinData >= 0.0f) {
                            downMinData = 0.0f - (downMaxData - 0.0f);
                        } else {
                            downMaxData = 0.0f + (0.0f - downMinData);
                        }
                    }
                    float upSpacing = Math.abs(downMaxData - 0.0f);
                    float downSpacing = Math.abs(downMinData - 0.0f);
                    if (upSpacing > downSpacing) {
                        downMinData = 0.0f - upSpacing;
                    } else {
                        downMaxData = downSpacing + 0.0f;
                    }
                }
                // else if (mIndexType == IndexType.BOLL) {
                // // 计算布林最大、最小
                // downMaxData = (float) data.get(position).getBoll().getUpper();
                // downMinData = (float) data.get(position).getBoll().getLower();
                // for (int i = position; i < data.size()
                // && i < candleNum + position; i++) {
                // downMaxData = (float) (downMaxData < data.get(i).getBoll()
                // .getUpper() ? data.get(i).getBoll().getUpper()
                // : downMaxData);
                //
                // downMinData = (float) (downMinData > data.get(i).getBoll()
                // .getLower() ? data.get(i).getBoll().getLower()
                // : downMinData);
                // }
                // }
                else if (mIndexType == IndexType.KDJ || mIndexType == IndexType.KD) {
                    // 计算KDJ、KD最大、最小
                    downMaxData = (float) data.get(position).getKdj().getK();
                    downMinData = downMaxData;
                    for (int i = position; i < data.size()
                            && i < candleNum + position; i++) {
                        downMaxData = (float) (downMaxData < data.get(i).getKdj()
                                .getK() ? data.get(i).getKdj().getK() : downMaxData);
                        downMaxData = (float) (downMaxData < data.get(i).getKdj()
                                .getD() ? data.get(i).getKdj().getD() : downMaxData);
                        downMinData = (float) (downMinData > data.get(i).getKdj()
                                .getK() ? data.get(i).getKdj().getK() : downMinData);
                        downMinData = (float) (downMinData > data.get(i).getKdj()
                                .getD() ? data.get(i).getKdj().getD() : downMinData);
                        if (mIndexType != IndexType.KD) {
                            downMaxData = (float) (downMaxData < data.get(i)
                                    .getKdj().getJ() ? data.get(i).getKdj().getJ()
                                    : downMaxData);
                            downMinData = (float) (downMinData > data.get(i)
                                    .getKdj().getJ() ? data.get(i).getKdj().getJ()
                                    : downMinData);
                        }
                    }
                } else if (mIndexType == IndexType.RSI) {
                    // 计算RSI最大、最小
                    downMaxData = (float) data.get(position).getRsi().getRsi6();
                    downMinData = downMaxData;
                    for (int i = position; i < data.size()
                            && i < candleNum + position; i++) {
                        downMaxData = (float) (downMaxData < data.get(i).getRsi()
                                .getRsi6() ? data.get(i).getRsi().getRsi6()
                                : downMaxData);
                        downMaxData = (float) (downMaxData < data.get(i).getRsi()
                                .getRsi12() ? data.get(i).getRsi().getRsi12()
                                : downMaxData);
                        downMaxData = (float) (downMaxData < data.get(i).getRsi()
                                .getRsi24() ? data.get(i).getRsi().getRsi24()
                                : downMaxData);
                        downMinData = (float) (downMinData > data.get(i).getRsi()
                                .getRsi6() ? data.get(i).getRsi().getRsi6()
                                : downMinData);
                        downMinData = (float) (downMinData > data.get(i).getRsi()
                                .getRsi12() ? data.get(i).getRsi().getRsi12()
                                : downMinData);
                        downMinData = (float) (downMinData > data.get(i).getRsi()
                                .getRsi24() ? data.get(i).getRsi().getRsi24()
                                : downMinData);
                    }
                } else if (mIndexType == IndexType.BIAS) {
                    // 计算BIAS最大、最小
                    downMaxData = (float) data.get(position).getBias().getBias1();
                    downMinData = downMaxData;
                    for (int i = position; i < data.size()
                            && i < candleNum + position; i++) {
                        downMaxData = (float) (downMaxData < data.get(i).getBias()
                                .getBias1() ? data.get(i).getBias().getBias1()
                                : downMaxData);
                        downMaxData = (float) (downMaxData < data.get(i).getBias()
                                .getBias2() ? data.get(i).getBias().getBias2()
                                : downMaxData);
                        downMaxData = (float) (downMaxData < data.get(i).getBias()
                                .getBias3() ? data.get(i).getBias().getBias3()
                                : downMaxData);
                        downMinData = (float) (downMinData > data.get(i).getBias()
                                .getBias1() ? data.get(i).getBias().getBias1()
                                : downMinData);
                        downMinData = (float) (downMinData > data.get(i).getBias()
                                .getBias2() ? data.get(i).getBias().getBias2()
                                : downMinData);
                        downMinData = (float) (downMinData > data.get(i).getBias()
                                .getBias3() ? data.get(i).getBias().getBias3()
                                : downMinData);
                    }
                } else if (mIndexType == IndexType.BRAR) {
                    // 计算BRAR最大、最小
                    downMaxData = (float) data.get(position).getBrar().getBr();
                    downMinData = downMaxData;
                    for (int i = position; i < data.size()
                            && i < candleNum + position; i++) {
                        downMaxData = (float) (downMaxData < data.get(i).getBrar()
                                .getBr() ? data.get(i).getBrar().getBr()
                                : downMaxData);
                        downMaxData = (float) (downMaxData < data.get(i).getBrar()
                                .getAr() ? data.get(i).getBrar().getAr()
                                : downMaxData);
                        downMinData = (float) (downMinData > data.get(i).getBrar()
                                .getBr() ? data.get(i).getBrar().getBr()
                                : downMinData);
                        downMinData = (float) (downMinData > data.get(i).getBrar()
                                .getAr() ? data.get(i).getBrar().getAr()
                                : downMinData);
                    }
                } else if (mIndexType == IndexType.CCI) {
                    // 计算CCI最大、最小
                    downMaxData = (float) data.get(position).getCci().getCci();
                    downMinData = downMaxData;
                    for (int i = position; i < data.size()
                            && i < candleNum + position; i++) {
                        downMaxData = (float) (downMaxData < data.get(i).getCci()
                                .getCci() ? data.get(i).getCci().getCci()
                                : downMaxData);
                        downMinData = (float) (downMinData > data.get(i).getCci()
                                .getCci() ? data.get(i).getCci().getCci()
                                : downMinData);
                    }
                } else if (mIndexType == IndexType.DMI) {
                    // 计算DMI最大、最小
                    downMaxData = (float) data.get(position).getDmi().getPdi();
                    downMinData = downMaxData;
                    for (int i = position; i < data.size()
                            && i < candleNum + position; i++) {
                        downMaxData = (float) (downMaxData < data.get(i).getDmi()
                                .getPdi() ? data.get(i).getDmi().getPdi()
                                : downMaxData);
                        downMaxData = (float) (downMaxData < data.get(i).getDmi()
                                .getMdi() ? data.get(i).getDmi().getMdi()
                                : downMaxData);
                        downMaxData = (float) (downMaxData < data.get(i).getDmi()
                                .getAdx() ? data.get(i).getDmi().getAdx()
                                : downMaxData);
                        downMaxData = (float) (downMaxData < data.get(i).getDmi()
                                .getAdxr() ? data.get(i).getDmi().getAdxr()
                                : downMaxData);
                        downMinData = (float) (downMinData > data.get(i).getDmi()
                                .getPdi() ? data.get(i).getDmi().getPdi()
                                : downMinData);
                        downMinData = (float) (downMinData > data.get(i).getDmi()
                                .getMdi() ? data.get(i).getDmi().getMdi()
                                : downMinData);
                        downMinData = (float) (downMinData > data.get(i).getDmi()
                                .getAdx() ? data.get(i).getDmi().getAdx()
                                : downMinData);
                        downMinData = (float) (downMinData > data.get(i).getDmi()
                                .getAdxr() ? data.get(i).getDmi().getAdxr()
                                : downMinData);
                    }
                } else if (mIndexType == IndexType.CR) {
                    // 计算CR最大、最小
                    downMaxData = (float) data.get(position).getCr().getCr();
                    downMinData = downMaxData;
                    for (int i = position; i < data.size()
                            && i < candleNum + position; i++) {
                        downMaxData = (float) (downMaxData < data.get(i).getCr()
                                .getCr() ? data.get(i).getCr().getCr()
                                : downMaxData);
                        downMaxData = (float) (downMaxData < data.get(i).getCr()
                                .getMa1() ? data.get(i).getCr().getMa1()
                                : downMaxData);
                        downMaxData = (float) (downMaxData < data.get(i).getCr()
                                .getMa2() ? data.get(i).getCr().getMa2()
                                : downMaxData);
                        downMaxData = (float) (downMaxData < data.get(i).getCr()
                                .getMa3() ? data.get(i).getCr().getMa3()
                                : downMaxData);
                        downMinData = (float) (downMinData > data.get(i).getCr()
                                .getCr() ? data.get(i).getCr().getCr()
                                : downMinData);
                        downMinData = (float) (downMinData > data.get(i).getCr()
                                .getMa1() ? data.get(i).getCr().getMa1()
                                : downMinData);
                        downMinData = (float) (downMinData > data.get(i).getCr()
                                .getMa2() ? data.get(i).getCr().getMa2()
                                : downMinData);
                        downMinData = (float) (downMinData > data.get(i).getCr()
                                .getMa2() ? data.get(i).getCr().getMa2()
                                : downMinData);
                    }
                } else if (mIndexType == IndexType.PSY) {
                    // 计算PSY最大、最小
                    downMaxData = (float) data.get(position).getPsy().getPsy();
                    downMinData = downMaxData;
                    for (int i = position; i < data.size()
                            && i < candleNum + position; i++) {
                        downMaxData = (float) (downMaxData < data.get(i).getPsy()
                                .getPsy() ? data.get(i).getPsy().getPsy()
                                : downMaxData);
                        downMinData = (float) (downMinData > data.get(i).getPsy()
                                .getPsy() ? data.get(i).getPsy().getPsy()
                                : downMinData);
                    }
                } else if (mIndexType == IndexType.DMA) {
                    // 计算DMA最大、最小
                    downMaxData = (float) data.get(position).getDma().getDif();
                    downMinData = downMaxData;
                    for (int i = position; i < data.size()
                            && i < candleNum + position; i++) {
                        downMaxData = (float) (downMaxData < data.get(i).getDma()
                                .getDif() ? data.get(i).getDma().getDif()
                                : downMaxData);
                        downMaxData = (float) (downMaxData < data.get(i).getDma()
                                .getAma() ? data.get(i).getDma().getAma()
                                : downMaxData);
                        downMinData = (float) (downMinData > data.get(i).getDma()
                                .getDif() ? data.get(i).getDma().getDif()
                                : downMinData);
                        downMinData = (float) (downMinData > data.get(i).getDma()
                                .getAma() ? data.get(i).getDma().getAma()
                                : downMinData);
                    }
                } else if (mIndexType == IndexType.TRIX) {
                    // 计算TRIX最大、最小
                    downMaxData = (float) data.get(position).getTrix().getTrix();
                    downMinData = downMaxData;
                    for (int i = position; i < data.size()
                            && i < candleNum + position; i++) {
                        downMaxData = (float) (downMaxData < data.get(i).getTrix()
                                .getTrix() ? data.get(i).getTrix().getTrix()
                                : downMaxData);
                        downMaxData = (float) (downMaxData < data.get(i).getTrix()
                                .getMaTrix() ? data.get(i).getTrix().getMaTrix()
                                : downMaxData);
                        downMinData = (float) (downMinData > data.get(i).getTrix()
                                .getTrix() ? data.get(i).getTrix().getTrix()
                                : downMinData);
                        downMinData = (float) (downMinData > data.get(i).getTrix()
                                .getMaTrix() ? data.get(i).getTrix().getMaTrix()
                                : downMinData);
                    }
                }
            }
            TextPaint tp = new TextPaint();
            tp.setTextSize(textSize);
            //    tp.setTypeface(Typeface.DEFAULT_BOLD);
            tp.setAntiAlias(true);
            // float upDataWidth = tp.measureText(Parse.getInstance().parse2String(
            // upMaxData));
            // float downDataWidth = tp.measureText(Parse.getInstance()
            // .parse2CNString(downMaxData));
            float dataWidth = tp.measureText("19990909");
            // if (spacing == 0.0f)
            // setStrokeBottom(textSize);
            // 计算上表与数据的比例
            upDataRatio = upChartHeight / (upMaxData - upMinData);
            // 计算下表与数据比例
            downDataRatio = downChartHeight / (downMaxData - downMinData);
            Paint paint = new Paint();
            paint.setAntiAlias(true);
            // 绘制纬线
            drawLatitudes(canvas, paint);
            // 绘制经线
            drawLongitudes(canvas, paint);
            // 绘制时间
            drawTime(canvas, tp);
            // 绘制蜡烛线
            drawCandleLine(canvas, paint, tp);
            // 绘制是上表折线
            drawUpLine(canvas, paint);
            // 绘制指标
            drawIndex(canvas, paint);
            // 绘制上表左边Y轴刻度
            drawUpAxisXTitle(canvas, tp, dataWidth);
            // 绘制下表左边Y轴刻度
            drawDownAxisXTitle(canvas, tp, dataWidth);
            // 绘制十字光标
            drawCrossLine(canvas, paint, tp);
        } catch (NullPointerException ex) {
            ex.printStackTrace();
        }
    }
    /**
     * 绘制纬线
     *
     * @param canvas
     * @param paint
     */
    private void drawLatitudes(Canvas canvas, Paint paint) {
        Log.i("KLineChart", "drawLatitudes.....................");
        Paint paint1 = new Paint();
        paint1.setColor(latLngColor);
        paint1.setStyle(Paint.Style.STROKE);
        paint1.setStrokeWidth(latLongWidth);
        paint1.setAntiAlias(true);
        paint1.setPathEffect(new DashPathEffect(new float[]{4, 4}, 1));
        Path path = new Path();
        for (int i = 1; i <= latitudesUpNum; i++) {
        /*    canvas.drawLine(getStrokeLeft(), upLatitudesSpacing * i
                                             + getStrokeWidth() + getStrokeTop(), getWidth()
                                                                                  -
                                                                                  getStrokeRight(),
                    upLatitudesSpacing * i
                    + getStrokeWidth() + getStrokeTop(), paint);  */
            path.moveTo(getStrokeLeft(), upLatitudesSpacing * i
                    + getStrokeWidth() + getStrokeTop());
            path.lineTo(getWidth()
                    -
                    getStrokeRight(), upLatitudesSpacing * i
                    + getStrokeWidth() + getStrokeTop());
        }
        canvas.drawPath(path, paint1);
        for (int i = 1; i <= latitudesDownNum; i++) {
            canvas.drawLine(getStrokeLeft(),
                    (getHeight() - getStrokeWidth() - getStrokeBottom())
                            - downLatitudesSpacing * i, getWidth()
                            - getStrokeRight(),
                    (getHeight() - getStrokeWidth() - getStrokeBottom())
                            - downLatitudesSpacing * i, paint1);
        }
    }
    /**
     * 绘制经线
     *
     * @param canvas
     * @param paint
     */
    private void drawLongitudes(Canvas canvas, Paint paint) {
        Paint paint1 = new Paint();
        paint1.setColor(latLngColor);
        paint1.setStyle(Paint.Style.STROKE);
        paint1.setStrokeWidth(latLongWidth);
        paint1.setAntiAlias(true);
        paint1.setPathEffect(new DashPathEffect(new float[]{4, 4}, 1));
        Path path = new Path();
        for (int i = 1; i <= longitudesNum; i++) {
            float X = getStrokeLeft() + i * longitudesSpacing;
            path.moveTo(X, getStrokeTop() + getStrokeWidth() / 2);
            path.lineTo(X, upChartBottom);
            path.moveTo(X, upChartBottom + spacing);
            path.lineTo(X, downChartBottom);
         /*
            canvas.drawLine(X, getStrokeTop() + getStrokeWidth() / 2, X,
                    upChartBottom, paint);
            canvas.drawLine(X, upChartBottom + spacing, X, downChartBottom,
                    paint);
                    */
        }
        canvas.drawPath(path, paint1);
    }
    /**
     * 绘制时间
     *
     * @param canvas
     * @param paint
     */
    private void drawTime(Canvas canvas, TextPaint paint) {
        try {
            paint.setColor(getResources().getColor(R.color.text_color_5c5f66));
            String startTime = "00:00";
            String endTime = "00:00";
            if (data != null && data.size() > position) {
                startTime = MyUtils.getInstance().date2String(
                        "yyyy/MM/dd HH:mm:ss", data.get(position).getTime() * 1000);
                endTime = position + candleNum >= data.size() ? MyUtils
                        .getInstance().date2String("yyyy/MM/dd HH:mm:ss",
                                data.get(data.size() - 1).getTime() * 1000)
                        : MyUtils.getInstance()
                        .date2String(
                                "yyyy/MM/dd HH:mm:ss",
                                data.get(position + candleNum - 1)
                                        .getTime() * 1000);
                if (isShowTime) {
                    startTime = startTime.substring(0, startTime.length() - 3);
                    endTime = endTime.substring(0, endTime.length() - 3);
                } else {
                    if(data.get(0).getType() == T_D_TYPE){
                        startTime = judgeTDNextDay(startTime);
                        endTime  =  judgeTDNextDay(endTime);
                    }else {
                        startTime = startTime.substring(0, startTime.length() - 9);
                        endTime = endTime.substring(0, endTime.length() - 9);
                    }
                }
            }
            canvas.drawText(startTime, getStrokeLeft() + getStrokeWidth() + 2,
                    upChartBottom + textSize, paint);
            canvas.drawText(endTime, getWidth() - getStrokeRight()
                            - getStrokeWidth() - paint.measureText(endTime) - 2,
                    upChartBottom + textSize, paint);
        }catch(ArrayIndexOutOfBoundsException ex){
            ex.printStackTrace();
        }catch(Exception ex){
            ex.printStackTrace();
        }
    }
    /**
     * 绘制蜡烛线
     *
     * @param canvas
     * @param paint
     */
    private void drawCandleLine(Canvas canvas, Paint paint, TextPaint tp) {
        if (data == null)
            return;
        paint.setStrokeWidth(2);
        float startX = getStrokeWidth() + getStrokeLeft();
        int index = 0;
        float maxY = Float.MAX_VALUE;
        float minY = 0;
        float maxX = 0;
        float minX = 0;
        KLineData maxYEntity = null;
        KLineData minYEntity = null;
        // float oldDate;
        // float oldX = 0.0f;
        for (int i = position; i < data.size() && i < candleNum + position; i++) {
            KLineData entity = data.get(i);
            // String date = Parse.getInstance().isNull(entity.getDate());
            // date = date.substring(0, 6);
            double close = entity.getClose();
            double open = entity.getOpen();
            // 柱形图
            float openY = upChartBottom
                    - (float) (open - upMinData) * upDataRatio;
            float closeY = upChartBottom
                    - (float) (close - upMinData) * upDataRatio;
            // 中线
            float highY = upChartBottom
                    - (float) (entity.getHighPrice() - upMinData) * upDataRatio;
            float lowY = upChartBottom
                    - (float) (entity.getLowPrice() - upMinData) * upDataRatio;
            float endX = getStrokeWidth() + getStrokeLeft()
                    + (dataSpacing * (index + 1) - dataSpacing * 0.25f);
            if (highY < maxY) {
                maxY = highY;
                maxYEntity = entity;
                maxX = endX;
            }
            if (lowY > minY) {
                minY = lowY;
                minYEntity = entity;
                minX = endX;
            }
            // 绘制经线
            // if (entity.isDrawLongitude()) {
            // paint.setColor(latitudesColor);
            //
            // tp.setColor(0xff868F9B);
            // String date = Parse.getInstance().isNull(entity.getTime());
            // date = date.substring(0, 6);
            // float textWidth = tp.measureText(date);
            // float textY = upChartBottom + textSize * 2 / 2;
            // float newX = 0.0f;
            // if (((endX - startX) / 2 + startX) - (textWidth / 2) <=
            // getStrokeLeft()
            // + getStrokeWidth()) {
            // newX = getStrokeWidth() + getStrokeLeft() + 2;
            // } else if (viewWidth - getStrokeWidth() - getStrokeRight()
            // - ((endX - startX) / 2 + startX) <= textWidth / 2) {
            // newX = viewWidth - textWidth - 2;
            // } else {
            // newX = ((endX - startX) / 2 + startX) - (textWidth / 2);
            // }
            // if (i != position) {
            // if (newX - oldX > textWidth + 2) {
            // canvas.drawLine((endX - startX) / 2 + startX,
            // getStrokeWidth() + getStrokeTop(),
            // (endX - startX) / 2 + startX, upChartBottom,
            // paint);
            // canvas.drawLine((endX - startX) / 2 + startX,
            // upChartBottom + spacing, (endX - startX) / 2
            // + startX, downChartBottom, paint);
            // canvas.drawText(date, newX, textY, tp);
            // oldX = newX;
            // }
            // } else {
            // canvas.drawLine((endX - startX) / 2 + startX,
            // getStrokeWidth() + getStrokeTop(), (endX - startX)
            // / 2 + startX, upChartBottom, paint);
            // canvas.drawLine((endX - startX) / 2 + startX, upChartBottom
            // + spacing, (endX - startX) / 2 + startX,
            // downChartBottom, paint);
            //
            // canvas.drawText(date, newX, textY, tp);
            // oldX = newX;
            // }
            // }
            // oldDate = date;
            if (openY < closeY) {
                paint.setStyle(Style.FILL);
                paint.setColor(getResources().getColor(R.color.green));
                canvas.drawRect(startX, openY, endX, closeY, paint);
                canvas.drawLine((endX - startX) / 2 + startX, highY,
                        (endX - startX) / 2 + startX, lowY, paint);
            } else if (openY > closeY) {
                paint.setStyle(Style.FILL);
                paint.setColor(getResources().getColor(R.color.red));
                canvas.drawRect(startX, closeY, endX, openY, paint);
                paint.setStyle(Style.FILL);
                canvas.drawLine((endX - startX) / 2 + startX, highY,
                        (endX - startX) / 2 + startX, closeY, paint);
                canvas.drawLine((endX - startX) / 2 + startX, lowY,
                        (endX - startX) / 2 + startX, openY, paint);
            } else {
                if (i != 0) {
                    KLineData oldItem = data.get(i - 1);
                    double oldClose = oldItem.getClose();
                    if (close > oldClose) {
                        paint.setColor(getResources().getColor(R.color.red));
                    } else if (close < oldClose) {
                        paint.setColor(getResources().getColor(R.color.green));
                    } else {
                        double oldOpen = oldItem.getOpen();
                        if (open > oldOpen) {
                            paint.setColor(getResources().getColor(R.color.red));
                        } else if (open < oldOpen) {
                            paint.setColor(getResources().getColor(R.color.green));
                        } else {
                            paint.setColor(getResources().getColor(R.color.red));
                        }
                    }
                } else {
                    paint.setColor(getResources().getColor(R.color.red));
                }
                paint.setStyle(Style.FILL);
                canvas.drawLine(startX, openY, endX, openY, paint);
                canvas.drawLine((endX - startX) / 2 + startX, highY,
                        (endX - startX) / 2 + startX, lowY, paint);
            }
            startX = getStrokeWidth() + getStrokeLeft() + dataSpacing
                    * (index + 1);
            index++;
            // if (i == position) {
            // tp.setColor(0xff868F9B);
            // canvas.drawText(String.valueOf(entity.getDate()),
            // getStrokeLeft() + getStrokeWidth() + 2, viewHeight, tp);
            // }
        }
        /************在K线图上标记最高、最低价***********/
        tp.setColor(getResources().getColor(R.color.color_333333));
        if (maxYEntity != null) {
            String h = Parse.getInstance().parse2String(maxYEntity.getHighPrice(), 2);
            Rect bounds = new Rect();
            tp.getTextBounds(h, 0, h.length(), bounds);
            maxY += Utils.Dp2Px(getContext(), 10);
            if (viewWidth / 2 < maxX) {
                maxX = maxX - bounds.width() - Utils.Dp2Px(getContext(), 15);
                drawAL(canvas, tp, (int) maxX + bounds.width() + Utils.Dp2Px(getContext(), 1), (int) maxY + bounds.height() / 2, (int) maxX + bounds.width() + Utils.Dp2Px(getContext(), 13), (int) maxY + bounds.height() / 2);
                //    Log.i(getClass().getSimpleName(), "getWidth()=" + getWidth() +  )
            } else {
                maxX += Utils.Dp2Px(getContext(), 15);
                drawAL(canvas, tp, (int) maxX - Utils.Dp2Px(getContext(), 1), (int) maxY + bounds.height() / 2, (int) maxX - Utils.Dp2Px(getContext(), 13), (int) maxY + bounds.height() / 2);
            }
            canvas.drawText(h, maxX, maxY + bounds.height(), tp);
        }
        if (minYEntity != null) {
            String l = Parse.getInstance().parse2String(minYEntity.getLowPrice(), 2);
            Rect bounds = new Rect();
            tp.getTextBounds(l, 0, l.length(), bounds);
            minY -= Utils.Dp2Px(getContext(), 10);
            if (viewWidth / 2 < minX) {
                minX = minX - bounds.width()  - Utils.Dp2Px(getContext(), 15);
                drawAL(canvas, tp, (int) minX + bounds.width() + Utils.Dp2Px(getContext(), 1), (int) minY - bounds.height() / 2, (int) minX + bounds.width() + Utils.Dp2Px(getContext(), 13), (int) minY - bounds.height() / 2);
            } else {
                minX += Utils.Dp2Px(getContext(), 15);
                drawAL(canvas, tp, (int) minX - Utils.Dp2Px(getContext(), 1), (int) minY - bounds.height() / 2, (int) minX - Utils.Dp2Px(getContext(), 13), (int) minY - bounds.height() / 2);
            }
            canvas.drawText(l, minX, minY, tp);
        }
        /**************************/
    }
    /**
     * 绘制上表折线
     *
     * @param canvas
     * @param paint
     */
    private void drawUpLine(Canvas canvas, Paint paint) {
        if (data == null || data.size() < position)
            return;
        paint.setStyle(Style.FILL);
        paint.setStrokeWidth(1);
        int index = 0;
        if (mMainIndexType == MainIndexType.BOLL) {
            int[] colors = {0xff187cef, 0xfff5a623, 0xfff80101};// 白,黄,红
            upColors = colors;
            Path path = new Path();
            Path path1 = new Path();
            Path path2 = new Path();
            for (int i = position; i < data.size() && i < candleNum + position; i++) {
                KLineData entity = data.get(i);
                if (i < data.size() - 1 && i < candleNum + position - 1) {
                    if (i >= 25) {
                        float startUPY = upChartBottom
                                - ((float) entity.getBoll().getUpper() - upMinData)
                                * upDataRatio;
                        float endUPY = upChartBottom
                                - ((float) data.get(i + 1).getBoll().getUpper() - upMinData)
                                * upDataRatio;
                        float lineStartX = getStrokeWidth() + getStrokeLeft()
                                + dataSpacing * index
                                + (dataSpacing * 0.75f / 2);
                        float lineEndX = getStrokeWidth() + getStrokeLeft()
                                + dataSpacing * (index + 1)
                                + (dataSpacing * 0.75f / 2);
//                        paint.setColor(colors[0]);
//                        canvas.drawLine(lineStartX, startUPY, lineEndX, endUPY,
//                                paint);
                        float startMIDY = upChartBottom
                                - ((float) entity.getBoll().getmID() - upMinData)
                                * upDataRatio;
                        float endMIDY = upChartBottom
                                - ((float) data.get(i + 1).getBoll().getmID() - upMinData)
                                * upDataRatio;
//                        paint.setColor(colors[1]);
//                        canvas.drawLine(lineStartX, startMIDY, lineEndX,
//                                endMIDY, paint);
                        float startLOWY = upChartBottom
                                - ((float) entity.getBoll().getLower() - upMinData)
                                * upDataRatio;
                        float endLOWY = upChartBottom
                                - ((float) data.get(i + 1).getBoll().getLower() - upMinData)
                                * upDataRatio;
//                        paint.setColor(colors[2]);
//                        canvas.drawLine(lineStartX, startLOWY, lineEndX,
//                                endLOWY, paint);
                        if (i == position || (position <= 25 && i == 25)) {
                            path.moveTo(lineStartX, startUPY);
                            path1.moveTo(lineStartX, startMIDY);
                            path2.moveTo(lineStartX, startLOWY);
                        } else {
                            path.lineTo(lineEndX, endUPY);
                            path1.lineTo(lineEndX, endMIDY);
                            path2.lineTo(lineEndX, endLOWY);
                        }
                    }
                }
                index++;
            }
            paint.setStyle(Style.STROKE);
            paint.setColor(colors[0]);
            canvas.drawPath(path, paint);
            paint.setColor(colors[1]);
            canvas.drawPath(path1, paint);
            paint.setColor(colors[2]);
            canvas.drawPath(path2, paint);
        } else {
            int[] colors = {0xfff5a623, 0xff187cef, 0xffbd10e0};
            upColors = colors;
            Path path = new Path();
            Path path1 = new Path();
            Path path2 = new Path();
            for (int i = position; i < data.size() && i < candleNum + position; i++) {
                KLineData entity = data.get(i);
                if (i < data.size() - 1 && i < candleNum + position - 1) {
                    if (i >= 4) {
                        float startMA5Y = upChartBottom
                                - ((float) entity.getDayMovingAverage()
                                .getMa5() - upMinData) * upDataRatio;
                        float endMA5Y = upChartBottom
                                - ((float) data.get(i + 1)
                                .getDayMovingAverage().getMa5() - upMinData)
                                * upDataRatio;
                        float lineStartX = getStrokeWidth() + getStrokeLeft()
                                + dataSpacing * index
                                + (dataSpacing * 0.75f / 2);
                        float lineEndX = getStrokeWidth() + getStrokeLeft()
                                + dataSpacing * (index + 1)
                                + (dataSpacing * 0.75f / 2);
//                        paint.setColor(colors[0]);
//                        canvas.drawLine(lineStartX, startMA5Y, lineEndX,
//                                endMA5Y, paint);
                        if (i == position || (position <= 4 && i == 4)) {
                            path.moveTo(lineStartX, startMA5Y);
                        } else {
                            path.lineTo(lineEndX, endMA5Y);
                        }
                        if (i >= 9) {
                            float startMA10Y = upChartBottom
                                    - ((float) entity.getDayMovingAverage()
                                    .getMa10() - upMinData)
                                    * upDataRatio;
                            float endMA10Y = upChartBottom
                                    - ((float) data.get(i + 1)
                                    .getDayMovingAverage().getMa10() - upMinData)
                                    * upDataRatio;
//                            paint.setColor(colors[1]);
//                            canvas.drawLine(lineStartX, startMA10Y, lineEndX,
//                                    endMA10Y, paint);
                            if (i == position || (position <= 9 && i == 9)) {
                                path1.moveTo(lineStartX, startMA10Y);
                            } else {
                                path1.lineTo(lineEndX, endMA10Y);
                            }
                            if (i >= 19) {
                                float startMA20Y = upChartBottom
                                        - ((float) entity.getDayMovingAverage()
                                        .getMa20() - upMinData)
                                        * upDataRatio;
                                float endMA20Y = upChartBottom
                                        - ((float) data.get(i + 1)
                                        .getDayMovingAverage()
                                        .getMa20() - upMinData)
                                        * upDataRatio;
//                                paint.setColor(colors[2]);
//                                canvas.drawLine(lineStartX, startMA20Y,
//                                        lineEndX, endMA20Y, paint);
                                if (i == position || (position <= 19 && i == 19)) {
                                    path2.moveTo(lineStartX, startMA20Y);
                                } else {
                                    path2.lineTo(lineEndX, endMA20Y);
                                }
                            }
                        }
                    }
                }
                index++;
            }
            paint.setStyle(Style.STROKE);
            paint.setColor(colors[0]);
            canvas.drawPath(path, paint);
            paint.setColor(colors[1]);
            canvas.drawPath(path1, paint);
            paint.setColor(colors[2]);
            canvas.drawPath(path2, paint);
        }
    }
    /**
     * 绘制指标
     *
     * @param canvas
     * @param paint
     */
    private void drawIndex(Canvas canvas, Paint paint) {
        if (data == null) {
            return;
        }
        if (mIndexType == IndexType.VOL)
            drawVOL(canvas, paint);
        else if (mIndexType == IndexType.MACD)
            drawMACD(canvas, paint);
     //   else if (mIndexType == IndexType.BOLL)
        //    drawVOL(canvas, paint);
            // drawBOLL(canvas, paint);
        else if (mIndexType == IndexType.KDJ)
            drawKDJ(canvas, paint);
        else if (mIndexType == IndexType.KD)
            drawKDJ(canvas, paint);
        else if (mIndexType == IndexType.RSI)
            drawRSI(canvas, paint);
        else if (mIndexType == IndexType.BIAS)
            drawBIAS(canvas, paint);
        else if (mIndexType == IndexType.BRAR)
            drawBRAR(canvas, paint);
        else if (mIndexType == IndexType.CCI)
            drawCCI(canvas, paint);
        else if (mIndexType == IndexType.DMI)
            drawDMI(canvas, paint);
        else if (mIndexType == IndexType.CR)
            drawCR(canvas, paint);
        else if (mIndexType == IndexType.PSY)
            drawPSY(canvas, paint);
        else if (mIndexType == IndexType.DMA)
            drawDMA(canvas, paint);
        else if (mIndexType == IndexType.TRIX)
            drawTRIX(canvas, paint);
    }
    /**
     * 绘制成交量指标(vol指标)
     *
     * @param canvas
     * @param paint
     */
    private void drawVOL(Canvas canvas, Paint paint) {
        int redColor = getResources().getColor(R.color.red);
        int greenColor = getResources().getColor(R.color.green);
        int[] colors = {redColor,
                greenColor};
        if (data == null || data.size() < position)
            return;
        int index = 0;
        for (int i = position; i < data.size() && i < candleNum + position; i++) {
            KLineData entity = data.get(i);
            if (entity.getClose() >= entity.getOpen()) {
                paint.setStyle(Style.FILL);
                paint.setColor(colors[0]);
            } else {
                paint.setStyle(Style.FILL);
                paint.setColor(colors[1]);
            }
            float startX = getStrokeWidth() + getStrokeLeft() + dataSpacing
                    * index;
            float endX = getStrokeWidth() + getStrokeLeft()
                    + (dataSpacing * (index + 1) - dataSpacing * 0.25f);
            float highY = downChartBottom
                    - ((float) entity.getVolume().getNum() - downMinData)
                    * downDataRatio;
            float lowY = downChartBottom - (0 - downMinData) * downDataRatio;
            canvas.drawRect(startX, highY, endX, lowY, paint);
            index++;
        }
        drawVOLMA(canvas, paint);
    }
    /**
     * 绘制成交量MA折线
     *
     * @param canvas
     * @param paint
     */
    private void drawVOLMA(Canvas canvas, Paint paint) {
        int[] colors = {0xff187cef, 0xfff5a623, 0xffbd10e0};
        downColors = colors;
        paint.setStyle(Style.FILL);
        paint.setStrokeWidth(1);
        int index = 0;
        Path path = new Path();
        Path path1 = new Path();
        Path path2 = new Path();
        for (int i = position; i < data.size() - 1
                && i < candleNum + position - 1; i++) {
            KLineData entity = data.get(i);
            float lineStartX = getStrokeWidth() + getStrokeLeft() + dataSpacing
                    * index +
                    (dataSpacing * 0.75f / 2);
            float lineEndX = getStrokeWidth() + getStrokeLeft() + dataSpacing
                    * (index + 1) +
                    (dataSpacing * 0.75f / 2);
            if (i >= 4) {
                float startVMA5Y = (float) (downChartBottom - (entity
                        .getVolume().getMa5() -
                        downMinData) * downDataRatio);
                float endVMA5Y = (float) (downChartBottom - (data.get(i + 1)
                        .getVolume().getMa5() -
                        downMinData)
                        * downDataRatio);
//                paint.setColor(colors[0]);
//                canvas.drawLine(lineStartX, startVMA5Y, lineEndX, endVMA5Y,
//                        paint);
                if (i == position || (position <= 4 && i == 4)) {
                    path.moveTo(lineStartX, startVMA5Y);
                } else {
                    path.lineTo(lineEndX, endVMA5Y);
                }
            }
            if (i >= 9) {
                float startVMA10Y = (float) (downChartBottom - (entity
                        .getVolume().getMa10() -
                        downMinData) * downDataRatio);
                float endVMA10Y = (float) (downChartBottom - (data.get(i + 1)
                        .getVolume().getMa10() -
                        downMinData)
                        * downDataRatio);
//                paint.setColor(colors[1]);
//                canvas.drawLine(lineStartX, startVMA10Y, lineEndX, endVMA10Y,
//                        paint);
                if (i == position || (position <= 9 && i == 9)) {
                    path1.moveTo(lineStartX, startVMA10Y);
                } else {
                    path1.lineTo(lineEndX, endVMA10Y);
                }
            }
            if (i >= 19) {
                float startVMA20Y = (float) (downChartBottom - (entity
                        .getVolume().getMa20() -
                        downMinData) * downDataRatio);
                float endVMA20Y = (float) (downChartBottom - (data.get(i + 1)
                        .getVolume().getMa20() -
                        downMinData)
                        * downDataRatio);
//                paint.setColor(colors[2]);
//                canvas.drawLine(lineStartX, startVMA20Y, lineEndX, endVMA20Y,
//                        paint);
                if (i == position || (position <= 19 && i == 19)) {
                    path2.moveTo(lineStartX, startVMA20Y);
                } else {
                    path2.lineTo(lineEndX, startVMA20Y);
                }
            }
            index++;
        }
        paint.setStyle(Style.STROKE);
        paint.setColor(colors[0]);
        canvas.drawPath(path, paint);
        paint.setColor(colors[1]);
        canvas.drawPath(path1, paint);
        paint.setColor(colors[2]);
        canvas.drawPath(path2, paint);
    }
    /**
     * 绘制MACD指标
     *
     * @param canvas
     * @param paint
     */
    private void drawMACD(Canvas canvas, Paint paint) {
        int[] colors = {0xff187cef, 0xfff5a623, 0xfff80101};
        int redColor = getResources().getColor(R.color.red);
        int greenColor = getResources().getColor(R.color.green);
        int[] colorss = {redColor, greenColor};
        downColors = colors;
        paint.setStyle(Style.FILL);
        paint.setStrokeWidth(1);
        int index = 0;
        for (int i = position; i < data.size() && i < candleNum + position; i++) {
            KLineData entity = data.get(i);
            float lineX = getStrokeWidth() + getStrokeLeft() + dataSpacing
                    * index + (dataSpacing * 0.75f / 2);
            if (i >= 33) {
                float MACD = (float) (downChartBottom - (entity.getMacd()
                        .getMacd() - downMinData) *
                        downDataRatio);
                float zero = (float) (downChartBottom - (0 - downMinData)
                        * downDataRatio);
                if (MACD < zero) {
                    paint.setColor(colorss[0]);
                } else {
                    paint.setColor(colorss[1]);
                }
                canvas.drawLine(lineX, zero, lineX, MACD, paint);
            }
            index++;
        }
        index = 0;
        Path path = new Path();
        Path path1 = new Path();
        for (int i = position; i < data.size() - 1
                && i < candleNum + position - 1; i++) {
            KLineData entity = data.get(i);
            float lineStartX = getStrokeWidth() + getStrokeLeft() + dataSpacing
                    * index +
                    (dataSpacing * 0.75f / 2);
            float lineEndX = getStrokeWidth() + getStrokeLeft() + dataSpacing
                    * (index + 1) +
                    (dataSpacing * 0.75f / 2);
            if (i >= 25) {
                float startEMA26Y = (float) (downChartBottom - (entity
                        .getMacd().getDiff() -
                        downMinData) * downDataRatio);
                float endEMA26Y = (float) (downChartBottom - (data.get(i + 1)
                        .getMacd().getDiff() -
                        downMinData)
                        * downDataRatio);
//                paint.setColor(colors[0]);
//                canvas.drawLine(lineStartX, startEMA26Y, lineEndX, endEMA26Y,
//                        paint);
                if (i == position || (position <= 25 && i == 25)) {
                    path.moveTo(lineStartX, startEMA26Y);
                } else {
                    path.lineTo(lineEndX, endEMA26Y);
                }
            }
            if (i >= 33) {
                float startEMA9Y = (float) (downChartBottom - (entity.getMacd()
                        .getDea() - downMinData) *
                        downDataRatio);
                float endEMA9Y = (float) (downChartBottom - (data.get(i + 1)
                        .getMacd().getDea() -
                        downMinData)
                        * downDataRatio);
//                paint.setColor(colors[1]);
//                canvas.drawLine(lineStartX, startEMA9Y, lineEndX, endEMA9Y,
//                        paint);
                if (i == position || (position <= 33 && i == 33)) {
                    path1.moveTo(lineStartX, startEMA9Y);
                } else {
                    path1.lineTo(lineEndX, endEMA9Y);
                }
            }
            index++;
        }
        paint.setStyle(Style.STROKE);
        paint.setColor(colors[0]);
        canvas.drawPath(path, paint);
        paint.setColor(colors[1]);
        canvas.drawPath(path1, paint);
    }
    /**
     * 绘制BOLL指标
     *
     * @param canvas
     * @param paint
     */
    private void drawBOLL(Canvas canvas, Paint paint) {
        int[] colors = {0xff187cef, 0xfff5a623, 0xfff80101};// 白,黄,红
        downColors = colors;
        int index = 0;
        paint.setStrokeWidth(1);
        for (int i = position; i < data.size() - 1
                && i < candleNum + position - 1; i++) {
            KLineData entity = data.get(i);
            float lineStartX = getStrokeWidth() + getStrokeLeft() + dataSpacing
                    * index +
                    (dataSpacing * 0.75f / 2);
            float lineEndX = getStrokeWidth() + getStrokeLeft() + dataSpacing
                    * (index + 1) +
                    (dataSpacing * 0.75f / 2);
            if (i >= 25) {
                // 中轨线
                float startMIDY = (float) (downChartBottom - (entity.getBoll()
                        .getmID() - downMinData) *
                        downDataRatio);
                float endMIDY = (float) (downChartBottom - (data.get(i + 1)
                        .getBoll().getmID() -
                        downMinData)
                        * downDataRatio);
                paint.setColor(colors[0]);
                canvas.drawLine(lineStartX, startMIDY, lineEndX, endMIDY, paint);
                // 上轨线
                float startUpY = (float) (downChartBottom - (entity.getBoll()
                        .getUpper() - downMinData) *
                        downDataRatio);
                float endUpY = (float) (downChartBottom - (data.get(i + 1)
                        .getBoll().getUpper() -
                        downMinData)
                        * downDataRatio);
                paint.setColor(colors[1]);
                canvas.drawLine(lineStartX, startUpY, lineEndX, endUpY, paint);
                // 下轨线
                float startLowY = (float) (downChartBottom - (entity.getBoll()
                        .getLower() - downMinData) *
                        downDataRatio);
                float endLowY = (float) (downChartBottom - (data.get(i + 1)
                        .getBoll().getLower() -
                        downMinData)
                        * downDataRatio);
                paint.setColor(colors[2]);
                canvas.drawLine(lineStartX, startLowY, lineEndX, endLowY, paint);
            }
            index++;
        }
    }
    /**
     * 绘制KDJ
     *
     * @param canvas
     * @param paint
     */
    private void drawKDJ(Canvas canvas, Paint paint) {
        int[] colors = {0xff187cef, 0xfff5a623, 0xfff80101};// 白,黄,红
        downColors = colors;
        int index = 0;
        paint.setStrokeWidth(1);
        Path path = new Path();
        Path path1 = new Path();
        Path path2 = new Path();
        for (int i = position; i < data.size() - 1
                && i < candleNum + position - 1; i++) {
            KLineData entity = data.get(i);
            float lineStartX = getStrokeWidth() + getStrokeLeft() + dataSpacing
                    * index +
                    (dataSpacing * 0.75f / 2);
            float lineEndX = getStrokeWidth() + getStrokeLeft() + dataSpacing
                    * (index + 1) +
                    (dataSpacing * 0.75f / 2);
            if (i >= 8) {
                float startKY = (float) (downChartBottom - (entity.getKdj()
                        .getK() - downMinData) *
                        downDataRatio);
                float endKY = (float) (downChartBottom - (data.get(i + 1)
                        .getKdj().getK() - downMinData)
                        * downDataRatio);
//                paint.setColor(colors[0]);
//                canvas.drawLine(lineStartX, startKY, lineEndX, endKY, paint);
                float startDY = (float) (downChartBottom - (entity.getKdj()
                        .getD() - downMinData) *
                        downDataRatio);
                float endDY = (float) (downChartBottom - (data.get(i + 1)
                        .getKdj().getD() - downMinData)
                        * downDataRatio);
//                paint.setColor(colors[1]);
//                canvas.drawLine(lineStartX, startDY, lineEndX, endDY, paint);
                if (i == position || (position <= 8 && i == 8)) {
                    path.moveTo(lineStartX, startKY);
                    path1.moveTo(lineStartX, startDY);
                } else {
                    path.lineTo(lineEndX, endKY);
                    path1.lineTo(lineEndX, endDY);
                }
                if (mIndexType == IndexType.KDJ) {
                    float startJY = (float) (downChartBottom - (entity.getKdj()
                            .getJ() - downMinData) *
                            downDataRatio);
                    float endJY = (float) (downChartBottom - (data.get(i + 1)
                            .getKdj().getJ() -
                            downMinData)
                            * downDataRatio);
//                    paint.setColor(colors[2]);
//                    canvas.drawLine(lineStartX, startJY, lineEndX, endJY, paint);
                    if (i == position || (position <= 8 && i == 8)) {
                        path2.moveTo(lineStartX, startJY);
                    } else {
                        path2.lineTo(lineEndX, endJY);
                    }
                }
            }
            index++;
        }
        paint.setStyle(Style.STROKE);
        paint.setColor(colors[0]);
        canvas.drawPath(path, paint);
        paint.setColor(colors[1]);
        canvas.drawPath(path1, paint);
        if (mIndexType == IndexType.KDJ) {
            paint.setColor(colors[2]);
            canvas.drawPath(path2, paint);
        }
    }
    /**
     * 绘制RSI
     *
     * @param canvas
     * @param paint
     */
    private void drawRSI(Canvas canvas, Paint paint) {
        int[] colors = {0xff187cef, 0xfff5a623, 0xfff80101};// 白,黄,红
        downColors = colors;
        int index = 0;
        paint.setStrokeWidth(1);
        Path path = new Path();
        Path path1 = new Path();
        Path path2 = new Path();
        for (int i = position; i < data.size() - 1
                && i < candleNum + position - 1; i++) {
            KLineData entity = data.get(i);
            float lineStartX = getStrokeWidth() + getStrokeLeft() + dataSpacing
                    * index +
                    (dataSpacing * 0.75f / 2);
            float lineEndX = getStrokeWidth() + getStrokeLeft() + dataSpacing
                    * (index + 1) +
                    (dataSpacing * 0.75f / 2);
            if (i >= 6) {
                float startRSI1Y = (float) (downChartBottom - (entity.getRsi()
                        .getRsi6() - downMinData) *
                        downDataRatio);
                float endRSI1Y = (float) (downChartBottom - (data.get(i + 1)
                        .getRsi().getRsi6() -
                        downMinData)
                        * downDataRatio);
//                paint.setColor(colors[0]);
//                canvas.drawLine(lineStartX, startRSI1Y, lineEndX, endRSI1Y,
//                        paint);
                if (i == position || (position <= 6 && i == 6)) {
                    path.moveTo(lineStartX, startRSI1Y);
                } else {
                    path.lineTo(lineEndX, endRSI1Y);
                }
                if (i >= 12) {
                    float startRSI2Y = (float) (downChartBottom - (entity
                            .getRsi().getRsi12() -
                            downMinData) * downDataRatio);
                    float endRSI2Y = (float) (downChartBottom - (data
                            .get(i +
                                    1).getRsi().getRsi12() -
                            downMinData)
                            * downDataRatio);
//                    paint.setColor(colors[1]);
//                    canvas.drawLine(lineStartX, startRSI2Y, lineEndX, endRSI2Y,
//                            paint);
                    if (i == position || (position <= 12 && i == 12)) {
                        path1.moveTo(lineStartX, startRSI2Y);
                    } else {
                        path1.lineTo(lineEndX, endRSI2Y);
                    }
                    if (i >= 24) {
                        float startRSI3Y = (float) (downChartBottom - (entity
                                .getRsi().getRsi24() -
                                downMinData)
                                * downDataRatio);
                        float endRSI3Y = (float) (downChartBottom - (data
                                .get(i +
                                        1).getRsi().getRsi24() -
                                downMinData)
                                * downDataRatio);
//                        paint.setColor(colors[2]);
//                        canvas.drawLine(lineStartX, startRSI3Y, lineEndX,
//                                endRSI3Y, paint);
                        if (i == position || (position <= 24 && i == 24)) {
                            path2.moveTo(lineStartX, startRSI3Y);
                        } else {
                            path2.lineTo(lineEndX, endRSI3Y);
                        }
                    }
                }
            }
            index++;
        }
        paint.setStyle(Style.STROKE);
        paint.setColor(colors[0]);
        canvas.drawPath(path, paint);
        paint.setColor(colors[1]);
        canvas.drawPath(path1, paint);
        paint.setColor(colors[2]);
        canvas.drawPath(path2, paint);
    }
    /**
     * 绘制BIAS
     *
     * @param canvas
     * @param paint
     */
    private void drawBIAS(Canvas canvas, Paint paint) {
        int[] colors = {0xff187cef, 0xfff5a623, 0xfff80101};// 白,黄,红
        downColors = colors;
        int index = 0;
        paint.setStrokeWidth(1);
        Path path = new Path();
        Path path1 = new Path();
        Path path2 = new Path();
        for (int i = position; i < data.size() - 1
                && i < candleNum + position - 1; i++) {
            KLineData entity = data.get(i);
            float lineStartX = getStrokeWidth() + getStrokeLeft() + dataSpacing
                    * index +
                    (dataSpacing * 0.75f / 2);
            float lineEndX = getStrokeWidth() + getStrokeLeft() + dataSpacing
                    * (index + 1) +
                    (dataSpacing * 0.75f / 2);
            if (i >= 5) {
                float startBIAS1Y = (float) (downChartBottom - (entity
                        .getBias().getBias1() -
                        downMinData) * downDataRatio);
                float endBIAS1Y = (float) (downChartBottom - (data.get(i + 1)
                        .getBias().getBias1() -
                        downMinData)
                        * downDataRatio);
//                paint.setColor(colors[0]);
//                canvas.drawLine(lineStartX, startBIAS1Y, lineEndX, endBIAS1Y,
//                        paint);
                if (i == position || (position <= 5 && i == 5)) {
                    path.moveTo(lineStartX, startBIAS1Y);
                } else {
                    path.lineTo(lineEndX, endBIAS1Y);
                }
                if (i >= 11) {
                    float startBIAS2Y = (float) (downChartBottom - (entity
                            .getBias().getBias2() -
                            downMinData)
                            * downDataRatio);
                    float endBIAS2Y = (float) (downChartBottom - (data
                            .get(i +
                                    1).getBias().getBias2() -
                            downMinData)
                            * downDataRatio);
//                    paint.setColor(colors[1]);
//                    canvas.drawLine(lineStartX, startBIAS2Y, lineEndX,
//                            endBIAS2Y, paint);
                    if (i == position || (position <= 11 && i == 11)) {
                        path1.moveTo(lineStartX, startBIAS2Y);
                    } else {
                        path1.lineTo(lineEndX, endBIAS2Y);
                    }
                    if (i >= 23) {
                        float startBIAS3Y = (float) (downChartBottom - (entity
                                .getBias().getBias3() -
                                downMinData)
                                * downDataRatio);
                        float endBIAS3Y = (float) (downChartBottom - (data
                                .get(i +
                                        1).getBias().getBias3() -
                                downMinData)
                                * downDataRatio);
//                        paint.setColor(colors[2]);
//                        canvas.drawLine(lineStartX, startBIAS3Y, lineEndX,
//                                endBIAS3Y, paint);
                        if (i == position || (position <= 23 && i == 23)) {
                            path2.moveTo(lineStartX, startBIAS3Y);
                        } else {
                            path2.lineTo(lineEndX, endBIAS3Y);
                        }
                    }
                }
            }
            index++;
        }
        paint.setStyle(Style.STROKE);
        paint.setColor(colors[0]);
        canvas.drawPath(path, paint);
        paint.setColor(colors[1]);
        canvas.drawPath(path1, paint);
        paint.setColor(colors[2]);
        canvas.drawPath(path2, paint);
    }
    /**
     * 绘制BRAR
     *
     * @param canvas
     * @param paint
     */
    private void drawBRAR(Canvas canvas, Paint paint) {
        int[] colors = {0xff187cef, 0xfff5a623};// 白,黄
        downColors = colors;
        int index = 0;
        paint.setStrokeWidth(1);
        Path path = new Path();
        Path path1 = new Path();
        for (int i = position; i < data.size() - 1
                && i < candleNum + position - 1; i++) {
            KLineData entity = data.get(i);
            float lineStartX = getStrokeWidth() + getStrokeLeft() + dataSpacing
                    * index +
                    (dataSpacing * 0.75f / 2);
            float lineEndX = getStrokeWidth() + getStrokeLeft() + dataSpacing
                    * (index + 1) +
                    (dataSpacing * 0.75f / 2);
            if (i >= 25) {
                float startARY = (float) (downChartBottom - (entity.getBrar()
                        .getAr() - downMinData) *
                        downDataRatio);
                float endARY = (float) (downChartBottom - (data.get(i + 1)
                        .getBrar().getAr() - downMinData)
                        * downDataRatio);
//                paint.setColor(colors[0]);
//                canvas.drawLine(lineStartX, startARY, lineEndX, endARY, paint);
                if (i == position || (position <= 25 && i == 25)) {
                    path.moveTo(lineStartX, startARY);
                } else {
                    path.lineTo(lineEndX, endARY);
                }
                if (i >= 26) {
                    float startBRY = (float) (downChartBottom - (entity
                            .getBrar().getBr() -
                            downMinData) * downDataRatio);
                    float endBRY = (float) (downChartBottom - (data.get(i + 1)
                            .getBrar().getBr() -
                            downMinData)
                            * downDataRatio);
//                    paint.setColor(colors[1]);
//                    canvas.drawLine(lineStartX, startBRY, lineEndX, endBRY,
//                            paint);
                    if (i == position || (position <= 26 && i == 26)) {
                        path1.moveTo(lineStartX, startBRY);
                    } else {
                        path1.lineTo(lineEndX, endBRY);
                    }
                }
            }
            index++;
        }
        paint.setStyle(Style.STROKE);
        paint.setColor(colors[0]);
        canvas.drawPath(path, paint);
        paint.setColor(colors[1]);
        canvas.drawPath(path1, paint);
    }
    /**
     * 绘制CCI
     *
     * @param canvas
     * @param paint
     */
    private void drawCCI(Canvas canvas, Paint paint) {
        int[] colors = {0xff187cef};// 白
        downColors = colors;
        int index = 0;
        paint.setStrokeWidth(1);
        Path path = new Path();
        for (int i = position; i < data.size() - 1
                && i < candleNum + position - 1; i++) {
            KLineData entity = data.get(i);
            float lineStartX = getStrokeWidth() + getStrokeLeft() + dataSpacing
                    * index +
                    (dataSpacing * 0.75f / 2);
            float lineEndX = getStrokeWidth() + getStrokeLeft() + dataSpacing
                    * (index + 1) +
                    (dataSpacing * 0.75f / 2);
            if (i >= 13) {
                float startCCIY = (float) (downChartBottom - (entity.getCci()
                        .getCci() - downMinData) *
                        downDataRatio);
                float endCCIY = (float) (downChartBottom - (data.get(i + 1)
                        .getCci().getCci() -
                        downMinData)
                        * downDataRatio);
//                paint.setColor(colors[0]);
//                canvas.drawLine(lineStartX, startCCIY, lineEndX, endCCIY, paint);
                if (i == position || (position <= 13 && i == 13)) {
                    path.moveTo(lineStartX, startCCIY);
                } else {
                    path.lineTo(lineEndX, endCCIY);
                }
            }
            index++;
        }
        paint.setStyle(Style.STROKE);
        paint.setColor(colors[0]);
        canvas.drawPath(path, paint);
    }
    /**
     * 绘制CCI
     *
     * @param canvas
     * @param paint
     */
    private void drawDMI(Canvas canvas, Paint paint) {
        int[] colors = {0xff187cef, 0xfff5a623, 0xfff80101, 0xff74bd4f};// 白,黄,红,绿
        downColors = colors;
        int index = 0;
        paint.setStrokeWidth(1);
        Path path = new Path();
        Path path1 = new Path();
        Path path2 = new Path();
        Path path3 = new Path();
        for (int i = position; i < data.size() - 1
                && i < candleNum + position - 1; i++) {
            KLineData entity = data.get(i);
            float lineStartX = getStrokeWidth() + getStrokeLeft() + dataSpacing
                    * index +
                    (dataSpacing * 0.75f / 2);
            float lineEndX = getStrokeWidth() + getStrokeLeft() + dataSpacing
                    * (index + 1) +
                    (dataSpacing * 0.75f / 2);
            if (i >= 14) {
                float startPDIY = (float) (downChartBottom - (entity.getDmi()
                        .getPdi() - downMinData) *
                        downDataRatio);
                float endPDIY = (float) (downChartBottom - (data.get(i + 1)
                        .getDmi().getPdi() -
                        downMinData)
                        * downDataRatio);
//                paint.setColor(colors[0]);
//                canvas.drawLine(lineStartX, startPDIY, lineEndX, endPDIY, paint);
                float startMDIY = (float) (downChartBottom - (entity.getDmi()
                        .getMdi() - downMinData) *
                        downDataRatio);
                float endMDIY = (float) (downChartBottom - (data.get(i + 1)
                        .getDmi().getMdi() -
                        downMinData)
                        * downDataRatio);
//                paint.setColor(colors[1]);
//                canvas.drawLine(lineStartX, startMDIY, lineEndX, endMDIY, paint);
                if (i == position || (position <= 14 && i == 14)) {
                    path.moveTo(lineStartX, startPDIY);
                    path1.moveTo(lineStartX, startMDIY);
                } else {
                    path.lineTo(lineEndX, endPDIY);
                    path1.lineTo(lineEndX, endMDIY);
                }
                if (i >= 19) {
                    float startADXY = (float) (downChartBottom - (entity
                            .getDmi().getAdx() -
                            downMinData) * downDataRatio);
                    float endADXY = (float) (downChartBottom - (data.get(i + 1)
                            .getDmi().getAdx() -
                            downMinData)
                            * downDataRatio);
//                    paint.setColor(colors[2]);
//                    canvas.drawLine(lineStartX, startADXY, lineEndX, endADXY,
//                            paint);
                    if (i == position || (position <= 19 && i == 19)) {
                        path2.moveTo(lineStartX, startADXY);
                    } else {
                        path2.lineTo(lineEndX, endADXY);
                    }
                    if (i >= 25) {
                        float startADXRY = (float) (downChartBottom - (entity
                                .getDmi().getAdxr() -
                                downMinData)
                                * downDataRatio);
                        float endADXRY = (float) (downChartBottom - (data
                                .get(i +
                                        1).getDmi().getAdxr() -
                                downMinData)
                                * downDataRatio);
//                        paint.setColor(colors[3]);
//                        canvas.drawLine(lineStartX, startADXRY, lineEndX,
//                                endADXRY, paint);
                        if (i == position || (position <= 25 && i == 25)) {
                            path3.moveTo(lineStartX, startADXRY);
                        } else {
                            path3.lineTo(lineEndX, endADXRY);
                        }
                    }
                }
            }
            index++;
        }
        paint.setStyle(Style.STROKE);
        paint.setColor(colors[0]);
        canvas.drawPath(path, paint);
        paint.setColor(colors[1]);
        canvas.drawPath(path1, paint);
        paint.setColor(colors[2]);
        canvas.drawPath(path2, paint);
        paint.setColor(colors[3]);
        canvas.drawPath(path3, paint);
    }
    /**
     * 绘制CR
     *
     * @param canvas
     * @param paint
     */
    private void drawCR(Canvas canvas, Paint paint) {
        int[] colors = {0xff187cef, 0xfff5a623, 0xfff80101, 0xff74bd4f};// 白,黄,红,绿
        downColors = colors;
        int index = 0;
        paint.setStrokeWidth(1);
        Path path = new Path();
        Path path1 = new Path();
        Path path2 = new Path();
        Path path3 = new Path();
        for (int i = position; i < data.size() - 1
                && i < candleNum + position - 1; i++) {
            KLineData entity = data.get(i);
            float lineStartX = getStrokeWidth() + getStrokeLeft() + dataSpacing
                    * index +
                    (dataSpacing * 0.75f / 2);
            float lineEndX = getStrokeWidth() + getStrokeLeft() + dataSpacing
                    * (index + 1) +
                    (dataSpacing * 0.75f / 2);
            if (i >= 26) {
                float startCRY = (float) (downChartBottom - (entity.getCr()
                        .getCr() - downMinData) *
                        downDataRatio);
                float endCRY = (float) (downChartBottom - (data.get(i + 1)
                        .getCr().getCr() - downMinData)
                        * downDataRatio);
//                paint.setColor(colors[0]);
//                canvas.drawLine(lineStartX, startCRY, lineEndX, endCRY, paint);
                if (i == position || (position <= 26 && i == 26)) {
                    path.moveTo(lineStartX, startCRY);
                } else {
                    path.lineTo(lineEndX, endCRY);
                }
                if (i >= 33) {
                    float startMA1Y = (float) (downChartBottom - (entity
                            .getCr().getMa1() -
                            downMinData) * downDataRatio);
                    float endMA1Y = (float) (downChartBottom - (data.get(i + 1)
                            .getCr().getMa1() -
                            downMinData)
                            * downDataRatio);
//                    paint.setColor(colors[1]);
//                    canvas.drawLine(lineStartX, startMA1Y, lineEndX, endMA1Y,
//                            paint);
                    if (i == position || (position <= 33 && i == 33)) {
                        path1.moveTo(lineStartX, startMA1Y);
                    } else {
                        path1.lineTo(lineEndX, endMA1Y);
                    }
                    if (i >= 40) {
                        float startMA2Y = (float) (downChartBottom - (entity
                                .getCr().getMa2() -
                                downMinData)
                                * downDataRatio);
                        float endMA2Y = (float) (downChartBottom - (data
                                .get(i +
                                        1).getCr().getMa2() -
                                downMinData)
                                * downDataRatio);
//                        paint.setColor(colors[2]);
//                        canvas.drawLine(lineStartX, startMA2Y, lineEndX,
//                                endMA2Y, paint);
                        if (i == position || (position <= 40 && i == 40)) {
                            path2.moveTo(lineStartX, startMA2Y);
                        } else {
                            path2.lineTo(lineEndX, endMA2Y);
                        }
                        if (i >= 54) {
                            float startMA3Y = (float) (downChartBottom - (entity
                                    .getCr().getMa3() -
                                    downMinData)
                                    * downDataRatio);
                            float endMA3Y = (float) (downChartBottom - (data
                                    .get(i +
                                            1).getCr().getMa3() -
                                    downMinData)
                                    * downDataRatio);
//                            paint.setColor(colors[3]);
//                            canvas.drawLine(lineStartX, startMA3Y, lineEndX,
//                                    endMA3Y, paint);
                            if (i == position || (position <= 54 && i == 54)) {
                                path3.moveTo(lineStartX, startMA3Y);
                            } else {
                                path3.lineTo(lineEndX, endMA3Y);
                            }
                        }
                    }
                }
            }
            index++;
        }
        paint.setStyle(Style.STROKE);
        paint.setColor(colors[0]);
        canvas.drawPath(path, paint);
        paint.setColor(colors[1]);
        canvas.drawPath(path1, paint);
        paint.setColor(colors[2]);
        canvas.drawPath(path2, paint);
        paint.setColor(colors[3]);
        canvas.drawPath(path3, paint);
    }
    /**
     * 绘制PSY
     *
     * @param canvas
     * @param paint
     */
    private void drawPSY(Canvas canvas, Paint paint) {
        int[] colors = {0xff187cef};
        downColors = colors;
        int index = 0;
        paint.setStrokeWidth(1);
        Path path = new Path();
        for (int i = position; i < data.size() - 1
                && i < candleNum + position - 1; i++) {
            KLineData entity = data.get(i);
            float lineStartX = getStrokeWidth() + getStrokeLeft() + dataSpacing
                    * index +
                    (dataSpacing * 0.75f / 2);
            float lineEndX = getStrokeWidth() + getStrokeLeft() + dataSpacing
                    * (index + 1) +
                    (dataSpacing * 0.75f / 2);
            if (i >= 12) {
                float startPSYY = (float) (downChartBottom - (entity.getPsy()
                        .getPsy() - downMinData) *
                        downDataRatio);
                float endPSYY = (float) (downChartBottom - (data.get(i + 1)
                        .getPsy().getPsy() -
                        downMinData)
                        * downDataRatio);
//                paint.setColor(colors[0]);
//                canvas.drawLine(lineStartX, startPSYY, lineEndX, endPSYY, paint);
                if (i == position || (position <= 12 && i == 12)) {
                    path.moveTo(lineStartX, startPSYY);
                } else {
                    path.lineTo(lineEndX, endPSYY);
                }
            }
            index++;
        }
        paint.setStyle(Style.STROKE);
        paint.setColor(colors[0]);
        canvas.drawPath(path, paint);
    }
    /**
     * 绘制DMA
     *
     * @param canvas
     * @param paint
     */
    private void drawDMA(Canvas canvas, Paint paint) {
        int[] colors = {0xff187cef, 0xfff5a623};// 白,黄
        downColors = colors;
        int index = 0;
        paint.setStrokeWidth(1);
        Path path = new Path();
        Path path1 = new Path();
        for (int i = position; i < data.size() - 1
                && i < candleNum + position - 1; i++) {
            KLineData entity = data.get(i);
            float lineStartX = getStrokeWidth() + getStrokeLeft() + dataSpacing
                    * index +
                    (dataSpacing * 0.75f / 2);
            float lineEndX = getStrokeWidth() + getStrokeLeft() + dataSpacing
                    * (index + 1) +
                    (dataSpacing * 0.75f / 2);
            if (i >= 49) {
                float startDIFY = (float) (downChartBottom - (entity.getDma()
                        .getDif() - downMinData) *
                        downDataRatio);
                float endDIFY = (float) (downChartBottom - (data.get(i + 1)
                        .getDma().getDif() -
                        downMinData)
                        * downDataRatio);
//                paint.setColor(colors[0]);
//                canvas.drawLine(lineStartX, startDIFY, lineEndX, endDIFY, paint);
                if (i == position || (position <= 49 && i == 49)) {
                    path.moveTo(lineStartX, startDIFY);
                } else {
                    path.lineTo(lineEndX, endDIFY);
                }
                if (i >= 58) {
                    float startAMAY = (float) (downChartBottom - (entity
                            .getDma().getAma() -
                            downMinData) * downDataRatio);
                    float endAMAY = (float) (downChartBottom - (data.get(i + 1)
                            .getDma().getAma() -
                            downMinData)
                            * downDataRatio);
//                    paint.setColor(colors[1]);
//                    canvas.drawLine(lineStartX, startAMAY, lineEndX, endAMAY,
//                            paint);
                    if (i == position || (position <= 58 && i == 58)) {
                        path1.moveTo(lineStartX, startAMAY);
                    } else {
                        path1.lineTo(lineEndX, endAMAY);
                    }
                }
            }
            index++;
        }
        paint.setStyle(Style.STROKE);
        paint.setColor(colors[0]);
        canvas.drawPath(path, paint);
        paint.setColor(colors[1]);
        canvas.drawPath(path1, paint);
    }
    /**
     * 绘制TRIX
     *
     * @param canvas
     * @param paint
     */
    private void drawTRIX(Canvas canvas, Paint paint) {
        int[] colors = {0xff187cef, 0xfff5a623};// 白,黄
        downColors = colors;
        int index = 0;
        paint.setStrokeWidth(1);
        Path path = new Path();
        Path path1 = new Path();
        for (int i = position; i < data.size() - 1
                && i < candleNum + position - 1; i++) {
            KLineData entity = data.get(i);
            float lineStartX = getStrokeWidth() + getStrokeLeft() + dataSpacing
                    * index +
                    (dataSpacing * 0.75f / 2);
            float lineEndX = getStrokeWidth() + getStrokeLeft() + dataSpacing
                    * (index + 1) +
                    (dataSpacing * 0.75f / 2);
            if (i >= 33) {
                float startTRIXY = (float) (downChartBottom - (entity.getTrix()
                        .getTrix() - downMinData) *
                        downDataRatio);
                float endTRIXY = (float) (downChartBottom - (data.get(i + 1)
                        .getTrix().getTrix() -
                        downMinData)
                        * downDataRatio);
//                paint.setColor(colors[0]);
//                canvas.drawLine(lineStartX, startTRIXY, lineEndX, endTRIXY,
//                        paint);
                if (i == position || (position <= 33 && i == 33)) {
                    path.moveTo(lineStartX, startTRIXY);
                } else {
                    path.lineTo(lineEndX, endTRIXY);
                }
                if (i >= 52) {
                    float startMATRIXY = (float) (downChartBottom - (entity
                            .getTrix().getMaTrix() -
                            downMinData)
                            * downDataRatio);
                    float endMATRIXY = (float) (downChartBottom - (data
                            .get(i +
                                    1).getTrix().getMaTrix() -
                            downMinData)
                            * downDataRatio);
//                    paint.setColor(colors[1]);
//                    canvas.drawLine(lineStartX, startMATRIXY, lineEndX,
//                            endMATRIXY, paint);
                    if (i == position || (position <= 52 && i == 52)) {
                        path1.moveTo(lineStartX, startMATRIXY);
                    } else {
                        path1.lineTo(lineEndX, endMATRIXY);
                    }
                }
            }
            index++;
        }
        paint.setStyle(Style.STROKE);
        paint.setColor(colors[0]);
        canvas.drawPath(path, paint);
        paint.setColor(colors[1]);
        canvas.drawPath(path1, paint);
    }
    /**
     * 绘制上表左边Y刻度
     *
     * @param canvas 画布
     * @param paint  画笔
     */
    private void drawUpAxisXTitle(Canvas canvas, TextPaint paint,
                                  float dataWidth) {
        paint.setColor(getResources().getColor(R.color.text_color_5c5f66));
        if (!isDrawOutside) {
            float YData = upMaxData;
            float spacing = (upMaxData - upMinData) / (latitudesUpNum);
            for (int i = 0; i < latitudesUpNum + 1; i++) {
                if (i == 0) {
                    canvas.drawText(
                            Parse.getInstance().parse2String(upMaxData, num),
                            getStrokeWidth() + getStrokeLeft() + 2,
                            getStrokeWidth() + getStrokeTop() + textSize, paint);
                } else if (i == latitudesUpNum) {
                    canvas.drawText(
                            Parse.getInstance().parse2String(upMinData, num),
                            getStrokeWidth() + getStrokeLeft() + 2,
                            (getStrokeWidth() + getStrokeTop() + upLatitudesSpacing
                                    * latitudesUpNum) - 2, paint);
                } else {
                    canvas.drawText(Parse.getInstance()
                            .parse2String(YData, num), getStrokeWidth()
                            + getStrokeLeft() + 2, getStrokeWidth()
                            + getStrokeTop() +
                            textSize / 2
                            + upLatitudesSpacing *
                            i, paint);
                }
                YData -= spacing;
            }
        } else {
            float YData = upMaxData;
            float spacing = (upMaxData - upMinData) / (latitudesUpNum);
            for (int i = 0; i < latitudesUpNum + 1; i++) {
                // if (i < 2) {
                // paint.setColor(getResources().getColor(R.color.z_red));
                // } else if (i > 2) {
                // paint.setColor(getResources().getColor(R.color.z_green));
                // } else {
                // paint.setColor(getResources()
                // .getColor(R.color.z_list_title));
                // }
                if (i == 0) {
                    canvas.drawText(
                            Parse.getInstance().parse2String(YData, num),
                            getStrokeLeft()
                                    - getStrokeWidth()
                                    / 2
                                    - 2
                                    - paint.measureText(Parse.getInstance()
                                    .parse2String(YData, num)),
                            getStrokeWidth() + getStrokeTop() + textSize
                                    + upLatitudesSpacing * i, paint);
                } else if (i == latitudesUpNum) {
                    canvas.drawText(
                            Parse.getInstance().parse2String(YData, num),
                            getStrokeLeft()
                                    - getStrokeWidth()
                                    / 2
                                    - 2
                                    - paint.measureText(Parse.getInstance()
                                    .parse2String(YData, num)),
                            (getStrokeWidth() + getStrokeTop() + upLatitudesSpacing
                                    * i) - 2, paint);
                } else {
                    canvas.drawText(
                            Parse.getInstance().parse2String(YData, num),
                            getStrokeLeft()
                                    - getStrokeWidth()
                                    / 2
                                    - 2
                                    - paint.measureText(Parse.getInstance()
                                    .parse2String(YData, num)),
                            getStrokeWidth() + getStrokeTop() + textSize / 2
                                    + upLatitudesSpacing * i, paint);
                }
                YData -= spacing;
            }
        }
    }
    /**
     * 绘制下表Y轴X坐标
     *
     * @param canvas
     * @param paint
     */
    private void drawDownAxisXTitle(Canvas canvas, TextPaint paint,
                                    float dataWidth) {
        paint.setColor(getResources().getColor(R.color.text_color_5c5f66));
        float YData = downMinData;
        float spacing = (downMaxData - downMinData) / (latitudesDownNum);
        String text;
        if (!isDrawOutside) {
            for (int i = 0; i < latitudesDownNum + 1; i++) {
                if (mIndexType == IndexType.VOL || mMainIndexType == MainIndexType.BOLL) {
                    text = Parse.getInstance().parse2CNStringWan(YData, 2,
                            false);
                } else {
                    text = Parse.getInstance().parse2String(YData, num);
                }
                if (i == latitudesDownNum) {
                    canvas.drawText(text, getStrokeWidth() + getStrokeLeft()
                            + 2, downChartBottom + textSize
                            - downLatitudesSpacing * i, paint);
                } else if (i == 0) {
                    canvas.drawText(text, getStrokeWidth() + getStrokeLeft()
                                    + 2,
                            downChartBottom - downLatitudesSpacing * i - 2,
                            paint);
                } else {
                    canvas.drawText(text, getStrokeWidth() + getStrokeLeft()
                            + 2, downChartBottom + textSize / 2
                            - downLatitudesSpacing * i, paint);
                }
                YData += spacing;
            }
        } else {
            for (int i = 0; i < latitudesDownNum + 1; i++) {
                if (mIndexType == IndexType.VOL) {
                    text = Parse.getInstance().parse2CNStringWan(YData, 2,
                            false);
                } else if (mIndexType == IndexType.MACD
                     //   || mIndexType == IndexType.BOLL
                        || mIndexType == IndexType.KDJ
                        || mIndexType == IndexType.KD
                        || mIndexType == IndexType.RSI
                        || mIndexType == IndexType.BIAS
                        || mIndexType == IndexType.BRAR
                        || mIndexType == IndexType.CCI
                        || mIndexType == IndexType.DMI
                        || mIndexType == IndexType.CR
                        || mIndexType == IndexType.PSY
                        || mIndexType == IndexType.DMA
                        || mIndexType == IndexType.TRIX) {
                    text = Parse.getInstance().parse2String(YData, num);
                } else
                    text = Parse.getInstance().parse2CNStringWan(YData, 2,
                            false);
                if (i == latitudesDownNum) {
                    canvas.drawText(text, getStrokeLeft() - getStrokeWidth()
                                    / 2 - 2 - paint.measureText(text),
                            downChartBottom
                                    + textSize - downLatitudesSpacing * i, paint);
                } else if (i == 0) {
                    canvas.drawText(text, getStrokeLeft() - getStrokeWidth()
                                    / 2 - 2 - paint.measureText(text),
                            downChartBottom
                                    - downLatitudesSpacing * i - 2, paint);
                } else {
                    canvas.drawText(text, getStrokeLeft() - getStrokeWidth()
                                    / 2 - 2 - paint.measureText(text),
                            downChartBottom
                                    + textSize / 2 - downLatitudesSpacing * i, paint);
                }
                YData += spacing;
            }
        }
    }
    /**
     * 绘制十字光标
     *
     * @param canvas
     * @param paint
     */
    private void drawCrossLine(Canvas canvas, Paint paint, TextPaint tp) {
        if (isShowCrossLine) {
            paint.setStyle(Style.FILL);
            paint.setColor(getContext().getResources().getColor(
                    R.color.cross_line_color));
            paint.setStrokeWidth(1);
            canvas.drawLine(getStrokeWidth() + getStrokeLeft(), crossY,
                    viewWidth - getStrokeWidth() - getStrokeRight(), crossY,
                    paint);
            canvas.drawLine(crossX, getStrokeTop() + getStrokeWidth(), crossX,
                    upChartBottom, paint);
            canvas.drawLine(crossX, upChartBottom + spacing, crossX,
                    downChartBottom, paint);
            tp.setColor(Color.WHITE);
            // float textWidth =
            // tp.measureText(Parse.getInstance().parse2String(
            // leftData));
            float size = MyUtils.getInstance().dp2px(getContext(), 10);
            paint.setStrokeWidth(textSize + 6);
            String leftDatas = Parse.getInstance().parse2String(leftData, num);
            float topS = crossY - (textSize + 6) / 2 <= getStrokeTop()
                    + getStrokeWidth() ? getStrokeTop() +
                    getStrokeWidth()
                    + (textSize + 6) / 2
                    : crossY;
            topS = topS + (textSize + 6) / 2 >= upChartBottom ? upChartBottom
                    - (textSize + 6) / 2 : topS;
            float dataWidth = tp.measureText(leftDatas);
            if (!isDrawOutside) {
                canvas.drawLine(getStrokeLeft() + getStrokeWidth() / 2
                        + dataWidth + size, topS, getStrokeLeft()
                        + getStrokeWidth() / 2, topS, paint);
                canvas.drawText(leftDatas, getStrokeLeft() + getStrokeWidth()
                                / 2 + size / 2,
                        topS + textSize / 2 - 3, tp);
                /**
                 * 绘制时间
                 */
                String timeDatas;
                if (isShowTime) {
                    timeDatas = MyUtils.getInstance().date2String("yyyy/MM/dd HH:mm", date);
                } else {
                    if(data.get(0).getType() == T_D_TYPE){
                        timeDatas = MyUtils.getInstance().date2String("yyyy/MM/dd HH:mm:ss", date);
                        timeDatas  =  judgeTDNextDay(timeDatas);
                    }else {
                        timeDatas = MyUtils.getInstance().date2String("yyyy/MM/dd", date);
                    }
                }
                dataWidth = tp.measureText(timeDatas);
                float timeY = upChartBottom + textSize / 2;
                float drawTimeX = crossX - (dataWidth + size) / 2;
                if (drawTimeX <= getStrokeLeft() + getStrokeWidth() / 2) {
                    drawTimeX = getStrokeLeft() + getStrokeWidth() / 2;
                } else if (drawTimeX >= getWidth() - getStrokeRight()
                        - getStrokeWidth() / 2 - dataWidth - size) {
                    drawTimeX = getWidth() - getStrokeRight() - getStrokeWidth() / 2
                            - dataWidth - size;
                }
                canvas.drawLine(drawTimeX, timeY, drawTimeX + dataWidth + size, timeY, paint);
                canvas.drawText(timeDatas, drawTimeX + size / 2, timeY + textSize / 2, tp);
            } else {
                size = MyUtils.getInstance().dp2px(getContext(), 1);
                canvas.drawLine(getStrokeLeft() - getStrokeWidth() / 2
                        - dataWidth - size, topS, getStrokeLeft()
                        - getStrokeWidth() / 2, topS, paint);
                canvas.drawText(leftDatas, getStrokeLeft() - getStrokeWidth()
                                / 2 - dataWidth - size / 2,
                        topS + textSize / 2 - 3, tp);
                /**
                 * 绘制时间
                 */
                String timeDatas;
                if (isShowTime) {
                    timeDatas = MyUtils.getInstance().date2String("yyyy/MM/dd HH:mm", date);
                } else {
                    timeDatas = MyUtils.getInstance().date2String("yyyy/MM/dd", date);
                }
                dataWidth = tp.measureText(timeDatas);
                float timeY = upChartBottom + textSize / 2;
                float drawTimeX = crossX - (dataWidth + size) / 2;
                if (drawTimeX <= getStrokeLeft() + getStrokeWidth() / 2) {
                    drawTimeX = getStrokeLeft() + getStrokeWidth() / 2;
                } else if (drawTimeX >= getWidth() - getStrokeRight()
                        - getStrokeWidth() / 2 - dataWidth - size) {
                    drawTimeX = getWidth() - getStrokeRight() - getStrokeWidth() / 2
                            - dataWidth - size;
                }
                canvas.drawLine(drawTimeX, timeY, drawTimeX + dataWidth + size, timeY, paint);
                canvas.drawText(timeDatas, drawTimeX + size / 2, timeY + textSize / 2, tp);
            }
        }
    }
    /**
     * 画箭头
     *
     * @param sx
     * @param sy
     * @param ex
     * @param ey
     */
    public void drawAL(Canvas canvas, Paint paint, int sx, int sy, int ex, int ey) {
        double H = 8; // 箭头高度
        double L = 3.5; // 底边的一半
        int x3 = 0;
        int y3 = 0;
        int x4 = 0;
        int y4 = 0;
        double awrad = Math.atan(L / H); // 箭头角度
        double arraow_len = Math.sqrt(L * L + H * H); // 箭头的长度
        double[] arrXY_1 = rotateVec(ex - sx, ey - sy, awrad, true, arraow_len);
        double[] arrXY_2 = rotateVec(ex - sx, ey - sy, -awrad, true, arraow_len);
        double x_3 = ex - arrXY_1[0]; // (x3,y3)是第一端点
        double y_3 = ey - arrXY_1[1];
        double x_4 = ex - arrXY_2[0]; // (x4,y4)是第二端点
        double y_4 = ey - arrXY_2[1];
        Double X3 = new Double(x_3);
        x3 = X3.intValue();
        Double Y3 = new Double(y_3);
        y3 = Y3.intValue();
        Double X4 = new Double(x_4);
        x4 = X4.intValue();
        Double Y4 = new Double(y_4);
        y4 = Y4.intValue();
        // 画线
        canvas.drawLine(sx, sy, ex, ey, paint);
        Path triangle = new Path();
        triangle.moveTo(ex, ey);
        triangle.lineTo(x3, y3);
        triangle.lineTo(x4, y4);
        triangle.close();
        canvas.drawPath(triangle, paint);
    }
    // 计算
    public double[] rotateVec(int px, int py, double ang, boolean isChLen, double newLen) {
        double mathstr[] = new double[2];
        // 矢量旋转函数,参数含义分别是x分量、y分量、旋转角、是否改变长度、新长度
        double vx = px * Math.cos(ang) - py * Math.sin(ang);
        double vy = px * Math.sin(ang) + py * Math.cos(ang);
        if (isChLen) {
            double d = Math.sqrt(vx * vx + vy * vy);
            vx = vx / d * newLen;
            vy = vy / d * newLen;
            mathstr[0] = vx;
            mathstr[1] = vy;
        }
        return mathstr;
    }
    @TargetApi(Build.VERSION_CODES.FROYO)
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        obtainVelocityTracker(event);
        if (event.getActionMasked() == MotionEvent.ACTION_CANCEL) {
            releaseVelocityTracker();
        }
        switch (event.getAction() & MotionEvent.ACTION_MASK) {
            case MotionEvent.ACTION_DOWN:
                // 按下
                if (data != null)
                    stopDeceleration();
                downX = event.getX();
                downY = event.getY();
                if (downX < getStrokeLeft()
                        || downX > getWidth() - getStrokeRight()) {
                    return super.onTouchEvent(event);
                }
                moveX = event.getRawX();
                moveY = event.getRawY();
                // 记录触摸起始点坐标
                mTouchStartPoint.set(event.getX(), event.getY());
                touchMode = 0;
                // if (downX < getStrokeLeft() + getStrokeWidth() / 2) {
                // return false;
                // }
                isMoved = false;
                isReleased = false;
                isStartMoved = false;
                // isLeftRightMoved = false;
                getParent().requestDisallowInterceptTouchEvent(true);
                if (mRunnable != null) {
                    removeCallbacks(mRunnable);
                    postDelayed(mRunnable, 200);
                }
                return true;
            case MotionEvent.ACTION_POINTER_DOWN:
                // 多点
                if (downX < getStrokeLeft()
                        || downX > getWidth() - getStrokeRight()) {
                    return super.onTouchEvent(event);
                }
                if (data == null)
                    return false;
                // oldDistance = spacing(event);
                // 多点触摸一些起始性数据的记录
                if (event.getPointerCount() >= 2) {
                    mSavedXDist = ChartUtils.getXDist(event);
                    mSavedDist = ChartUtils.spacing(event);
                    if (mSavedDist > 10f) {
                        isMoved = true;
                        touchMode = TOUCH_ZOOM;
                    }
                    // 取得多点触摸的两点的中点
                    ChartUtils.midPoint(mTouchPointCenter, event);
                    // 得到触摸所在的位置,保持缩放后,触摸位置不变
                    mTouchPosition = calculationTouchPosition(mTouchPointCenter);
                    mTouchCandleNum = candleNum;
                    mTouchStartPosition = position;
                }
                return true;
            case MotionEvent.ACTION_MOVE:
                // 触摸
                if (downX < getStrokeLeft()
                        || downX > getWidth() - getStrokeRight()) {
                    return super.onTouchEvent(event);
                }
                if (data == null)
                    return false;
                // 子控件相对于父布局若达到滚动条件,则让父布局拦截触摸事件
                if (Math.abs(event.getRawY() - moveY) > 50
                        && Math.abs(event.getRawX() - moveX) < 150
                        && touchMode == 0) {
                    isMoved = true;
                    getParent().requestDisallowInterceptTouchEvent(false);
                }
                // 左右边侧触摸时,忽略事件
                // if (downX < getStrokeLeft() + getStrokeWidth() / 2) {
                // return false;
                // }
                if (touchMode == TOUCH_ZOOM) {
                    // 处理缩放
                    return performZoom(event);
                } else if (Math.abs(Math.abs(event.getX()) - Math.abs(downX)) > 50
                        && Math.abs(Math.abs(event.getY()) - Math.abs(downY)) < 150
                        && touchMode == 0) {
                    isMoved = true;
                    touchMode = TOUCH_DRAG;
                }
                if (touchMode == TOUCH_DRAG) {
                    return performDrag(event);
                } else if (touchMode == TOUCH_ADSORPTION) {
                    return performAsorption(event);
                }
                return true;
            case MotionEvent.ACTION_POINTER_UP:
                if (downX < getStrokeLeft()
                        || downX > getWidth() - getStrokeRight()) {
                    return super.onTouchEvent(event);
                }
                touchMode = 0;
                ChartUtils.velocityTrackerPointerUpCleanUpIfNecessary(event,
                        mVelocityTracker);
                return true;
            case MotionEvent.ACTION_UP:
                if (downX < getStrokeLeft()
                        || downX > getWidth() - getStrokeRight()) {
                    return super.onTouchEvent(event);
                }
                // 对一次完整的触摸时间做计算统计,判断是否为快速手势事件
                final VelocityTracker velocityTracker = mVelocityTracker;
                final int pointerId = event.getPointerId(0);
                velocityTracker.computeCurrentVelocity(1000,
                        ChartUtils.getMaximumFlingVelocity());
                final float velocityY = velocityTracker.getYVelocity(pointerId);
                final float velocityX = velocityTracker.getXVelocity(pointerId);
                // 重置上一次fling的距离为0
                mLastFlingDist = 0;
                if (Math.abs(velocityX) > ChartUtils.getMinimumFlingVelocity()) {
                    if (touchMode == TOUCH_DRAG) {
                        mDecelerationLastTime = AnimationUtils
                                .currentAnimationTimeMillis();
                        mDecelerationCurrentPoint = new PointF(event.getX(),
                                event.getY());
                        mDecelerationVelocity = new PointF(velocityX, velocityY);
                        ChartUtils.postInvalidateOnAnimation(this);
                    }
                }
                if (touchMode == 0 && Math.abs(downX - event.getX()) < 30
                        && Math.abs(downY - event.getY()) < 30) {
                    if (clickL != null)
                        clickL.click(this);
                }
                // 拿起
                touchMode = 0;
                getParent().requestDisallowInterceptTouchEvent(false);
                isReleased = true;
                isShowCrossLine = false;
                if (l != null && data != null)
                    l.transferData(this, false, crossX, upColors, downColors, data,
                            (position + candleNum) >= data.size() ? data.size() - 1
                                    : position +
                                    candleNum, mIndexType, num);
                invalidate();
                releaseVelocityTracker();
                return true;
            default:
                break;
        }
        return super.onTouchEvent(event);
    }
    /**
     * (non-Javadoc)
     *
     * @see View#computeScroll()
     * <p/>
     * 计算控件内容滚动。 此处的滚动并非视图的真正滚动,而是内容展示的滚动,根据手势记录下来的轨迹参数进行平滑的内容切换展示。
     */
    @Override
    public void computeScroll() {
        if (data == null)
            return;
        int size = data.size();
        if (mDecelerationVelocity.x == 0.f) {
            // 滚动结束
            return;
        }
        // 记录当前时间
        final long currentTime = AnimationUtils.currentAnimationTimeMillis();
        // 递减加速度范围(0-0.99],此值必须小于1且大于0的值,决定滚动的速度的快慢,越接近0速度越快
        mDecelerationVelocity.x *= 0.9;
        final float timeInterval = (float) (currentTime - mDecelerationLastTime) / 1000.f;
        float distanceX = mDecelerationVelocity.x * timeInterval;
        mDecelerationCurrentPoint.x += distanceX;
        MotionEvent event = MotionEvent.obtain(currentTime, currentTime,
                MotionEvent.ACTION_MOVE, mDecelerationCurrentPoint.x,
                mDecelerationCurrentPoint.y, 0);
        // 当前滚动的距离
        float currFlingDist = event.getX() - mTouchStartPoint.x;
        if (mLastFlingDist == 0)
            mLastFlingDist = currFlingDist;
        // 两次滚动距离的差,据此来计算滚动了多少个k线柱,两次滚动的值大于1个K线柱体的时候重绘视图
        float fingDist = currFlingDist - mLastFlingDist;
        if (Math.abs(fingDist) > dataSpacing) {
            mLastFlingDist = currFlingDist;
            if (fingDist < 0) {
                isMoved = true;
                // isLeftRightMoved = true;
                if (size < candleNum) {
                    return;
                } else {
                    int scaleCandle = (int) Math.abs(fingDist / dataSpacing);
                    for (int i = scaleCandle - 1; i >= 0; i--) {
                        position++;
                        if (position >= size - candleNum) {
                            position = size - candleNum;
                            invalidate();
                            break;
                        }
                        invalidate();
                    }
                }
            } else {
                isMoved = true;
                // isLeftRightMoved = true;
                if (size < candleNum) {
                    return;
                } else {
                    int scaleCandle = (int) Math.abs(fingDist / dataSpacing);
                    for (int i = scaleCandle - 1; i >= 0; i--) {
                        position--;
                        if (position <= 0) {
                            position = 0;
                            invalidate();
                            break;
                        }
                        invalidate();
                    }
                }
            }
        }
        event.recycle();
        mDecelerationLastTime = currentTime;
        if (Math.abs(mDecelerationVelocity.x) >= 1) {
            ChartUtils.postInvalidateOnAnimation(this); // This causes
            // computeScroll to
            // fire, recommended for
            // this by Google
        } else {
            stopDeceleration();
        }
    }
    /**
     * 减速运行结束,停止滚动
     */
    public void stopDeceleration() {
        mDecelerationVelocity = new PointF(0.f, 0.f);
    }
    private void obtainVelocityTracker(MotionEvent event) {
        if (mVelocityTracker == null) {
            mVelocityTracker = VelocityTracker.obtain();
        }
        mVelocityTracker.addMovement(event);
    }
    private void releaseVelocityTracker() {
        if (mVelocityTracker != null) {
            mVelocityTracker.recycle();
            mVelocityTracker = null;
        }
    }
    /**
     * 处理拖拽视图事件。
     *
     * @param event
     * @return
     */
    private boolean performDrag(MotionEvent event) {
        // 左右滑动事件
        float indexX = event.getRawX() - moveX;
        if (indexX < 0 - dataSpacing / 2) {
            moveX = event.getRawX();
            isMoved = true;
            // isLeftRightMoved = true;
            if (this.data.size() < candleNum) {
                return false;
            }
            int scaleCandle = (int) Math.abs(indexX / dataSpacing);
            if (scaleCandle == 0)
                scaleCandle = 1;
            position += scaleCandle;
            if (position >= this.data.size() - candleNum) {
                position = this.data.size() - candleNum;
            }
            invalidate();
            return true;
        } else if (indexX > dataSpacing / 2) {
            moveX = event.getRawX();
            isMoved = true;
            // isLeftRightMoved = true;
            if (this.data.size() < candleNum) {
                return false;
            }
            int scaleCandle = (int) Math.abs(indexX / dataSpacing);
            if (scaleCandle == 0)
                scaleCandle = 1;
            position -= scaleCandle;
            if (position <= 0) {
                position = 0;
            }
            invalidate();
            if (isLoadMore && position == 0) {
                isLoadMore = false;
                if (onLoadMoreListener != null)
                    onLoadMoreListener.onLoadMore();
            }
            return true;
        }
        return true;
    }
    /**
     * 处理十字光标视图事件。
     *
     * @param event
     * @return
     */
    private boolean performAsorption(MotionEvent event) {
        if (isStartMoved) {
            if (data != null && data.size() > 0) {
                calculationCrossLine(event);
                return true;
            }
        }
        return true;
    }
    /**
     * 多点触摸,根据手势进行放大或者缩小。
     *
     * @param event
     */
    @TargetApi(Build.VERSION_CODES.ECLAIR)
    private boolean performZoom(MotionEvent event) {
        if (event.getPointerCount() >= 2) {
            float totalDist = ChartUtils.spacing(event);
            if (totalDist > 10f) {
                float xDist = ChartUtils.getXDist(event);
                // x轴方向 scale
                float scaleX = xDist / mSavedXDist;
                // 是否缩小
                boolean isZoomingOut = (scaleX < 1);
                // Log.d(VIEW_LOG_TAG,
                // "touchPostion:"+mTouchPosition+",xDist:"+xDist+",mSavedXDist:"+mSavedXDist+",isZoomingOut:"+isZoomingOut+",scaleX:"+scaleX);
                if (!isZoomingOut) {
                    if (candleNum <= minCandleNum) {
                        // 无法继续放大
                        return false;
                    }
                } else {
                    if (candleNum >= maxCandleNum) {
                        // 无法继续缩小
                        return false;
                    }
                }
                isMoved = true;
                // Log.d(VIEW_LOG_TAG,
                // "position:"+position+",candleNum:"+candleNum);
                // 计算缩放后的position位置
                if (mTouchPosition != -1)
                    position = (int) (mTouchPosition - (mTouchPosition - mTouchStartPosition)
                            / scaleX);
                // 防止position超出边界
                if (position < 0)
                    position = 0;
                // 计算缩放后的candelNum大小
                candleNum = (int) (mTouchCandleNum / scaleX);
                invalidate();
            }
        }
        return true;
    }
    /**
     * 计算十字光标位置
     *
     * @param event
     */
    private void calculationCrossLine(MotionEvent event) {
        float startX = getStrokeWidth() + getStrokeLeft();
        int index = 0;
        for (int i = position; i < data.size() && i < candleNum + position; i++) {
            KLineData entity = data.get(i);
            // 柱形图
            float openY = upChartBottom
                    - ((float) entity.getOpen() - upMinData) * upDataRatio;
            float closeY = upChartBottom
                    - ((float) entity.getClose() - upMinData) * upDataRatio;
            // 中线
            // float highY = upChartBottom - (entity.getHigh() - upMinData)
            // * upDataRatio;
            // float lowY = upChartBottom - (entity.getLow() - upMinData)
            // * upDataRatio;
            float endX = getStrokeWidth() + getStrokeLeft()
                    + (dataSpacing * (index + 1) - dataSpacing * 0.25f);
            if (event.getX() > startX && event.getX() < endX) {
                isShowCrossLine = true;
                crossX = (endX - startX) / 2 + startX;
                if (openY < closeY) {// 绿色
                    crossY = closeY;
                } else if (openY > closeY) {// 红色
                    crossY = closeY;
                } else {// 红色
                    crossY = openY;
                }
                leftData = Parse.getInstance().parseFloat(
                        Parse.getInstance()
                                .parse2String(entity.getClose(), num));
                date = entity.getTime() * 1000;
                if (l != null) {
                    l.transferData(this, true, crossX, upColors, downColors,
                            data, i, mIndexType, num);
                }
                invalidate();
                return;
            }
            startX = getStrokeWidth() + getStrokeLeft() + dataSpacing
                    * (index + 1);
            index++;
        }
    }
    /**
     * 计算触摸所在的数据位置
     */
    private int calculationTouchPosition(PointF point) {
        float startX = getStrokeWidth() + getStrokeLeft();
        int index = 0;
        for (int i = position; i < data.size() && i < candleNum + position && i >= 0; i++) {
            KLineData entity = data.get(i);
            // 柱形图
            // float openY = upChartBottom
            // - ((float) entity.getOpen() - upMinData) * upDataRatio;
            // float closeY = upChartBottom
            // - ((float) entity.getClose() - upMinData) * upDataRatio;
            // 中线
            // float highY = upChartBottom - (entity.getHigh() - upMinData)
            // * upDataRatio;
            // float lowY = upChartBottom - (entity.getLow() - upMinData)
            // * upDataRatio;
            float endX = getStrokeWidth() + getStrokeLeft()
                    + (dataSpacing * (index + 1) - dataSpacing * 0.25f);
            if (point.x > startX && point.x < endX) {
                return i;
            }
            startX = getStrokeWidth() + getStrokeLeft() + dataSpacing
                    * (index + 1);
            index++;
        }
        return -1;
    }
    /**
     * 获取字体大小(像素单位)
     *
     * @return
     */
    public float getTextSize() {
        return textSize;
    }
    /**
     * 设置字体大小(像素单位)
     *
     * @param textSize
     */
    public void setTextSize(float textSize) {
        this.textSize = textSize;
    }
    /**
     * 获取上表与下表间距
     *
     * @return
     */
    public float getSpacing() {
        return spacing;
    }
    /**
     * 设置上表与下表间距
     *
     * @param spacing
     */
    public void setSpacing(float spacing) {
        if (spacing < MyUtils.getInstance().dp2px(getContext(),
                DEFAULT_TEXT_SIZE)) {
            spacing = MyUtils.getInstance().dp2px(getContext(),
                    DEFAULT_TEXT_SIZE) * 2;
        } else {
            this.spacing = spacing;
        }
    }
    /**
     * 获取上表底部与控件顶部距离(是负值)
     *
     * @return
     */
    public float getUpChartBottom() {
        return upChartBottom;
    }
    /**
     * 获取
     *
     * @return
     */
    public float getUpChartHeight() {
        return Math.abs(upChartHeight);
    }
    /**
     * 获取下表高度
     *
     * @return
     */
    public float getDownChartHeight() {
        return downChartHeight;
    }
    /**
     * 设置数据
     *
     * @param data
     */
    public synchronized void setData(Vector<KLineData> data, IndexType type, MainIndexType mainIndexType) {
        if (this.data == null) {
            if (data == null || data.size() < candleNum) {
                position = 0;
            } else {
                position = data.size() - candleNum;
            }
        } else {
            if (data == null || data.size() < candleNum) {
                position = 0;
            } else if (position > data.size() - candleNum) {
                position = data.size() - candleNum;
            } else if (position < 0) {
                position = 0;
            } else if (isLoadMore) {
                position += oldSize;
                oldSize = 0;
                if (position > data.size() - candleNum) {
                    position = data.size() - candleNum;
                }
            }
        }
        notifyRunnable.setData(data, type, mainIndexType);
        executorService.execute(notifyRunnable);
    }
    /**
     * 设置时间显示样式(true:显示yyyy/MM/dd HH:mm;false:显示yyyy/MM/dd)
     *
     * @param isShowTime
     */
    public void setShowTime(boolean isShowTime) {
        this.isShowTime = isShowTime;
    }
    /**
     * 清除K线
     */
    public void clean() {
        this.data = null;
        invalidate();
    }
    /**
     * 更新数据、指标的线程
     *
     * @author dingrui
     */
    class NotifyRunnable implements Runnable {
        private Vector<KLineData> dataOld;
        private IndexType type;
        private MainIndexType mainIndexType;
        public NotifyRunnable() {
            dataOld = null;
            type = IndexType.VOL;
        }
        public void setData(Vector<KLineData> data, IndexType type, MainIndexType mainIndexType) {
            this.dataOld = data;
            this.type = type;
            this.mainIndexType = mainIndexType;
        }
        public IndexType getType() {
            return type;
        }
        @Override
        public void run() {
            // TODO Auto-generated method stub
            //加入同步锁
            synchronized (this) {
            if (null == dataOld) {
                return;
            }
                Vector<KLineData> data = new Vector<>();
                for (int i = 0; i < dataOld.size(); i++) {
                    KLineData oldItem = dataOld.get(i);
                    KLineData item = new KLineData();
                    item.setType(oldItem.getType());
                    item.setTime(oldItem.getTime());
                    item.setClose(oldItem.getClose());
                    item.setOpen(oldItem.getOpen());
                    item.setLowPrice(oldItem.getLowPrice());
                    item.setHighPrice(oldItem.getHighPrice());
                    item.setCjl(oldItem.getCjl());
                    item.setCje(oldItem.getCje());
                    data.add(item);
                }
                if (mainIndexType == MainIndexType.BOLL) {
                    data = IndexCalculation.calculationBOLL(data);
                }
                if (type == IndexType.VOL) {
                    data = IndexCalculation.calculationVol(data);
                } else if (type == IndexType.MACD) {
                    // 计算MACD
                    data = IndexCalculation.calculationMACD(data);
                }/* else if (type == IndexType.BOLL) {
                // 计算布林指标
                data = IndexCalculation.calculationBOLL(data);
                data = IndexCalculation.calculationVol(data);
            }*/ else if (type == IndexType.KDJ || type == IndexType.KD) {
                    // 计算KDJ
                    data = IndexCalculation.calculationKDJ(data);
                } else if (type == IndexType.RSI) {
                    // 计算RSI
                    data = IndexCalculation.calculationRSI(data);
                } else if (type == IndexType.BIAS) {
                    // 计算BIAS
                    data = IndexCalculation.calculationBIAS(data);
                } else if (type == IndexType.BRAR) {
                    // 计算BRAR
                    data = IndexCalculation.calculationBRAR(data);
                } else if (type == IndexType.CCI) {
                    // 计算CCI
                    data = IndexCalculation.calculationCCI(data);
                } else if (type == IndexType.DMI) {
                    // 计算DMI
                    data = IndexCalculation.calculationDMI(data);
                } else if (type == IndexType.CR) {
                    // 计算CR
                    data = IndexCalculation.calculationCR(data);
                } else if (type == IndexType.PSY) {
                    // 计算PSY
                    data = IndexCalculation.calculationPSY(data);
                } else if (type == IndexType.DMA) {
                    // 计算DMA
                    data = IndexCalculation.calculationDMA(data);
                } else if (type == IndexType.TRIX) {
                    // 计算TRIX
                    data = IndexCalculation.calculationTRIX(data);
                }
                Bundle bundle = new Bundle();
                bundle.putSerializable("data", data);
                if (mainIndexType == MainIndexType.MA) {
                    bundle.putInt("mainindex", 0);
                } else if (mainIndexType == MainIndexType.BOLL) {
                    bundle.putInt("mainindex", 1);
                }
                Message msg = handler.obtainMessage();
                msg.what = 0x1;
                msg.setData(bundle);
                msg.obj = type;
                handler.sendMessage(msg);
            }
        }
    }
    public IndexType getIndexType() {
        return notifyRunnable.getType();
    }
    /**
     * 是否设置了将坐标绘制在框外
     *
     * @return
     */
    public boolean isDrawOutside() {
        return isDrawOutside;
    }
    /**
     * 设置是否将两边坐标值绘制在边框线外(注:如果设置成true,必须设置strokeLeft和strokeRight)
     *
     * @param strokeLeft  左边距
     * @param strokeRight 右边距
     */
    public void setDrawOutside(boolean isDrawOutside, float strokeLeft,
                               float strokeRight) {
        this.isDrawOutside = isDrawOutside;
        if (isDrawOutside == false) {
            setStrokeLeft(1.0f);
            setStrokeRight(1.0f);
        } else {
            setStrokeLeft(strokeLeft);
            setStrokeRight(strokeRight);
        }
        invalidate();
    }
    /**
     * 设置当前显示k线数量
     *
     * @param candleNum
     */
    public void setCandleNum(int candleNum) {
        this.candleNum = candleNum;
        if (data == null || data.size() < candleNum) {
            position = 0;
        } else {
            position = data.size() - candleNum;
        }
    }
    /**
     * 设置当前显示K线数量上限
     *
     * @param maxCandleNum
     */
    public void setMaxCandleNum(int maxCandleNum) {
        this.maxCandleNum = maxCandleNum;
    }
    /**
     * 设置当前显示K线数量下限
     *
     * @param minCandleNum
     */
    public void setMinCandleNum(int minCandleNum) {
        this.minCandleNum = minCandleNum;
    }
    /**
     * 加载完成并开启加载更多接口
     *
     * @param oldDataSize 加载更多后的数据长度
     */
    public void loadMoreFinish(int oldDataSize) {
        isLoadMore = true;
        oldSize = oldDataSize;
    }
    /**
     * 小数保留位数
     *
     * @param num
     */
    public void setNum(int num) {
        this.num = num;
        invalidate();
    }
    /**
     * 设置接口
     *
     * @param l
     */
    public void setKLineListener(KLineListener l) {
        this.l = l;
    }
    /**
     * 接口
     *
     * @author dingrui
     */
    public interface KLineListener {
        public void transferData(View view, boolean isMoved, float touchX,
                                 int[] upColors, int[] downColors, Vector<KLineData> data,
                                 int position, IndexType mIndexType, int num);
    }
    /**
     * 设置点击事件接口
     *
     * @param l
     */
    public void setOnKLineChartClickListener(OnKLineChartClickListener l) {
        this.clickL = l;
    }
    /**
     * 单击事件接口
     *
     * @author dingrui
     */
    public interface OnKLineChartClickListener {
        public void click(View v);
    }
    /**
     * 设置加载更多接口
     *
     * @param onLoadMoreListener
     */
    public void setOnLoadMoreListener(OnLoadMoreListener onLoadMoreListener) {
        this.onLoadMoreListener = onLoadMoreListener;
    }
    /**
     * 加载更多接口
     */
    public interface OnLoadMoreListener {
        public void onLoadMore();
    }
}
package com.kedll.kedelllibrary.stock;
import java.io.Serializable;
public class KLineData implements Serializable {
    /**
     * 区分交易品种
     */
    private int type;
    /**
     * 是否绘制时间和经线
     */
    private boolean isDrawLongitude;
    /**
     * 时间
     */
    private long time;
    /**
     * 开盘价
     */
    private double open;
    /**
     * 收盘价
     */
    private double close;
    /**
     * 最高价
     */
    private double highPrice;
    /**
     * 最低价
     */
    private double lowPrice;
    /**
     * 成交额原始数据(非累加)
     */
    private double cje;
    /**
     * 成交量原始数据(非累加)
     */
    private double cjl;
    /**
     * 涨跌
     */
    private double change;
    /**
     * 涨跌幅
     */
    private double changep;
    /**
     * 均线
     */
    private DayMovingAverage dayMovingAverage;
    /** 指标相关 */
    /**
     * 成交量
     */
    private Volume volume;
    /**
     * 指数平滑异同平均线(MACD指标)
     */
    private MACD macd;
    /**
     * 动向指标
     */
    private DMI dmi;
    /**
     * 威廉指标
     */
    private WR wr;
    /**
     * 布林线
     */
    private BOLL boll;
    /**
     * 随机指标(KDJ)
     */
    private KDJ kdj;
    /**
     * OBV指标(统计成交量变动的趋势来推测股价趋势)
     */
    private OBV obv;
    /**
     * 强弱指标
     */
    private RSI rsi;
    /**
     * 停损转向操作点指标
     */
    private SAR sar;
    /**
     * 乖离率(BIAS)是测量股价偏离均线大小程度的指标
     */
    private BIAS bias;
    /**
     * 情绪指标(BRAR)也称为人气意愿指标
     */
    private BRAR brar;
    /**
     * 顺势指标
     */
    private CCI cci;
    /**
     * 能量指标
     */
    private CR cr;
    /**
     * 心理线(PSY)指标是研究投资者对股市涨跌产生心理波动的情绪指标
     */
    private PSY psy;
    /**
     * 平行线差指标
     */
    private DMA dma;
    /**
     * 三重指数平滑平均线(TRIX)属于长线指标
     */
    private TRIX trix;
    public KLineData() {
    }
    /**
     * 构造函数
     *
     * @param time      时间
     * @param open      开盘价
     * @param close     收盘价
     * @param highPrice 最高价
     * @param lowPrice  最低价
     * @param cje       成交额
     * @param cjl       成交量
     */
    public KLineData(long time, double open, double close, double highPrice,
                     double lowPrice, double cje, double cjl) {
        this.time = time;
        this.open = open;
        this.close = close;
        this.highPrice = highPrice;
        this.lowPrice = lowPrice;
        this.cje = cje;
        this.cjl = cjl;
    }
    public int getType() {
        return type;
    }
    public void setType(int type) {
        this.type = type;
    }
    public boolean isDrawLongitude() {
        return isDrawLongitude;
    }
    public void setDrawLongitude(boolean isDrawLongitude) {
        this.isDrawLongitude = isDrawLongitude;
    }
    public long getTime() {
        return time;
    }
    public void setTime(long time) {
        this.time = time;
    }
    public double getOpen() {
        return open;
    }
    public void setOpen(double open) {
        this.open = open;
    }
    public double getClose() {
        return close;
    }
    public void setClose(double close) {
        this.close = close;
    }
    public double getHighPrice() {
        return highPrice;
    }
    public void setHighPrice(double highPrice) {
        this.highPrice = highPrice;
    }
    public double getLowPrice() {
        return lowPrice;
    }
    public void setLowPrice(double lowPrice) {
        this.lowPrice = lowPrice;
    }
    public double getCje() {
        return cje;
    }
    public void setCje(double cje) {
        this.cje = cje;
    }
    public double getCjl() {
        return cjl;
    }
    public void setCjl(double cjl) {
        this.cjl = cjl;
    }
    public double getChange() {
        return change;
    }
    public void setChange(double change) {
        this.change = change;
    }
    public double getChangep() {
        return changep;
    }
    public void setChangep(double changep) {
        this.changep = changep;
    }
    public DayMovingAverage getDayMovingAverage() {
        return dayMovingAverage == null ? new DayMovingAverage(0, 0, 0)
                                        : dayMovingAverage;
    }
    public void setDayMovingAverage(DayMovingAverage dayMovingAverage) {
        this.dayMovingAverage = dayMovingAverage;
    }
    public Volume getVolume() {
        return volume == null ? new Volume(0, 0, 0, 0) : volume;
    }
    public void setVolume(Volume volume) {
        this.volume = volume;
    }
    public MACD getMacd() {
        return macd;
    }
    public void setMacd(MACD macd) {
        this.macd = macd;
    }
    public DMI getDmi() {
        return dmi;
    }
    public void setDmi(DMI dmi) {
        this.dmi = dmi;
    }
    public WR getWr() {
        return wr;
    }
    public void setWr(WR wr) {
        this.wr = wr;
    }
    public BOLL getBoll() {
        return boll;
    }
    public void setBoll(BOLL boll) {
        this.boll = boll;
    }
    public KDJ getKdj() {
        return kdj;
    }
    public void setKdj(KDJ kdj) {
        this.kdj = kdj;
    }
    public OBV getObv() {
        return obv;
    }
    public void setObv(OBV obv) {
        this.obv = obv;
    }
    public RSI getRsi() {
        return rsi;
    }
    public void setRsi(RSI rsi) {
        this.rsi = rsi;
    }
    public SAR getSar() {
        return sar;
    }
    public void setSar(SAR sar) {
        this.sar = sar;
    }
    public BIAS getBias() {
        return bias;
    }
    public void setBias(BIAS bias) {
        this.bias = bias;
    }
    public BRAR getBrar() {
        return brar;
    }
    public void setBrar(BRAR brar) {
        this.brar = brar;
    }
    public CCI getCci() {
        return cci;
    }
    public void setCci(CCI cci) {
        this.cci = cci;
    }
    public CR getCr() {
        return cr;
    }
    public void setCr(CR cr) {
        this.cr = cr;
    }
    public PSY getPsy() {
        return psy;
    }
    public void setPsy(PSY psy) {
        this.psy = psy;
    }
    public DMA getDma() {
        return dma;
    }
    public void setDma(DMA dma) {
        this.dma = dma;
    }
    public TRIX getTrix() {
        return trix;
    }
    public void setTrix(TRIX trix) {
        this.trix = trix;
    }
    /**
     * 均线
     *
     * @author dingrui
     */
    public static class DayMovingAverage implements Serializable {
        /**
         * 5日均线
         */
        private double ma5;
        /**
         * 10日均线
         */
        private double ma10;
        /**
         * 20日均线
         */
        private double ma20;
        public DayMovingAverage() {
        }
        public DayMovingAverage(double ma5, double ma10, double ma20) {
            this.ma5 = ma5;
            this.ma10 = ma10;
            this.ma20 = ma20;
        }
        public double getMa5() {
            return ma5;
        }
        public void setMa5(double ma5) {
            this.ma5 = ma5;
        }
        public double getMa10() {
            return ma10;
        }
        public void setMa10(double ma10) {
            this.ma10 = ma10;
        }
        public double getMa20() {
            return ma20;
        }
        public void setMa20(double ma20) {
            this.ma20 = ma20;
        }
    }
    /**
     * 成交量指标
     *
     * @author dingrui
     */
    public static class Volume implements Serializable {
        /**
         * 成交量
         */
        private double num;
        /**
         * 均线
         */
        private double ma5;
        private double ma10;
        private double ma20;
        public Volume(double num, double ma5, double ma10, double ma20) {
            this.num = num;
            this.ma5 = ma5;
            this.ma10 = ma10;
            this.ma20 = ma20;
        }
        public double getNum() {
            return num;
        }
        public void setNum(double num) {
            this.num = num;
        }
        public double getMa5() {
            return ma5;
        }
        public void setMa5(double ma5) {
            this.ma5 = ma5;
        }
        public double getMa10() {
            return ma10;
        }
        public void setMa10(double ma10) {
            this.ma10 = ma10;
        }
        public double getMa20() {
            return ma20;
        }
        public void setMa20(double ma20) {
            this.ma20 = ma20;
        }
    }
    /**
     * 指数平滑异同平均线(MACD指标)
     *
     * @author dingrui
     */
    public static class MACD implements Serializable {
        private double diff;
        private double dea;
        private double macd;
        public MACD(double diff, double dea, double macd) {
            this.diff = diff;
            this.dea = dea;
            this.macd = macd;
        }
        public double getDiff() {
            return diff;
        }
        public void setDiff(double diff) {
            this.diff = diff;
        }
        public double getDea() {
            return dea;
        }
        public void setDea(double dea) {
            this.dea = dea;
        }
        public double getMacd() {
            return macd;
        }
        public void setMacd(double macd) {
            this.macd = macd;
        }
    }
    /**
     * 动向指标
     *
     * @author dingrui
     */
    public static class DMI implements Serializable {
        private double pdi;
        private double mdi;
        private double adx;
        private double adxr;
        public DMI(double pdi, double mdi, double adx, double adxr) {
            this.pdi = pdi;
            this.mdi = mdi;
            this.adx = adx;
            this.adxr = adxr;
        }
        public double getPdi() {
            return pdi;
        }
        public void setPdi(double pdi) {
            this.pdi = pdi;
        }
        public double getMdi() {
            return mdi;
        }
        public void setMdi(double mdi) {
            this.mdi = mdi;
        }
        public double getAdx() {
            return adx;
        }
        public void setAdx(double adx) {
            this.adx = adx;
        }
        public double getAdxr() {
            return adxr;
        }
        public void setAdxr(double adxr) {
            this.adxr = adxr;
        }
    }
    /**
     * 威廉指标
     *
     * @author dingrui
     */
    public class WR implements Serializable {
        private double wr1;
        private double wr2;
        public WR(double wr1, double wr2) {
            this.wr1 = wr1;
            this.wr2 = wr2;
        }
        public double getWr1() {
            return wr1;
        }
        public void setWr1(double wr1) {
            this.wr1 = wr1;
        }
        public double getWr2() {
            return wr2;
        }
        public void setWr2(double wr2) {
            this.wr2 = wr2;
        }
    }
    /**
     * 布林线
     *
     * @author dingrui
     */
    public static class BOLL implements Serializable {
        private double upper;
        private double mID;
        private double lower;
        public BOLL(double upper, double mID, double lower) {
            this.upper = upper;
            this.mID = mID;
            this.lower = lower;
        }
        public double getUpper() {
            return upper;
        }
        public void setUpper(double upper) {
            this.upper = upper;
        }
        public double getmID() {
            return mID;
        }
        public void setmID(double mID) {
            this.mID = mID;
        }
        public double getLower() {
            return lower;
        }
        public void setLower(double lower) {
            this.lower = lower;
        }
    }
    /**
     * 随机指标(KDJ)
     *
     * @author dingrui
     */
    public static class KDJ implements Serializable {
        private double K;
        private double D;
        private double J;
        public KDJ(double K, double D, double J) {
            this.K = K;
            this.D = D;
            this.J = J;
        }
        public double getK() {
            return K;
        }
        public void setK(double k) {
            K = k;
        }
        public double getD() {
            return D;
        }
        public void setD(double d) {
            D = d;
        }
        public double getJ() {
            return J;
        }
        public void setJ(double j) {
            J = j;
        }
    }
    /**
     * OBV指标(统计成交量变动的趋势来推测股价趋势)
     *
     * @author dingrui
     */
    public class OBV implements Serializable {
        private double obv;
        public OBV(double obv) {
            this.obv = obv;
        }
        public double getObv() {
            return obv;
        }
        public void setObv(double obv) {
            this.obv = obv;
        }
    }
    /**
     * 强弱指标
     *
     * @author dingrui
     */
    public static class RSI implements Serializable {
        private double rsi6;
        private double rsi12;
        private double rsi24;
        public RSI(double rsi6, double rsi12, double rsi24) {
            this.rsi6 = rsi6;
            this.rsi12 = rsi12;
            this.rsi24 = rsi24;
        }
        public double getRsi6() {
            return rsi6;
        }
        public void setRsi6(double rsi6) {
            this.rsi6 = rsi6;
        }
        public double getRsi12() {
            return rsi12;
        }
        public void setRsi12(double rsi12) {
            this.rsi12 = rsi12;
        }
        public double getRsi24() {
            return rsi24;
        }
        public void setRsi24(double rsi24) {
            this.rsi24 = rsi24;
        }
    }
    /**
     * 停损转向操作点指标
     *
     * @author dingrui
     */
    public class SAR implements Serializable {
        private double sar;
        public SAR(double sar) {
            this.sar = sar;
        }
        public double getSar() {
            return sar;
        }
        public void setSar(double sar) {
            this.sar = sar;
        }
    }
    /**
     * 乖离率(BIAS)是测量股价偏离均线大小程度的指标
     *
     * @author dingrui
     */
    public static class BIAS implements Serializable {
        private double bias1;// 5
        private double bias2;// 10
        private double bias3;// 20
        public BIAS(double bias1, double bias2, double bias3) {
            this.bias1 = bias1;
            this.bias2 = bias2;
            this.bias3 = bias3;
        }
        public double getBias1() {
            return bias1;
        }
        public void setBias1(double bias1) {
            this.bias1 = bias1;
        }
        public double getBias2() {
            return bias2;
        }
        public void setBias2(double bias2) {
            this.bias2 = bias2;
        }
        public double getBias3() {
            return bias3;
        }
        public void setBias3(double bias3) {
            this.bias3 = bias3;
        }
    }
    /**
     * 情绪指标(BRAR)也称为人气意愿指标
     *
     * @author dingrui
     */
    public static class BRAR implements Serializable {
        private double br;
        private double ar;
        public BRAR(double br, double ar) {
            this.br = br;
            this.ar = ar;
        }
        public double getBr() {
            return br;
        }
        public void setBr(double br) {
            this.br = br;
        }
        public double getAr() {
            return ar;
        }
        public void setAr(double ar) {
            this.ar = ar;
        }
    }
    /**
     * 顺势指标
     *
     * @author dingrui
     */
    public static class CCI implements Serializable {
        private double cci;
        public CCI(double cci) {
            this.cci = cci;
        }
        public double getCci() {
            return cci;
        }
        public void setCci(double cci) {
            this.cci = cci;
        }
    }
    /**
     * 能量指标
     *
     * @author dingrui
     */
    public static class CR implements Serializable {
        private double cr;
        private double ma1;
        private double ma2;
        private double ma3;
        public CR(double cr, double ma1, double ma2, double ma3) {
            this.cr = cr;
            this.ma1 = ma1;
            this.ma2 = ma2;
            this.ma3 = ma3;
        }
        public double getCr() {
            return cr;
        }
        public void setCr(double cr) {
            this.cr = cr;
        }
        public double getMa1() {
            return ma1;
        }
        public void setMa1(double ma1) {
            this.ma1 = ma1;
        }
        public double getMa2() {
            return ma2;
        }
        public void setMa2(double ma2) {
            this.ma2 = ma2;
        }
        public double getMa3() {
            return ma3;
        }
        public void setMa3(double ma3) {
            this.ma3 = ma3;
        }
    }
    /**
     * 心理线(PSY)指标是研究投资者对股市涨跌产生心理波动的情绪指标
     *
     * @author dingrui
     */
    public static class PSY implements Serializable {
        private double psy;
        public PSY(double psy) {
            this.psy = psy;
        }
        public double getPsy() {
            return psy;
        }
        public void setPsy(double psy) {
            this.psy = psy;
        }
    }
    /**
     * 平行线差指标
     *
     * @author dingrui
     */
    public static class DMA implements Serializable {
        private double dif;
        private double ama;
        public DMA(double dif, double ama) {
            this.dif = dif;
            this.ama = ama;
        }
        public double getDif() {
            return dif;
        }
        public void setDif(double dif) {
            this.dif = dif;
        }
        public double getAma() {
            return ama;
        }
        public void setAma(double ama) {
            this.ama = ama;
        }
    }
    /**
     * 三重指数平滑平均线(TRIX)属于长线指标
     *
     * @author dingrui
     */
    public static class TRIX implements Serializable {
        private double trix;
        private double maTrix;
        public TRIX(double trix, double maTrix) {
            this.trix = trix;
            this.maTrix = maTrix;
        }
        public double getTrix() {
            return trix;
        }
        public void setTrix(double trix) {
            this.trix = trix;
        }
        public double getMaTrix() {
            return maTrix;
        }
        public void setMaTrix(double maTrix) {
            this.maTrix = maTrix;
        }
    }
}