移动和滚动后填充第一个缺失的空元素 window
Fill the first missing null elements after shifting and rolling window
我正在用 pandas 重新创建在 python 中制定的策略。我认为我的代码有效,即使我还没有比较这些值,因为我遇到了异常。基本上,问题是 .Shift(20)
删除了前 20 个元素,而 .Window(12 * 60 / 15)
删除了 47 个元素。默认情况下,典型价格为 10180。移位滚动后变成10113window。我尝试使用 .FillMissing()
,但它似乎没有将第一个空值附加到系列。
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
if not {'buy', 'sell'}.issubset(dataframe.columns):
dataframe.loc[:, 'buy'] = 0
dataframe.loc[:, 'sell'] = 0
dataframe['typical'] = qtpylib.typical_price(dataframe)
dataframe['typical_sma'] = qtpylib.sma(dataframe['typical'], window=10)
min = dataframe['typical'].shift(20).rolling(int(12 * 60 / 15)).min()
max = dataframe['typical'].shift(20).rolling(int(12 * 60 / 15)).max()
dataframe['daily_mean'] = (max+min)/2
return dataframe
我的代码 (C#)
public override List<TradeAdvice> Prepare(List<OHLCV> candles)
{
var result = new List<TradeAdvice>();
var typicalPrice = candles.TypPrice().Select(e => e ?? 0).ToList();
var typicalSma = typicalPrice.Sma(10);
var series = typicalPrice.ToOrdinalSeries();
var min = series.Shift(20).Window(12 * 60 / 15).Select(kvp => kvp.Value.Min()).FillMissing(); // 10113 elements / 10180 expected
var max = series.Shift(20).Window(12 * 60 / 15).Select(kvp => kvp.Value.Max()).FillMissing(); // 10113 elements / 10180 expected
var dailyMean = (max + min) / 2;
var asd = dailyMean.SelectValues(e => Convert.ToDecimal(e)).Values.ToList();
var crossedBelow = asd.CrossedBelow(typicalPrice);
var crossedAbove = asd.CrossedAbove(typicalPrice);
for (int i = 0; i < candles.Count; i++)
{
if (i < StartupCandleCount - 1)
result.Add(TradeAdvice.WarmupData);
else if (crossedBelow[i]) // crossBelow is 10113 elements instead of 10180...
result.Add(TradeAdvice.Buy);
else if (crossedAbove[i]) // crossBelow is 10113 elements instead of 10180...
result.Add(TradeAdvice.Sell);
else
result.Add(TradeAdvice.NoAction);
}
return result;
}
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; }
}
如果你有一个用ToOrdinalSeries
创建的序数系列,这意味着系列的索引将自动生成从0到系列长度-1的数值。但是,这仍然是当你使用像 Shift
.
这样的操作时,一个真实的索引和 Deedle 会保留映射
如果你的索引是一个日期,比如 01/01 => a, 02/01 => b, 03/01 => c
,那么 Shift
会移动值并删除不再需要的键,即你可能会得到 02/01 => a, 03/01 => b
。
它与序数索引的工作原理相同,因此如果您有 0 => a, 1 => b, 2 => c
并移动数据,您将得到类似 1 => a, 2 => b
.
的结果
如果您随后想要获得 0 => <default>, 1 => a, 2 => b
,那么您可以使用 Realign
来执行此操作,它采用您想要的新键列表,后跟 FillMissing
。例如:
var ts = new[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }.ToOrdinalSeries();
var mins = ts.Shift(2).Window(2).Select(kvp => kvp.Value.Min());
var realigned = mins.Realign(Enumerable.Range(0, 10)).FillMissing(-1);
ts.Print(); // Starts from key '0'
mins.Print(); // Starts from key '3' because of Shift & Window
realigned.Print(); // Starts from key '0' with three -1 values at the start
我正在用 pandas 重新创建在 python 中制定的策略。我认为我的代码有效,即使我还没有比较这些值,因为我遇到了异常。基本上,问题是 .Shift(20)
删除了前 20 个元素,而 .Window(12 * 60 / 15)
删除了 47 个元素。默认情况下,典型价格为 10180。移位滚动后变成10113window。我尝试使用 .FillMissing()
,但它似乎没有将第一个空值附加到系列。
def populate_indicators(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
if not {'buy', 'sell'}.issubset(dataframe.columns):
dataframe.loc[:, 'buy'] = 0
dataframe.loc[:, 'sell'] = 0
dataframe['typical'] = qtpylib.typical_price(dataframe)
dataframe['typical_sma'] = qtpylib.sma(dataframe['typical'], window=10)
min = dataframe['typical'].shift(20).rolling(int(12 * 60 / 15)).min()
max = dataframe['typical'].shift(20).rolling(int(12 * 60 / 15)).max()
dataframe['daily_mean'] = (max+min)/2
return dataframe
我的代码 (C#)
public override List<TradeAdvice> Prepare(List<OHLCV> candles)
{
var result = new List<TradeAdvice>();
var typicalPrice = candles.TypPrice().Select(e => e ?? 0).ToList();
var typicalSma = typicalPrice.Sma(10);
var series = typicalPrice.ToOrdinalSeries();
var min = series.Shift(20).Window(12 * 60 / 15).Select(kvp => kvp.Value.Min()).FillMissing(); // 10113 elements / 10180 expected
var max = series.Shift(20).Window(12 * 60 / 15).Select(kvp => kvp.Value.Max()).FillMissing(); // 10113 elements / 10180 expected
var dailyMean = (max + min) / 2;
var asd = dailyMean.SelectValues(e => Convert.ToDecimal(e)).Values.ToList();
var crossedBelow = asd.CrossedBelow(typicalPrice);
var crossedAbove = asd.CrossedAbove(typicalPrice);
for (int i = 0; i < candles.Count; i++)
{
if (i < StartupCandleCount - 1)
result.Add(TradeAdvice.WarmupData);
else if (crossedBelow[i]) // crossBelow is 10113 elements instead of 10180...
result.Add(TradeAdvice.Buy);
else if (crossedAbove[i]) // crossBelow is 10113 elements instead of 10180...
result.Add(TradeAdvice.Sell);
else
result.Add(TradeAdvice.NoAction);
}
return result;
}
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; }
}
如果你有一个用ToOrdinalSeries
创建的序数系列,这意味着系列的索引将自动生成从0到系列长度-1的数值。但是,这仍然是当你使用像 Shift
.
如果你的索引是一个日期,比如 01/01 => a, 02/01 => b, 03/01 => c
,那么 Shift
会移动值并删除不再需要的键,即你可能会得到 02/01 => a, 03/01 => b
。
它与序数索引的工作原理相同,因此如果您有 0 => a, 1 => b, 2 => c
并移动数据,您将得到类似 1 => a, 2 => b
.
如果您随后想要获得 0 => <default>, 1 => a, 2 => b
,那么您可以使用 Realign
来执行此操作,它采用您想要的新键列表,后跟 FillMissing
。例如:
var ts = new[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }.ToOrdinalSeries();
var mins = ts.Shift(2).Window(2).Select(kvp => kvp.Value.Min());
var realigned = mins.Realign(Enumerable.Range(0, 10)).FillMissing(-1);
ts.Print(); // Starts from key '0'
mins.Print(); // Starts from key '3' because of Shift & Window
realigned.Print(); // Starts from key '0' with three -1 values at the start