All Downloads are FREE. Search and download functionalities are using the official Maven repository.

quant.fans.strategy.StrategyUtils Maven / Gradle / Ivy

The newest version!
package quant.fans.strategy;

import com.google.common.collect.Lists;
import quant.fans.Indicators;
import quant.fans.tools.Conditions;
import quant.fans.common.StockConstants;
import quant.fans.common.Utils;
import quant.fans.model.StockData;

import java.util.List;

import static quant.fans.common.StockConstants.*;

/**
 * 策略公共方法
 */
public class StrategyUtils {

    private static TDXFunction function = new TDXFunction();

    /**
     * 计算macd指标金叉和死叉
     *      指标名称:macd_cross
     *      状态:
     *          1:金叉
     *          0:相交
     *          -1:死叉
     * @param stockDatas stock data list
     * @return stock data list
     */
    public static List macdCross(List stockDatas){
        if(stockDatas == null || stockDatas.size() == 0){
            return stockDatas;
        }
        if(stockDatas.size() > 0){
            if(stockDatas.get(0).get("dif") == null || stockDatas.get(0).get("dea") == null){
                return stockDatas;
            }
        }

        for(int i =0;i< stockDatas.size();i++){
            if(stockDatas.get(i).get("dif") > stockDatas.get(i).get("dea")){
                stockDatas.get(i).put("macd_cross",1d);
            }else if(stockDatas.get(i).get("dif") < stockDatas.get(i).get("dea")) {
                stockDatas.get(i).put("macd_cross", -1d);
            }else{
                stockDatas.get(i).put("macd_cross", 0d);
            }
        }
        return stockDatas;
    }

    /**
     * 判断最近n个时间周期内是否出现金叉,或者是当前的MACD值在(-0.1,0.1)之间并且dif,dea持续缩短
     *
     * @param stockDataList stock data list
     * @param period period
     * @return 如果是返回true
     */
    public static boolean isMACDGoldenCrossIn(List stockDataList, int period) {
        int count = stockDataList.size();
        for (int i = count - 1; i > 0; i--) {
            StockData stockData = stockDataList.get(i);
            Double cross = stockData.get(MACD_CROSS);
            if (cross != null && count - i <= period && cross == 1  && stockDataList.get(i).get(DIF) < 0.1){
                return true;
            }
        }
        return false;
    }

    public static List kdjCross(List stockDatas){
        if(stockDatas == null || stockDatas.size() == 0){
            return stockDatas;
        }
        if(stockDatas.size() > 0){
            if(stockDatas.get(0).get("kdj_d") == null || stockDatas.get(0).get("kdj_d") == null){
                return stockDatas;
            }
        }

        for(int i =0;i< stockDatas.size();i++){
            if(stockDatas.get(i).get("kdj_j") > stockDatas.get(i).get("kdj_d")){
                stockDatas.get(i).put("kdj_cross",1d);
            }else if(stockDatas.get(i).get("kdj_j") < stockDatas.get(i).get("kdj_d")) {
                stockDatas.get(i).put("kdj_cross", -1d);
            }else{
                stockDatas.get(i).put("kdj_cross", 0d);
            }
        }
        return stockDatas;
    }

    /**
     * 布林线上下轨之差小于中轨的10%,标记为1
     * @param stockDatas stock data list
     * @return stock data list
     */
    public static List bollThroat(List stockDatas){
        if(stockDatas == null || stockDatas.size() == 0){
            return stockDatas;
        }
        if(stockDatas.size() > 0){
            if(stockDatas.get(0).get("boll_upper") == null || stockDatas.get(0).get("boll_lower") == null){
                return stockDatas;
            }
        }

        for(int i =0;i< stockDatas.size();i++){
            if((stockDatas.get(i).get("boll_upper") - stockDatas.get(i).get("boll_lower")) < (stockDatas.get(i).get("boll_lower") * 0.1)){
                stockDatas.get(i).put("boll_throat",1d);
            }else{
                stockDatas.get(i).put("boll_throat",0d);
            }
        }
        return stockDatas;
    }

    /**
     * 判断收盘价两条线是否相交,快线从下上传慢线叫金叉,快慢线名称请参考StockConstants类
     *
     * @param stockDataList stock data list
     * @param maFast        例如:close_ma5
     * @param maSlow        例如:close_ma10
     * @param period period
     * @return stock data list
     */
    public static boolean isGoldenCrossIn(List stockDataList, String maFast, String maSlow, int period) {
        int size = stockDataList.size() - 1;
        double[] maFastArr = Utils.getArrayFrom(stockDataList, maFast);
        double[] maSlowArr = Utils.getArrayFrom(stockDataList, maSlow);
        for (int i = size; i > 0; i--) {
            if (size - i > period) {
                break;
            }
            if (maFastArr[i] > maSlowArr[i] && maFastArr[i-1] < maSlowArr[i-1]) {
                return true;
            }
        }
        return false;
    }

    public static double goldenCrossPrice(List stockDataList, String maFast, String maSlow, int period){
        int size = stockDataList.size() - 1;
        double[] maFastArr = Utils.getArrayFrom(stockDataList, maFast);
        double[] maSlowArr = Utils.getArrayFrom(stockDataList, maSlow);
        for (int i = size; i > 0; i--) {
            if (size - i < period) {
                break;
            }
            if (maFastArr[i] > maSlowArr[i] && maFastArr[i-1] < maSlowArr[i-1]) {
                return stockDataList.get(i).get(StockConstants.CLOSE);
            }
        }
        return -1;
    }

    /**
     * 判断最近n个时间周期内是否出现死叉
     *
     * @param stockDataList stock data list
     * @param period period
     * @return 如果是返回true
     */
    public static boolean isMACDDiedCrossIn(List stockDataList, int period) {
        int count = stockDataList.size();
        for (int i = count - 1; i > 0; i--) {
            StockData stockData = stockDataList.get(i);
            Double cross = stockData.get(MACD_CROSS);
            if (cross != null && count - i <= period && cross == 0)
                return true;
        }
        return false;
    }

    /**
     * 计算有几条均线粘合,粘合数加入到AVERAGE_BOND参数中
     * @param stockDataList stock data list
     * @param threshold threshold
     * @return stock data list
     */
    public static List averageBond(List stockDataList, double threshold) {
        List result = Lists.newLinkedList();
        for (int i = 0; i < stockDataList.size(); i++) {
            StockData stockData = stockDataList.get(i);
            double ma5 = stockData.get(CLOSE_MA5);
            double ma10 = stockData.get(CLOSE_MA10);
            double ma20 = stockData.get(CLOSE_MA20);
            double ma30 = stockData.get(CLOSE_MA30);
            double ma40 = stockData.get(CLOSE_MA40);
            double ma60 = stockData.get(CLOSE_MA60);
            if (ma5 == 0 || ma10 == 0 || ma20 == 0 || ma30 == 0 || ma40 == 0 || ma60 == 0) {
                continue;
            }
            double maCount = 0;
            double[] maArr = {ma5, ma10, ma20, ma30, ma40, ma60};
            for (int j = 0; j < 5; j++) {
                for (int k = j + 1; k < 6; k++) {
                    if (Math.abs(maArr[j] / maArr[k] - 1) < threshold) {
                        maCount++;
                    }
                }
            }
            stockData.put(AVERAGE_BOND, maCount);
            result.add(stockData);
        }
        return result;
    }

    /**
     * 金蜘蛛策略
     * @param stockDataList stock data list
     * @return stock data list
     */
    public static List goldenSpider(List stockDataList) {
        Indicators indicators = new Indicators();
        List result = Lists.newLinkedList();
        double[] closes = Utils.getArrayFrom(stockDataList, CLOSE);
        double[] volume = Utils.getArrayFrom(stockDataList,VOLUME);
        double[] ma2 = indicators.ema(closes, 2);
        double[] ma5 = indicators.ema(closes, 5);
        double[] ma13 = indicators.ema(closes, 13);
        double[] ma34 = indicators.ema(closes, 34);
        double[] ma55 = indicators.ema(closes, 55);
        double[][] macd = indicators.macd(closes);
        double[] volume5 = indicators.ema(volume,5);

        for (int i = 0; i < stockDataList.size(); i++) {
            StockData stockData = stockDataList.get(i);
            stockData.put(GOLDEN_SPIDER, 0d);
            stockData.put(GOLDEN_SPIDER_RANGE,0d);
            if (i > 0 && ma5[i] > ma5[i - 1]) {
                double close = stockData.get(CLOSE);
                double open = stockData.get(OPEN);
                double max1 = function.max(ma5[i], ma13[i], ma34[i]);
                double min1 = function.min(ma5[i], ma13[i], ma34[i]);
                double max2 = function.max(ma5[i], ma13[i], ma34[i], ma55[i]);
                double min2 = function.min(ma5[i], ma13[i], ma34[i], ma55[i]);
                if (max1 < close && open < min1 && ma2[i] > ma2[i - 1]) {
                    if(!Utils.isNearTradingTime()){//如果是盘后,则计算成交量是否大于前一天成交量,并且今天成交量大于当天volume5
                        if(stockData.get(VOLUME) > stockDataList.get(i-1).get(VOLUME)*1.2 && stockData.get(VOLUME) > volume5[i]){
                            stockData.put(GOLDEN_SPIDER, 3d);
                        }
                    }else{
                        stockData.put(GOLDEN_SPIDER, 3d);
                    }
                } else if (max2 < close && open < min2 && ma2[i] > ma2[i - 1]) {
                    if(!Utils.isNearTradingTime()){//如果是盘后,则计算成交量是否大于前一天成交量,并且今天成交量大于当天volume5
                        if(stockData.get(VOLUME) > stockDataList.get(i-1).get(VOLUME)*1.2 && stockData.get(VOLUME) > volume5[i]){
                            stockData.put(GOLDEN_SPIDER, 4d);
                        }else{
                            stockData.put(GOLDEN_SPIDER, 0d);
                        }
                    }else{
                        stockData.put(GOLDEN_SPIDER, 4d);
                    }
                } else if(macd[2][i]>0 && macd[2][i] < 1){    //macd金叉,并且三天内出现金蜘蛛
                    double lastClose = stockData.get(CLOSE);
                    for(int j=i-1;j >= 0 && j >i-3;j--){
                        Double spider = result.get(j).get(GOLDEN_SPIDER);
                        if(spider!=null){
                            if(lastClose > result.get(j).get(CLOSE) && lastClose < result.get(j).get(CLOSE) * 1.1 && spider>0){
                                stockData.put(GOLDEN_SPIDER_RANGE,1d);
                            }
                        }
                    }
                }
            }
            result.add(stockData);
        }
        return result;
    }

    /**
     * 计算最近count天内每天涨跌幅是否出现过conditions
     * @param stockDataList stock data list
     * @param count n day
     * @param conditions conditions
     * @return true if conditions is true
     */
    public static boolean change(List stockDataList,int count,Conditions conditions){
        int size = stockDataList.size();
        for(int i=size-1;i>=size-count;i--){
            StockData stockData = stockDataList.get(i);
            if(conditions.check(stockData)){
                return true;
            }
        }
        return false;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy