我试图重新创建使用pandas的python代码(
this one
)用Deedle编写C#。基本上,我正在努力解决两件事。
-
我想用
Rsi(this IReadOnlyList<OHLCV> source...
在计算我的指标时超载。现在我正在使用
List<decimal>
.
-
我该如何转换它
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 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;
}