代码之家  ›  专栏  ›  技术社区  ›  nop

无法将Frame<int,string>转换为List<OHLCV>,因此我可以计算指标并定位其结果

  •  1
  • nop  · 技术社区  · 4 年前

    我试图重新创建使用pandas的python代码( this one )用Deedle编写C#。基本上,我正在努力解决两件事。

    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, 0, 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(), 0, 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 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();
            }
        }
    }
    
    

    编辑

    我只回答了问题的第一部分( closes 列表<十进制> 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;
    }
    
    0 回复  |  直到 4 年前