需要支持和阻力算法或帮助找到包com.perseus.analysis

时间:2016-12-02 09:28:56

标签: java c# algorithm

在stackoverflow上找到了一个实现,但也不确定在哪里找到它使用的包'com.perseus.analysis.calculator.technical.trend',如果你知道一个好的算法请告诉我,最终喜欢转换,并在c#中实现这里代码并链接到我获取代码的位置。

link:the post

界面......

public interface ISupportResistanceCalculator {

/**
 * Identifies support / resistance levels.
 * 
 * @param timeseries
 *            timeseries
 * @param beginIndex
 *            starting point (inclusive)
 * @param endIndex
 *            ending point (exclusive)
 * @param segmentSize
 *            number of elements per internal segment
 * @param rangePct
 *            range % (Example: 1.5%)
 * @return A tuple with the list of support levels and a list of resistance
 *         levels
 */
Tuple<List<Level>, List<Level>> identify(List<Float> timeseries,
        int beginIndex, int endIndex, int segmentSize, float rangePct);
}

还有班级......

/**


* 
 */
package com.perseus.analysis.calculator.technical.trend;

import static com.perseus.analysis.constant.LevelType.RESISTANCE;
import static com.perseus.analysis.constant.LevelType.SUPPORT;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

import com.google.common.collect.Lists;
import com.perseus.analysis.calculator.mean.IMeanCalculator;
import com.perseus.analysis.calculator.timeseries.ITimeSeriesCalculator;
import com.perseus.analysis.constant.LevelType;
import com.perseus.analysis.model.Tuple;
import com.perseus.analysis.model.technical.Level;
import com.perseus.analysis.model.timeseries.ITimeseries;
import com.perseus.analysis.util.CollectionUtils;

/**
 * A support and resistance calculator.
 * 
 * @author PRITESH
 * 
 */
public class SupportResistanceCalculator implements
        ISupportResistanceCalculator {

    static interface LevelHelper {

        Float aggregate(List<Float> data);

        LevelType type(float level, float priceAsOfDate, final float rangePct);

        boolean withinRange(Float node, float rangePct, Float val);

    }

    static class Support implements LevelHelper {

        @Override
        public Float aggregate(final List<Float> data) {
            return Collections.min(data);
        }

        @Override
        public LevelType type(final float level, final float priceAsOfDate,
                final float rangePct) {
            final float threshold = level * (1 - (rangePct / 100));
            return (priceAsOfDate < threshold) ? RESISTANCE : SUPPORT;
        }

        @Override
        public boolean withinRange(final Float node, final float rangePct,
                final Float val) {
            final float threshold = node * (1 + (rangePct / 100f));
            if (val < threshold)
                return true;
            return false;
        }

    }

    static class Resistance implements LevelHelper {

        @Override
        public Float aggregate(final List<Float> data) {
            return Collections.max(data);
        }

        @Override
        public LevelType type(final float level, final float priceAsOfDate,
                final float rangePct) {
            final float threshold = level * (1 + (rangePct / 100));
            return (priceAsOfDate > threshold) ? SUPPORT : RESISTANCE;
        }

        @Override
        public boolean withinRange(final Float node, final float rangePct,
                final Float val) {
            final float threshold = node * (1 - (rangePct / 100f));
            if (val > threshold)
                return true;
            return false;
        }

    }

    private static final int SMOOTHEN_COUNT = 2;

    private static final LevelHelper SUPPORT_HELPER = new Support();

    private static final LevelHelper RESISTANCE_HELPER = new Resistance();

    private final ITimeSeriesCalculator tsCalc;

    private final IMeanCalculator meanCalc;

    public SupportResistanceCalculator(final ITimeSeriesCalculator tsCalc,
            final IMeanCalculator meanCalc) {
        super();
        this.tsCalc = tsCalc;
        this.meanCalc = meanCalc;
    }

    @Override
    public Tuple<List<Level>, List<Level>> identify(
            final List<Float> timeseries, final int beginIndex,
            final int endIndex, final int segmentSize, final float rangePct) {

        final List<Float> series = this.seriesToWorkWith(timeseries,
                beginIndex, endIndex);
        // Split the timeseries into chunks
        final List<List<Float>> segments = this.splitList(series, segmentSize);
        final Float priceAsOfDate = series.get(series.size() - 1);

        final List<Level> levels = Lists.newArrayList();
        this.identifyLevel(levels, segments, rangePct, priceAsOfDate,
                SUPPORT_HELPER);

        this.identifyLevel(levels, segments, rangePct, priceAsOfDate,
                RESISTANCE_HELPER);

        final List<Level> support = Lists.newArrayList();
        final List<Level> resistance = Lists.newArrayList();
        this.separateLevels(support, resistance, levels);

        // Smoothen the levels
        this.smoothen(support, resistance, rangePct);

        return new Tuple<>(support, resistance);
    }

    private void identifyLevel(final List<Level> levels,
            final List<List<Float>> segments, final float rangePct,
            final float priceAsOfDate, final LevelHelper helper) {

        final List<Float> aggregateVals = Lists.newArrayList();

        // Find min/max of each segment
        for (final List<Float> segment : segments) {
            aggregateVals.add(helper.aggregate(segment));
        }

        while (!aggregateVals.isEmpty()) {
            final List<Float> withinRange = new ArrayList<>();
            final Set<Integer> withinRangeIdx = new TreeSet<>();

            // Support/resistance level node
            final Float node = helper.aggregate(aggregateVals);

            // Find elements within range
            for (int i = 0; i < aggregateVals.size(); ++i) {
                final Float f = aggregateVals.get(i);
                if (helper.withinRange(node, rangePct, f)) {
                    withinRangeIdx.add(i);
                    withinRange.add(f);
                }
            }

            // Remove elements within range
            CollectionUtils.remove(aggregateVals, withinRangeIdx);

            // Take an average
            final float level = this.meanCalc.mean(
                    withinRange.toArray(new Float[] {}), 0, withinRange.size());
            final float strength = withinRange.size();

            levels.add(new Level(helper.type(level, priceAsOfDate, rangePct),
                    level, strength));

        }

    }

    private List<List<Float>> splitList(final List<Float> series,
            final int segmentSize) {
        final List<List<Float>> splitList = CollectionUtils
                .convertToNewLists(CollectionUtils.splitList(series,
                        segmentSize));

        if (splitList.size() > 1) {
            // If last segment it too small
            final int lastIdx = splitList.size() - 1;
            final List<Float> last = splitList.get(lastIdx);
            if (last.size() <= (segmentSize / 1.5f)) {
                // Remove last segment
                splitList.remove(lastIdx);
                // Move all elements from removed last segment to new last
                // segment
                splitList.get(lastIdx - 1).addAll(last);
            }
        }

        return splitList;
    }

    private void separateLevels(final List<Level> support,
            final List<Level> resistance, final List<Level> levels) {
        for (final Level level : levels) {
            if (level.getType() == SUPPORT) {
                support.add(level);
            } else {
                resistance.add(level);
            }
        }
    }

    private void smoothen(final List<Level> support,
            final List<Level> resistance, final float rangePct) {
        for (int i = 0; i < SMOOTHEN_COUNT; ++i) {
            this.smoothen(support, rangePct);
            this.smoothen(resistance, rangePct);
        }
    }

    /**
     * Removes one of the adjacent levels which are close to each other.
     */
    private void smoothen(final List<Level> levels, final float rangePct) {
        if (levels.size() < 2)
            return;

        final List<Integer> removeIdx = Lists.newArrayList();
        Collections.sort(levels);

        for (int i = 0; i < (levels.size() - 1); i++) {
            final Level currentLevel = levels.get(i);
            final Level nextLevel = levels.get(i + 1);
            final Float current = currentLevel.getLevel();
            final Float next = nextLevel.getLevel();
            final float difference = Math.abs(next - current);
            final float threshold = (current * rangePct) / 100;

            if (difference < threshold) {
                final int remove = currentLevel.getStrength() >= nextLevel
                        .getStrength() ? i : i + 1;
                removeIdx.add(remove);
                i++; // start with next pair
            }
        }

        CollectionUtils.remove(levels, removeIdx);
    }

    private List<Float> seriesToWorkWith(final List<Float> timeseries,
            final int beginIndex, final int endIndex) {

        if ((beginIndex == 0) && (endIndex == timeseries.size()))
            return timeseries;

        return timeseries.subList(beginIndex, endIndex);

    }

}

1 个答案:

答案 0 :(得分:0)

以上是上述代码的C#版本。我还没有测试过,但这几乎就是它。

public interface ISupportResistanceCalculator
{
    /// <summary>
    /// 
    /// </summary>
    /// <param name="timeseries">timeseries</param>
    /// <param name="beginIndex">starting point (inclusive)</param>
    /// <param name="endIndex">ending point (exclusive)</param>
    /// <param name="segmentSize">number of elements per internal segment</param>
    /// <param name="rangePct"> range % (Example: 1.5%)</param>
    /// <returns> A tuple with the list of support levels and a list of resistance levels</returns>
    Tuple<List<Level>, List<Level>> GetSupportResistance(List<float> timeseries,
        int beginIndex, int endIndex, int segmentSize, float rangePct);
}

public enum LevelType
{

    Support, Resistance

}

public class Tuple<TA, TB>
{

    private readonly TA a;

    private readonly TB b;

    public Tuple(TA a, TB b)
    {
        this.a = a;
        this.b = b;
    }

    public TA GetA()
    {
        return this.a;
    }

    public TB GetB()
    {
        return this.b;
    }

    public String ToString()
    {
        return "Tuple [a=" + this.a + ", b=" + this.b + "]";
    }

}

public abstract class CollectionUtils
{

    public static void Remove<T>(List<T> list,
        List<int> indexes)
    {
        int i = 0;
        for (int j = 0; j < indexes.Count; j++)
        {
            list.RemoveAt(j - i++);
        }
    }

    public static IEnumerable<List<T>> IntoBatches<T>(IEnumerable<T> list, int size)
    {
        if (size < 1)
            throw new ArgumentException();

        var rest = list;

        while (rest.Any())
        {
            yield return rest.Take(size).ToList();
            rest = rest.Skip(size);
        }
    }
}


public class Level
{

    private long serialVersionUID = -7561265699198045328L;

    private LevelType type;

    private readonly float level;
    private readonly float strength;


    public Level(LevelType type, float level, float strength)
    {
        this.type = type;
        this.level = level;
        this.strength = strength;
    }

    public new LevelType GetType()
    {
        return this.type;
    }

    public float GetLevel()
    {
        return this.level;
    }

    public float GetStrength()
    {
        return this.strength;
    }

    public String ToString()
    {
        return "Level [type=" + this.type + ", level=" + this.level
                + ", strength=" + this.strength + "]";
    }

}


public interface ILevelHelper
{

    float Aggregate(List<float> data);

    LevelType Type(float level, float priceAsOfDate, float rangePct);

    bool WithinRange(float node, float rangePct, float val);

}

public class Support : ILevelHelper
{
    public float Aggregate(List<float> data)
    {
        return data.Min();
    }

    public LevelType Type(float level, float priceAsOfDate,
        float rangePct)
    {
        float threshold = level * (1 - (rangePct / 100));
        return (priceAsOfDate < threshold) ? LevelType.Resistance : LevelType.Support;
    }

    public bool WithinRange(float node, float rangePct,
        float val)
    {
        float threshold = node * (1 + (rangePct / 100f));
        if (val < threshold)
            return true;
        return false;
    }

}

public class Resistance : ILevelHelper
{
    public float Aggregate(List<float> data)
    {
        return data.Max();
    }

    public LevelType Type(float level, float priceAsOfDate,
        float rangePct)
    {
        float threshold = level * (1 + (rangePct / 100));
        return (priceAsOfDate > threshold) ? LevelType.Resistance : LevelType.Support;
    }

    public bool WithinRange(float node, float rangePct,
        float val)
    {
        float threshold = node * (1 - (rangePct / 100f));
        if (val > threshold)
            return true;
        return false;
    }

}

public class SupportResistanceCalculator : ISupportResistanceCalculator
{

    private static readonly int SMOOTHEN_COUNT = 2;

    private static readonly ILevelHelper SupportHelper = new Support();

    private static readonly ILevelHelper ResistanceHelper = new Resistance();


    public Tuple<List<Level>, List<Level>> GetSupportResistance(
        List<float> timeseries, int beginIndex,
        int endIndex, int segmentSize, float rangePct)
    {

        List<float> series = this.SeriesToWorkWith(timeseries,
            beginIndex, endIndex);
        // Split the timeseries into chunks
        List<List<float>> segments = this.SplitList(series, segmentSize);
        float priceAsOfDate = series[series.Count - 1];

        List<Level> levels = new List<Level>();
        this.IdentifySRLevel(levels, segments, rangePct, priceAsOfDate,
            SupportHelper);

        this.IdentifySRLevel(levels, segments, rangePct, priceAsOfDate,
            ResistanceHelper);

        List<Level> support = new List<Level>();
        List<Level> resistance = new List<Level>();
        this.SeparateLevels(support, resistance, levels);

        // Smoothen the levels
        this.Smoothen(support, resistance, rangePct);

        return new BullsEyeStockEx.Controllers.Tuple<List<Level>, List<Level>>(support, resistance);
    }

    private void IdentifySRLevel(List<Level> levels,
        List<List<float>> segments, float rangePct,
        float priceAsOfDate, ILevelHelper helper)
    {

        List<float> aggregateVals = new List<float>();

        // Find min/max of each segment
        foreach (var segment in segments)
        {
            aggregateVals.Add(helper.Aggregate(segment));
        }

        while (aggregateVals.Any())
        {
            List<float> withinRange = new List<float>();
            HashSet<int> withinRangeIdx = new HashSet<int>();

            // Support/resistance level node
            float node = helper.Aggregate(aggregateVals);

            // Find elements within range
            for (int i = 0; i < aggregateVals.Count; ++i)
            {
                float f = aggregateVals[i];
                if (helper.WithinRange(node, rangePct, f))
                {
                    withinRangeIdx.Add(i);
                    withinRange.Add(f);
                }
            }

            // Remove elements within range
            CollectionUtils.Remove(aggregateVals, withinRangeIdx.ToList());

            // Take an average
            float level = withinRange.Average();
            float strength = withinRange.Count;

            levels.Add(new Level(helper.Type(level, priceAsOfDate, rangePct),
                level, strength));

        }

    }

    private List<List<float>> SplitList(List<float> series,
        int segmentSize)
    {
        List<List<float>> splitList = CollectionUtils.IntoBatches(series, segmentSize).ToList();

        if (splitList.Count > 1)
        {
            // If last segment it too small
            int lastIdx = splitList.Count - 1;
            List<float> last = splitList[lastIdx].ToList();
            if (last.Count <= (segmentSize / 1.5f))
            {
                // Remove last segment
                splitList.Remove(last);
                // Move all elements from removed last segment to new last
                // segment
                foreach (var l in last)
                {
                    splitList[lastIdx - 1].Add(l);
                }
            }
        }

        return splitList.ToList();
    }

    private void SeparateLevels(List<Level> support,
        List<Level> resistance, List<Level> levels)
    {
        foreach (var level in levels)
        {
            if (level.GetType() == LevelType.Support)
            {
                support.Add(level);
            }
            else
            {
                resistance.Add(level);
            }
        }
    }

    private void Smoothen(List<Level> support,
        List<Level> resistance, float rangePct)
    {
        for (int i = 0; i < SMOOTHEN_COUNT; ++i)
        {
            this.Smoothen(support, rangePct);
            this.Smoothen(resistance, rangePct);
        }
    }

    /**
     * Removes one of the adjacent levels which are close to each other.
     */
    private void Smoothen(List<Level> levels, float rangePct)
    {
        if (levels.Count < 2)
            return;

        List<int> removeIdx = new List<int>();
        levels.Sort();

        for (int i = 0; i < (levels.Count - 1); i++)
        {
            Level currentLevel = levels[i];
            Level nextLevel = levels[i + 1];
            float current = currentLevel.GetLevel();
            float next = nextLevel.GetLevel();
            float difference = Math.Abs(next - current);
            float threshold = (current * rangePct) / 100;

            if (difference < threshold)
            {
                int remove = currentLevel.GetStrength() >= nextLevel
                                 .GetStrength()
                    ? i
                    : i + 1;
                removeIdx.Add(remove);
                i++; // start with next pair
            }
        }

        CollectionUtils.Remove(levels, removeIdx);
    }

    private List<float> SeriesToWorkWith(List<float> timeseries,
        int beginIndex, int endIndex)
    {

        if ((beginIndex == 0) && (endIndex == timeseries.Count))
            return timeseries;
        return timeseries.GetRange(beginIndex, endIndex);

    }
}