我有一个算法,它扫描从.csv文件中读取的数据(大约3700行),并通过在该年的每个星期日运行一个计数++并将计数值指定为每个条目,评估每个条目所在的交易周。交易周当日期在该周内。
它正在发挥作用,但性能却落后了。它是使用Task.Factory.StartNew运行的第三个函数(我也尝试过parallel.Invoke)。
时间测试的结果。
之前:00:00:05.58
之后:00:00:23.27
更新
设置每个交易周后添加休息时间。时间有所改善但仍然很慢。
新时间:00:00:15.74
对于我们的目的,一年中的第一周是第1周(不是0),并且定义为从一年的第一天到星期日。如果一年的第一天是星期日,则第1周的长度为1天。
private void SetDefiniteWeeks()
{
string FileLoc = FilePath + Market + ".csv";
string[] Data = File.ReadAllLines(FileLoc);
var FileData = from D in Data
let DataSplit = D.Split(',')
select new
{
Date = DateTime.Parse(DataSplit[0]),
ClosingPrice = double.Parse(DataSplit[4])
};
//assign each date to it's relevant week
TradingWeek TW;
List<TradingWeek> tradingWeek = new List<TradingWeek>();
foreach (var pe in FileData)
{
// DateTime dt = pe.Date;
int Year = pe.Date.Year;
string End_of_Week = "Sunday";
int WeekCount = 0;
DateTime LoopDate_Begin = new DateTime(Year,1,1);
DateTime LoopDate_End = new DateTime(Year,12,31);
do
{
if (LoopDate_Begin.DayOfWeek.ToString() == End_of_Week)
{
WeekCount++;
if (LoopDate_Begin.DayOfYear > pe.Date.DayOfYear && LoopDate_Begin.DayOfYear < (pe.Date.DayOfYear + 7))
{
TW = new TradingWeek { Week = WeekCount, Date = pe.Date };
tradingWeek.Add(TW);
break;
}
}
LoopDate_Begin = LoopDate_Begin.AddDays(1);
} while (LoopDate_Begin.Date.ToString() != LoopDate_End.Date.ToString());
}
}
请帮忙。
更新
新时间
00:00:06.686
一项巨大的改进。谢谢大家的帮助。
修订代码:
CalendarWeekRule cw = CalendarWeekRule.FirstDay;
var calendar = CultureInfo.CurrentCulture.Calendar;
var trad_Week = (from pe in FileData
select new TradingWeek
{
Date = pe.Date,
Week = (calendar.GetWeekOfYear(pe.Date, cw,DayOfWeek.Sunday))
}).ToList();
答案 0 :(得分:4)
三个快速的想法:
为什么你每次只增加一天并检查它是否是星期天。当你找到第一个星期天时,你可以增加七天来找到下一个星期日吗?
如果你在开始之前按照DateTime订购你的pes,那么你不需要在每年的年初重新开始,你可以从你离开的地方继续。
正如尼古拉斯所说,在加入交易周后突破。在你已经知道答案是什么之后,无需经历一年中的剩余时间。
我想你最终会得到这样的东西(可能或可能不会真正起作用,但应该足够接近)
TradingWeek TW;
List<TradingWeek> tradingWeek = new List<TradingWeek>();
string End_of_Week = "Sunday";
var orderedData = FileData.OrderBy(x => x.Date)
DateTime LoopDate_Begin = new DateTime(orderedData[0].Date.Year,1,1);
int WeekCount = 1;
while (LoopDate_Begin.DayOfWeek.ToString() != End_of_Week)
{
LoopDate_Begin = LoopDate_Begin.AddDays(1);
}
foreach (var pe in orderedData)
{
do
{
if (LoopDate_Begin.DayOfYear > pe.Date.DayOfYear && LoopDate_Begin.DayOfYear < (pe.Date.DayOfYear + 7))
{
TW = new TradingWeek { Week = WeekCount, Date = pe.Date };
tradingWeek.Add(TW);
break;
}
WeekCount++;
LoopDate_Begin = LoopDate_Begin.AddDays(7);
} while (true); //need to be careful here
}
答案 1 :(得分:4)
我不确定这是否是您想要的但是在阅读完评论后我觉得这可能有用(?)
var calendar = CultureInfo.CurrentCulture.Calendar;
var tradingWeek = (from pe in FileData
select new TradingWeek
{
Date = pe.Date,
Week = calendar.GetWeekOfYear(pe.Date, CalendarWeekRule.FirstDay, DayOfWeek.Sunday);
}).ToList();
编辑:改为CalendarWeekRule.FirstDay,因为它是(更多?)OP正在寻找的东西。
答案 2 :(得分:1)
如果我找到你,你不需要在添加TradingWeek后再查看
所以,你可以
break;
之后
tradingWeek.Add(TW);
然后你甚至可以省略
&& LoopDate_Begin.DayOfYear < (pe.Date.DayOfYear + 7)
条件,因为第一部分只会是真实的一次:为你想要的间隔。
答案 3 :(得分:1)
您甚至可以通过将自开始周以来的天数除以7来进行无环路方法 - 并进行一些清理工作;)
答案 4 :(得分:1)
你可以通过直接计算周数来完全摆脱do
循环吗?类似于接受的答案here。
答案 5 :(得分:1)
按照@ nicolas78的回复,这样的事情应该有效
int Year = pe.Date.Year;
DateTime Year_Begin = new DateTime(Year,1,1);
int Jan1DayOfWeek = Year_Begin.DayOfWeek;
foreach (var pe in FileData)
{
int WeekCount = (pe.Date.DayOfYear - Jan1DayOfWeek) % 7 + 1;
TradingWeek TW = new TradingWeek { Week = WeekCount, Date = pe.Date };
tradingWeek.Add(TW);
}
根据DayOfWeek和DayOfYear的计数方式,即0或1,以及mod操作的工作方式,您可能需要稍微调整WeekCount计算。
答案 6 :(得分:0)
您根本无需计算 - 只需快速计算即可。这假设一年开始的部分周是第1周,第2周从第一个星期一开始。
List<TradingWeek> tradingWeek = new List<TradingWeek>();
foreach (var pe in FileData)
{
var date = pe.Date;
while (date.DayOfWeek != DayOfWeek.Sunday)
date = date.AddDays(1);
var week = date.DayOfYear/7+1;
var TW = new TradingWeek {Week = week, Date = pe.Date};
tradingWeek.Add(TW);
}
答案 7 :(得分:0)
有一个内置功能可以根据.NET中的日期获取一年中的一周。下面显示了一个示例,但可能需要进行一些调整以适合您的业务场景:
System.Globalization.CultureInfo myCI = new System.Globalization.CultureInfo("en-US");
int week = myCI.Calendar.GetWeekOfYear(DateTime.Now.ToUniversalTime(), System.Globalization.CalendarWeekRule.FirstFourDayWeek, System.DayOfWeek.Sunday);