股票K線指標算法整理(Java封裝工具類)

 

工具類下載地址:

https://download.csdn.net/download/qq_28844947/11088865

 

可查看應用效果之一:https://www.coinsmt.com/fullScreen/huobipro_btc_usdt

目前是java實現  使用在MPAndroid上面,其他語言和圖表工具類比過去,可以然後將X,Y賦值過去

使用需知 chart_base_entity所有的類是你選用圖表時候對應的數據 需要去掉目前支持如下指標(多週期,及其他算法參數)

  1. EMA
  2. BOLL
  3. CCI
  4. DMI
  5. KDJ
  6. MACD
  7. OBV
  8. RSI
  9. SAR
  10. VOL
  11. WR

已封裝爲工具類可按如下調用


  • 使用方法

      //注意事項
            // 使用需知 chart_base_entity所有的類是你選用圖表時候對應的數據 需要去掉
            //現在爲了和圖表隔離 提供單純的算法工具類 所以才提供了臨時的Entry Candle BarEntry等
            ChartDataCalculateUtils calculateUtils = new ChartDataCalculateUtils("你的數據List<Candle>你根據你實際使用的圖表進行替換");
    
            //部分指標需要選擇週期 如EMA7 EMA10
            List<Integer> periods = Arrays.asList(7, 10);
            calculateUtils.getEMA()
            calculateUtils.getBollData()
            calculateUtils.getCCI()
            calculateUtils.getDMI()
            calculateUtils.getKDJ()
            calculateUtils.getMACD()
            calculateUtils.getOBV()
            calculateUtils.getRSI()
            calculateUtils.getSARLineDatas()
            calculateUtils.getVol()
            calculateUtils.getWR()
  • 核心源碼
     

    package com.beidd.lib.chart_data_utils;
    
    import com.beidd.lib.chart_data_utils.chart_base_entity.BarEntry;
    import com.beidd.lib.chart_data_utils.entity.BollEntity;
    import com.beidd.lib.chart_data_utils.entity.CCIEntity;
    import com.beidd.lib.chart_data_utils.chart_base_entity.Candle;
    import com.beidd.lib.chart_data_utils.entity.DMIEntity;
    import com.beidd.lib.chart_data_utils.entity.EMAEntity;
    import com.beidd.lib.chart_data_utils.chart_base_entity.Entry;
    import com.beidd.lib.chart_data_utils.entity.EntryType;
    import com.beidd.lib.chart_data_utils.entity.ICandle;
    import com.beidd.lib.chart_data_utils.entity.KDJEntity;
    import com.beidd.lib.chart_data_utils.entity.MACDEntity;
    import com.beidd.lib.chart_data_utils.entity.OBVEntity;
    import com.beidd.lib.chart_data_utils.entity.RSIEntity;
    import com.beidd.lib.chart_data_utils.entity.VolEntity;
    import com.beidd.lib.chart_data_utils.entity.WREntity;
    
    import java.util.ArrayList;
    import java.util.List;
    
    /**
     * Created by Rex on 2018/11/12.
     * 只負責計算指標 可選週期
     */
    public class ChartDataCalculateUtils {
    
    
        private List<Candle> originData;
    
        public ChartDataCalculateUtils(List<Candle> originData) {
            this.originData = originData;
        }
    
    
        public List<Entry> getSARLineDatas(float step, float maxStep, int period, int index) {
    
            List<ICandle> iCandles = changeCandleToICandle(originData);
            NewSarUtils.prepareDataForSARFromIndex(step, maxStep, period, index, iCandles);
    
    
            List<Entry> sars = new ArrayList<>();
            for (int i = 0; i < iCandles.size(); i++) {
                float sar = iCandles.get(i).sar;
                sars.add(new Entry(i, sar, originData.get(i)));
            }
    
            return sars;
    
        }
    
    
        /**
         * @param T boll T 一般默認爲20
         * @param K boll K 一般默認爲2
         * @return
         */
        public BollEntity getBollData(int T, int K) {
    
            if (originData == null || originData.size() == 0) {
                return null;
            }
    
            if (T < 1 || K < 1) {
                return null;
            }
            if (originData == null || originData.isEmpty()) {
                return null;
            }
            if (T > originData.size()) {
                return null;
            }
            //存儲上軌數據
            ArrayList<Entry> zhongList = new ArrayList();
            //存儲中軌數據
            ArrayList<Entry> shangList = new ArrayList();
            //存儲下軌數據
            ArrayList<Entry> xiaList = new ArrayList();
    
            //上軌
            Entry shangEntity;
            //中軌
            Entry zhongEntity;
            //下軌
            Entry xiaEntity;
    
            double standtard = 0;
            double squarSum = 0;
    
            int cycle = T;
    
            List<Double> sma = countMA(T);
            if (sma == null || sma.size() == 0) {
                return null;
            }
            for (int i = cycle - 1; i < originData.size(); i++) {
                Candle candle = originData.get(i);
                double smaValue = sma.get(i - T + 1).doubleValue();
    
                standtard = 0;
    
                for (int j = i - T + 1; j <= i; j++) {
                    standtard += (originData.get(j).Close - smaValue)
                            * (originData.get(j).Close - smaValue);
                }
                squarSum = Math.sqrt(standtard / T);
    
                zhongEntity = new Entry();
                zhongEntity.setX(i);
                zhongEntity.setY((float) smaValue);
                zhongEntity.setData(candle);
    
                shangEntity = new Entry();
                shangEntity.setX(i);
                shangEntity.setY((float) (smaValue + squarSum * K));
                shangEntity.setData(candle);
    
                xiaEntity = new Entry();
                xiaEntity.setX(i);
                xiaEntity.setY((float) (smaValue - squarSum * K));
                xiaEntity.setData(candle);
    
                zhongList.add(zhongEntity);
                xiaList.add(xiaEntity);
                shangList.add(shangEntity);
            }
    
            return new BollEntity(shangList, zhongList, xiaList);
    
        }
    
    
        /**
         * 抽取原始double 其他指數也需要用
         *
         * @param days 週期
         * @return 集合數據 
MA=N日內的收盤價之和÷N
         */
        public List<Double> countMA(int days) {
            if (days < 1) {
                return null;
            }
            if (originData == null || originData.size() == 0) {
                return null;
            }
            int cycle = days;
    
            if (cycle > originData.size()) {
                //設置的指標參數大於數據集合 不用計算
                return null;
            }
    
            double sum = 0;
    
            List<Double> ma5Values = new ArrayList();
    
            for (int i = cycle - 1; i < originData.size(); i++) {
                if (i == cycle - 1) {
                    for (int j = i - days + 1; j <= i; j++) {
                        sum += originData.get(j).Close;
                    }
                } else {
                    sum = sum + originData.get(i).Close - originData.get(i - days).Close;
                }
                ma5Values.add(sum / days);
            }
            return ma5Values;
        }
    
    
        /**
         * @param Tn default 6
         * @return
         */
        public List<Entry> getWR(int Tn, int index) {
            if (originData == null || originData.size() == 0) {
                return null;
            }
    
            List<Entry> wrList = new ArrayList<>();
    
            if (originData.size() > 0) {
                for (int j = index; j < originData.size(); j++) {
    
                    List<ICandle> iCandles = changeCandleToICandle(originData);
                    ICandle candle = iCandles.get(j);
                    WREntity.CandleParseWR(iCandles, j, Tn);
    
                    float wr = (candle.max6 - candle.Close) / (candle.max6 - candle.min6) * 100;
                    wrList.add(new Entry(j, wr, originData.get(j)));
    
                }
    
            }
    
    
            return wrList;
        }
    
        /**
         * @param p1 default 14
         * @param p2 default 6
         * @return 此處的DMIData 繼承了Candle
         * DMI存在4條線
         */
        public DMIEntity getDMI(int p1, int p2, int index) {
            if (originData == null || originData.size() == 0) {
                return null;
            }
            List<ICandle> dmiDatas = changeCandleToICandle(originData);
    
    
            if (index >= dmiDatas.size() - 1) {
                index = dmiDatas.size() - 1;
            }
            if (dmiDatas.size() >= 1) {
                for (int j = index; j < dmiDatas.size(); j++) {
                    DMIEntity.ParseByP1(dmiDatas, j, p1);
                    DMIEntity.ParseByP2(dmiDatas, j, p1, p2);
                }
            }
    
            //存儲dm_minus數據
            List<Entry> pdiList = new ArrayList<>();
            //dm_plus
            List<Entry> mdiList = new ArrayList<>();
            //adx
            List<Entry> adxList = new ArrayList<>();
            //adxr
            List<Entry> adxrList = new ArrayList<>();
            for (int i = 0; i < dmiDatas.size(); i++) {
                ICandle dmi = dmiDatas.get(i);
                pdiList.add(new Entry(i, dmi.di_plus14, dmi));
                mdiList.add(new Entry(i, dmi.di_minus14, dmi));
                adxList.add(new Entry(i, dmi.adx, dmi));
                adxrList.add(new Entry(i, dmi.adxr, dmi));
            }
    
            DMIEntity dmiData = new DMIEntity(pdiList, mdiList, adxList, adxrList);
            return dmiData;
        }
    
        public CCIEntity getCCI(int index, int Tn) {
    
            if (originData == null || originData.size() == 0) {
                return null;
            }
    
            List<ICandle> iCandles = changeCandleToICandle(originData);
    
            List<Entry> cci = new ArrayList<>();
            List<Entry> tp = new ArrayList<>();
            List<Entry> mtp = new ArrayList<>();
            List<Entry> md = new ArrayList<>();
    
            if (index >= iCandles.size() - 1) {
                index = iCandles.size() - 1;
            }
            if (iCandles.size() > 0) {
                for (int j = index; j < iCandles.size(); j++) {
                    CCIEntity.CandleParseCCI(iCandles, j, Tn);
                }
            }
    
            for (int i = 0; i < iCandles.size(); i++) {
                ICandle candle = iCandles.get(i);
                cci.add(new Entry(i, candle.cci, candle));
            }
            return new CCIEntity(cci, tp, mtp, md);
        }
    
        public OBVEntity getOBV(int index, int TnOBV) {
    
            if (originData == null || originData.size() == 0) {
                return null;
            }
    
            List<ICandle> iCandles = changeCandleToICandle(originData);
    
            List<Entry> obvList = new ArrayList<>();
            List<Entry> obv30List = new ArrayList<>();
    
            if (index >= iCandles.size() - 1) {
                index = iCandles.size() - 1;
            }
            if (iCandles.size() > 0) {
                for (int j = index; j < iCandles.size(); j++) {
                    OBVEntity.CandleParseObV(iCandles, j, TnOBV);
                }
            }
    
    //均線
            for (int i = 0; i < iCandles.size(); i++) {
                ICandle candle = iCandles.get(i);
                obvList.add(new Entry(i, candle.obv, candle));
                obv30List.add(new Entry(i, candle.obv30ma, candle));
            }
    
            OBVEntity obvData = new OBVEntity(obvList, obv30List);
            return obvData;
        }
    
        public EMAEntity getEMA(List<Integer> periods) {
    
            if (originData == null || originData.size() == 0) {
                return null;
            }
    
            //週期選擇
    
    
            List<EntryType> emaDataList = new ArrayList<>();
    
            for (int i = 0; i < periods.size(); i++) {
                List<ICandle> iCandles = changeCandleToICandle(originData);
                if (iCandles.size() > 0) {
                    int period = periods.get(i).intValue();
    
    //                if (period == Companion.getDefaultNullValue()) {
    //                    emaDataList.add(new EntryType(true));
    //                    continue;
    //                }
    
                    for (int j = 0; j < iCandles.size(); j++) {
                        EMAEntity.CandleParseToEMA(iCandles, j, period);
                    }
    
                    ArrayList emaList = new ArrayList();
                    for (int k = 0; k < iCandles.size(); k++) {
                        ICandle candle = iCandles.get(k);
                        emaList.add(new Entry(k, candle.common, candle));
                    }
    
                    emaDataList.add(new EntryType(emaList, period + ""));
    
                }
    
            }
    
    
            EMAEntity emaEntity = new EMAEntity(emaDataList);
            return emaEntity;
        }
    
    
        /**
         * 只允許一起拷貝 不可單獨拷貝
         *
         * @param originData
         * @return
         */
        private List<ICandle> changeCandleToICandle(List<Candle> originData) {
            List<ICandle> iCandles = new ArrayList<>();
            if (originData != null) {
                for (int i = 0; i < originData.size(); i++) {
                    ICandle iCandle = new ICandle(originData.get(i), true);
                    iCandles.add(iCandle);
                }
            }
            return iCandles;
        }
    
        public VolEntity getVol() {
            if (originData == null || originData.size() == 0) {
                return null;
            }
            VolEntity volEntity = new VolEntity();
            int flagPosition = 0;
    
            for (int i = 0; i < originData.size(); i++) {
                Candle candle = originData.get(i);
                BarEntry barEntry = new BarEntry((float) (i + flagPosition), candle.Volume, candle);
                volEntity.bars.add(barEntry);
            }
            return volEntity;
        }
    
        public MACDEntity getMACD(int quickLineIndex, int slowLineIndex, int moveLineIndex) {
            if (originData == null || originData.size() == 0) {
                return null;
            }
            int flagPosition = 0;
            MACDEntity macdEntity = new MACDEntity();
            macdEntity.clearValues();
    
            if (quickLineIndex <= 0) {
                quickLineIndex = 12;
            }
            if (slowLineIndex <= 0) {
                slowLineIndex = 26;
            }
    
            if (moveLineIndex <= 0) {
                moveLineIndex = 9;
            }
    
            //12 26 9
            float ema12 = 0f;
            float ema26 = 0f;
            float dif;
            float dea = 0f;
            float macd = 0f;
            Entry entry;
            BarEntry barEntry;
            for (int i = 0; i < originData.size(); i++) {
                Candle candle = originData.get(i);
                if (i == 0) {
                    ema12 = candle.Close;
                    ema26 = candle.Close;
                } else {
                    // EMA(12) = 前一日EMA(12) X 11/13 + 今日收盤價 X 2/13
                    ema12 = ema12 * (quickLineIndex - 1) / (quickLineIndex + 1) + candle.Close * 2f / (quickLineIndex + 1);
                    // EMA(26) = 前一日EMA(26) X 25/27 + 今日收盤價 X 2/27
                    ema26 = ema26 * (slowLineIndex - 1) / (slowLineIndex + 1) + candle.Close * 2f / (slowLineIndex + 1);
                }
                // DIF = EMA(12) - EMA(26) 。
                // 今日DEA = (前一日DEA X 8/10 + 今日DIF X 2/10)
                // 用(DIF-DEA)*2即爲MACD柱狀圖。
                dif = ema12 - ema26;
                dea = dea * (moveLineIndex - 1) / (moveLineIndex + 1) + dif * 2f / (moveLineIndex + 1);
                macd = (dif - dea) * 2f;
    
    
                entry = new Entry(i, dif, candle);
                macdEntity.diff.add(entry);
                entry = new Entry(i, dea, candle);
                macdEntity.dea.add(entry);
    
    
                barEntry = new BarEntry(i, macd, candle);
                macdEntity.bar.add(barEntry);
            }
    
            return macdEntity;
    
        }
    
    
        public KDJEntity getKDJ(List<Integer> ps) {
            if (originData == null || originData.size() == 0) {
                return null;
            }
            KDJEntity kdjEntity = new KDJEntity();
    
            if (ps == null || ps.size() == 0) {
                return null;
            }
            int Tn = ps.get(0);
            int index = 0;
    
    
            for (int i = index; i < originData.size(); i++) {
                Candle candle = originData.get(i);
                if (index == 0) {
                    candle.k = 50.0f;
                    candle.d = 50.0f;
    
                } else {
                    candle.rsv9 = p_rsv9WithEndIndex(index, Tn == 0 ? 9 : Tn);
                    p_K_D_WithIndex(index);
                }
                candle.j = (float) ((3.0 * candle.k) - (2.0 * candle.d));
    
            }
    
            for (int i = 0; i < originData.size(); i++) {
                Candle candle = originData.get(i);
    
                kdjEntity.k.add(new Entry(i, originData.get(i).k, candle));
                kdjEntity.d.add(new Entry(i, originData.get(i).d, candle));
                kdjEntity.j.add(new Entry(i, originData.get(i).j, candle));
            }
    
            kdjEntity.indexDes = "KDJ($Tn,3,3)";
            return kdjEntity;
        }
    
        /**
         * 計算RSV
         *
         * @param endindex 結束的下標
         * @return 計算後的RSV9
         */
        Float p_rsv9WithEndIndex(int endindex, int Tn)
    
        {
            float result = 0.0f;
            float low9 = Float.POSITIVE_INFINITY;
            float high9 = -Float.POSITIVE_INFINITY;
            float close = 0.0f;
            float startIndex = endindex - (Tn - 1);
            if (startIndex < 0) {
                startIndex = 0;
            }
            for (int i = 100; i > startIndex; i--) {
                Candle tempModel = originData.get(i);
    
                if (tempModel.Low < low9) {
                    low9 = tempModel.Low;
                }
    
                if (tempModel.High > high9) {
                    high9 = tempModel.High;
    
                }
    
                if (i == endindex) {
                    close = tempModel.Close;
                }
            }
            result = (float) ((close - low9) / (high9 - low9) * 100.0);
            if (java.lang.Float.isNaN(result)) {
                return 0.0f;
            } else {
                return result;
            }
    
        }
    
        /**
         * 計算K值和D值
         */
    
        void p_K_D_WithIndex(int a) {
            Candle tempModel = originData.get(a);
            Candle lastModel = originData.get(a - 1);
            tempModel.k = (float) (((2.0 * lastModel.k) + tempModel.rsv9) / 3.0);
            tempModel.d = (float) (((2.0 * lastModel.d) + tempModel.k) / 3.0);
        }
    
        public Object getRSI(List<Integer> ps) {
    
            if (originData == null || originData.size() == 0 || ps == null || ps.size() == 0) {
                return null;
            }
    
            RSIEntity rsiEntity = new RSIEntity();
    
    
            for (int index = 0; index < ps.size(); index++) {
                int rsiIndex = ps.get(index);
    
    //            if (rsiIndex == IndexSettingDetailActivity.defaultNullValue) {
    //                rsiEntity.rsiDataList.add(EntryType(true))
    //                continue
    //            }
    
                int flagPosition = 0;
                float lastSMAMax6 = 0f;
                float lastSMAAbs6 = 0f;
    
                float lastPrice = 0f;
                float rsi = 0f;
                Entry rsiEntry;
                boolean first = true;
    
                ArrayList<Entry> rsiList = new ArrayList();
    
                for (int i = 0; i < originData.size(); i++) {
                    Candle candle = originData.get(i);
                    if (!first) {
                        float priceDiffer = candle.Close - lastPrice;
                        if (priceDiffer < 0) {
                            lastSMAMax6 = (rsiIndex - 1) * lastSMAMax6 / rsiIndex;
                            lastSMAAbs6 = (Math.abs(priceDiffer) + (rsiIndex - 1) * lastSMAAbs6) / rsiIndex;
                        } else {
                            lastSMAMax6 = (priceDiffer + (rsiIndex - 1) * lastSMAMax6) / rsiIndex;
                            lastSMAAbs6 = (priceDiffer + (rsiIndex - 1) * lastSMAAbs6) / rsiIndex;
                        }
                    }
                    if (first || lastSMAAbs6 == 0f) {
                        rsiEntry = new Entry(i, 0f, candle);
                    } else {
                        rsi = lastSMAMax6 / lastSMAAbs6 * 100.0f;
                        rsiEntry = new Entry(i, rsi, candle);
                    }
    
                    rsiList.add(rsiEntry);
    
    
                    lastPrice = candle.Close;
                    first = false;
                }
                rsiEntity.rsiDataList.add(new EntryType(rsiList, String.valueOf(rsiIndex)));
            }
    
    
            return rsiEntity.rsiDataList;
        }
    }
    

     

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章