class Bar
{
public DateTime Time { get; set; }
public double Price { get; set; }
}
class Instrument
{
public List<Bar> Bars { get; set; }
public string Name { get; set; }
public Instrument(string name, string path) {
// set the Bars list here reading from files
}
}
以下是我的课程的两个简化版本。我正在为货币创建自定义回测平台。目前的问题是切断我不会在每台仪器上都有价格数据的条形码。
我从XML文件中读取价格。
var xlinqBarLists = xlinqInstruments.Select(i => i.Bars);
基本上是
List<List<Bar>> xlinqBarLists
我想要做的是遍历每个单独的列表,找到最新的开始日期和最早的结束日期,然后在该时间窗口之外删除所有栏。我的黑客密码是
var xlinqInstruments = root.Elements("instrument").Select( a =>
new Instrument( a.Element("name").Value, a.Element("path").Value ) );
var xlinqBarLists = xlinqInstruments.Select(i => i.Bars);
DateTime latestStartDate = DateTime.MinValue;
DateTime earliestEndDate = DateTime.MaxValue;
foreach (List<Bar> bars in xlinqBarLists)
{
if (bars.Min(b => b.Time) > latestStartDate)
latestStartDate = bars.Min(b => b.Time);
if (bars.Max(b => b.Time) < earliestEndDate)
earliestEndDate = bars.Max(b => b.Time);
}
foreach (List<Bar> barList in xlinqBarLists)
{
var timeWindowBars = from bar in barList
where bar.Time >= latestStartDate && bar.Time <= earliestEndDate
select bar;
// I need some way to overwrite the original Instrument.Bars property with timeWindowBars
// Suggestions?
}
我可以通过跳过foreach循环来更快更有效地完成这项工作吗?
答案 0 :(得分:0)
如果my comment above(我已在下面复制/粘贴)证明是这种情况,那么这是一个答案。
您是否要将每个乐器的Bars属性设置为a 列表仅包含最小值范围内的对象 所有Bar对象的结束日期和最长开始日期(包括 那些出现在其他仪器上的人?)
// Get the value of the earliest Bar.Time on each Instrument, and select the most recent of those.
DateTime latestStartDate = xlinqInstruments.Max(instrument => instrument.Bars.Min(bar => bar.Time));
// Get the value of the latest Bar.Time on each Instrument, and select the earliest of those.
DateTime earliestEndDate = xlinqInstruments.Min(instrument => instrument.Bars.Max(bar => bar.Time));
// Overwrite the Bars collection of each instrument with its contents truncated appropriately.
// I'd suggest doing this with a foreach loop as opposed to what I've provided below, but that's just me.
xlinqInstruments.ForEach(instrument =>
{
instrument.Bars = instrument.Bars.Where(obj => obj.Time >= latestStartDate && obj.Time <= earliestEndDate).ToList();
});
ForEach方法要求您先在.ToList()
集合上调用xlinqInstruments
,这可能毫无价值。在我的代码中,我假设该集合已经实现为List<Instrument>
您可能也对linq&#39; Enumerable.SelectMany
方法感兴趣。
Enumerable.SelectMany Method(IEnumerable,Func&gt;)
将序列的每个元素投影到IEnumerable,并将生成的序列展平为一个序列。
答案 1 :(得分:0)
有关最新的开始日期和最早的结束日期,您可以使用
DateTime latestStartDate = xlinqInstruments.Max(i => i.Bars.Min(bar => bar.Time));
DateTime earliestEndDate = xlinqInstruments.Min(i => i.Bars.Max(bar => bar.Time));
对于最后一部分,也许你想为'Instrument'添加一个无参数构造函数然后
var result = xlinqInstruments
.Select(i=>new Instrument()
{
Name = i.Name,
Bars = i.Bars.Where(bar => bar.Time >= latestStartDate
&& bar.Time <=earliestEndDate)
.ToList()
});
答案 2 :(得分:-1)
在分配到ToList
之前调用xlinqBarLists
:
var xlinqBarLists = xlinqInstruments.Select(i => i.Bars).ToList();
否则,您将一遍又一遍地解析相同的XML。
如果您希望稍后更新,请在创建ToList
时调用xlinqInstruments
。