微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

无法将 Frame<int, string> 转换为 List<OHLCV>,因此我可以计算指标并定位其结果 完全可测试的代码编辑

如何解决无法将 Frame<int, string> 转换为 List<OHLCV>,因此我可以计算指标并定位其结果 完全可测试的代码编辑

我正在尝试使用 deedle 在 C# 中重新创建使用 Pandas (this one) 的 Python 代码。基本上,我正在为两件事而苦苦挣扎。

  1. 我想在计算指标时使用 Rsi(this IReadOnlyList<OHLCV> source... 重载。现在我正在使用 List<decimal>
  2. 如何将 loc 转换为 C#?
dataframe.loc[
(
    qtpylib.crossed_above(dataframe['ema20'],dataframe['ema50']) &
    (dataframe['ha_close'] > dataframe['ema20']) &
    (dataframe['ha_open'] < dataframe['ha_close'])  # green bar
),'buy'] = 1

在我下面的示例中,被质疑的方法称为 PopulateIndicators。我想用上面提到的 foreach 之类的东西替换 loc 循环,并使代码看起来更像 python 代码(例如,将其拆分为三个方法等)。

完全可测试的代码

using Binance.Net;
using Binance.Net.Enums;
using deedle;
using System;
using System.Collections.Generic;
using System.Linq;

namespace deedleFrameTests
{
    public class OHLCV
    {
        public DateTime Timestamp { get; set; }
        public decimal Open { get; set; }
        public decimal High { get; set; }
        public decimal Low { get; set; }
        public decimal Close { get; set; }
        public decimal Volume { get; set; }
    }

    public static partial class IndicatorExtensions
    {
        private static IReadOnlyList<decimal?> FixIndicatorOrdering(IReadOnlyList<decimal> source,int outBegIdx,int outNbElement)
        {
            var outValues = new List<decimal?>();
            var validItems = source.Take(outNbElement);

            for (int i = 0; i < outBegIdx; i++)
                outValues.Add(null);

            foreach (var value in validItems)
                outValues.Add(value);

            return outValues;
        }

        public static IReadOnlyList<decimal?> Rsi(this IReadOnlyList<OHLCV> source,int period = 14)
        {
            var rsiValues = new decimal[source.Count];

            var closes = source.Select(e => e.Close).ToArray();

            var result = TALib.Core.Rsi(closes,source.Count - 1,rsiValues,out int outBegIdx,out int outNbElement,period);

            if (result == TALib.Core.RetCode.Success)
            {
                return FixIndicatorOrdering(rsiValues.ToList(),outBegIdx,outNbElement);
            }

            throw new Exception("Could not calculate RSI.");
        }

        public static IReadOnlyList<decimal?> Rsi(this List<decimal> source,int period = 14)
        {
            var rsiValues = new decimal[source.Count];

            var result = TALib.Core.Rsi(source.ToArray(),outNbElement);
            }

            throw new Exception("Could not calculate RSI.");
        }
    }

    public class TestStrategy
    {
        public enum TradeAdvice
        {
            Buy,Sell,Hold
        }

        public List<TradeAdvice> PopulateIndicatorsNodeedle(List<OHLCV> candles)
        {
            var result = new List<TradeAdvice>();

            var rsiPeriod = 2;
            var rsi = candles.Rsi(rsiPeriod);

            for (int i = 0; i < candles.Count; i++)
            {
                if (rsi[i] < 45 && rsi[i] > rsi[i - 1])
                    result.Add(TradeAdvice.Buy);
                else if (rsi[i] > 70)
                    result.Add(TradeAdvice.Sell);
                else
                    result.Add(TradeAdvice.Hold);
            }

            return result;
        }

        public List<TradeAdvice> PopulateIndicators(Frame<int,string> frame)
        {
            var closes = frame.GetColumn<decimal>("Close").Values.ToList();
            var indicator = closes.Rsi(2);

            frame.AddColumn("rsi",indicator);

            var rsi = frame.GetColumn<decimal>("rsi").Realign(Enumerable.Range(0,closes.Count)).FillMissing(0m);
            var rsiShifted = frame.GetColumn<decimal>("rsi").Shift(1).Realign(Enumerable.Range(0,closes.Count)).FillMissing(0m);

            var result = new List<TradeAdvice>();

            for (int i = 0; i < closes.Count; i++)
            {
                if (rsi[i] < 45 && rsi[i] > rsiShifted[i])
                    result.Add(TradeAdvice.Buy);
                else if (rsi[i] > 70)
                    result.Add(TradeAdvice.Sell);
                else
                    result.Add(TradeAdvice.Hold);
            }

            return result;
        }
    }

    public class Program
    {
        public static void Main(string[] args)
        {
            var candles = new BinanceClient().Spot.Market.GetKlines("TRXUSDT",KlineInterval.OneMinute).Data?
                .Select(x => new OHLCV
                {
                    Timestamp = x.OpenTime,Open = x.Open,High = x.High,Close = x.Close,Low = x.Low,Volume = x.BaseVolume
                }).ToList();

            var frame = Frame.Fromrecords(candles);

            var strategy = new TestStrategy();
            var advices = strategy.PopulateIndicatorsNodeedle(candles);
            var advices2 = strategy.PopulateIndicators(frame);

            var areEqual = Enumerable.SequenceEqual(advices,advices2);

            Console.ReadLine();
        }
    }
}

编辑

我只解决了问题的第一部分(closesList<decimal>List<OHLCV>)。这个问题帮助了我Convert a Deedle Dataframe into a C# List of Custom Class

剩下的问题仍未解决

public List<TradeAdvice> PopulateIndicators(Frame<int,string> df)
{   
    var closes = df.Rows.Select(row =>
        new OHLCV
        {
            Timestamp = row.Value.GetAs<DateTime>("Timestamp"),Open = row.Value.GetAs<decimal>("Open"),High = row.Value.GetAs<decimal>("High"),Low = row.Value.GetAs<decimal>("Low"),Close = row.Value.GetAs<decimal>("Close"),Volume = row.Value.GetAs<decimal>("Volume")
        }).Observations.Select(e => e.Value).ToList();

    //var closes = df.GetColumn<decimal>("Close").Values.ToList();
    var indicator = closes.Rsi(2);

    df.AddColumn("rsi",indicator);

    var rsi = df.GetColumn<decimal>("rsi").Realign(Enumerable.Range(0,closes.Count)).FillMissing(0m);
    var rsiShifted = df.GetColumn<decimal>("rsi").Shift(1).Realign(Enumerable.Range(0,closes.Count)).FillMissing(0m);

    var result = new List<TradeAdvice>();

    for (int i = 0; i < closes.Count; i++)
    {
        if (rsi[i] < 45 && rsi[i] > rsiShifted[i])
            result.Add(TradeAdvice.Buy);
        else if (rsi[i] > 70)
            result.Add(TradeAdvice.Sell);
        else
            result.Add(TradeAdvice.Hold);
    }

    return result;
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。