在平常的开发过程中,我们可能需要写一小段代码来分析某个数据,或者验证某个功能的实现是否正确,比如:

  • 对一段字符串进行解析,通常会使用IndexOf方法来查找想要字符串的起始位置,但这通常需要+1或-1来进行微调才能得到想要的结果,如何快速验证代码是否正确?
  • 使用正则表达式匹配时,如何验证结果是否正确等等?
  • .NET最大的工作线程数量和完成端口线程数量是多少?
  • .......

    要实现这些小功能,可以打开Visual Studio,然后创建项目,保存解决方案,添加类,然后才能开始写代码。从Visual Studio启动完成,到开始编写第一行代码,这通常需要很多时间(当然,随着Visual Studio版本的更新,以及计算机剩余可用内存量,打开可能需要更长的时间),显然效率十分低下。 我以前就是这样做的,非常的繁琐。

▲ 少不更事的我,用Visual Studio来做概念验证,新建了不少乱七八糟的测试项目

    如果有一款类似记事本这样的小工具,能秒开,然后不用繁琐的创建解决方案,添加工程文件,可以直接写代码并运行,并且能很方便的看到运行结果,就能极大的节省时间,这就工具就是LINQPad。

LINQPad介绍


    千万不要被这个名字所误导,误以为它只能进行LINQ相关的操作,我之前也是这么认为的,但当我试用后发现,这个工具简直就是一把瑞士军刀,能非常很方便的进行一些概念验证(POC—Proof of Concept)。

    打开LINQPad之后,在左下角有自带的一些教程,可以快速入门。具体的更多应用场景可以看LINQPad,我的C#/.NET学习诀窍这篇文章,说实话我也是从这篇文章开始注意LINQPad的。

一个例子


    比如我现在刚好有一个数据分析的例子,我们从行情供应商那里获取了某只股票的逐比成交落地数据"000629.tbt",在托管机器上也落地了同样这只股票的数据"20220726Real.txt",我需要分析:

  1. 行情供应商那边落地数据的本身延迟情况。
  2. 数据从行情供应商,通过API传输到托管机上的数据耗时。

     我这里演示如何通过LINQPad来实现这一简单的需求:

    "000629.tbt"的数据格式如下,第1列是本机时间记为O1,第2列数行情数据时间记为O2,第3列是类型记为O3,第5列是逐比成交序号记为O5:

20220726112648.767971  20220726112648760	2	2011	21305159	000629	0	20132735	0.000000	2700	4	20220726112648760

     通过第1列-第2列的时间,就能获取行情供应商本身落地数据时存在的延迟。

    "20220726Real.txt"的数据格式如下,中括号“[]”括起来的是托管机本机时间记为L1,"Time"后面是行情数据时间记为L2,“SN”是逐比成交序列号记为L5

[11:26:48.838]  {"Exchange":1,"Symbol":"000629","SN":21305159,"Time":"2022-07-26T11:26:48.76","Price":0.0,"Size":2700,"BSFlag":1,"TradeType":1,"AskOrder":20132735,"BidOrder":0,"QtyType":0,"qty":0.0,"Source":"","VolMultipiler":1}

    现在,解析出来数据之后,对于相同的逐比成交序列号O5==L5 就能计算出:

  1. 行情供应商落地数据本身延迟(可以认为是交易所发出数据延迟)=O1-O2
  2. 传输耗时,包括数据传输和处理=L1-O1

   下面来演示步骤:

Step1:单条数据的解析


    首先第一步,就是研究如何从上述两个文件中,解析出需要的数据,可以先从单行数据开始,打开LINQPad,将“Language”类型设置为“C# Program”,然后保存为"DiffAnalysis",然后就可以在Main函数内部写测试代码了,这部分的代码就是验证性质的,首先来解析托管机落地的数据"20220726Real.txt"中的某一行。

    解析的结果,可以使用.Dump方法直接输出,在图中,大量使用了Substring字符串截取,字符串的起始位置和长度,一开始可能不容易得到正确答案,需要不断的微调,这种修改、保存、运行过程非常容易,能很快调整得到正确的结果。

    然后解析行情供应商的数据文件"000629.tbt"中的某一行,也非常简单:

    这里需要注意,它是使用空格分隔的,有多少个空格不确定,所以这里不能直接使用Split方法,需要使用正则表达式。这里还可以设置断点,查看详细结果,如果要Dump日期里面的毫秒,需要去“Preferences-Result”里设置全局的格式

  设置好之后,再次运行Dump,就可以看到时间输出的毫秒了。

  在验证完两个数据文件的单条数据解析全部正确之后,就可以将这部分的解析逻辑移植到文件的解析里面了。

Step2:文件解析


   在解析文件之前,我们先在文件底部定义一个类,用来保存结果。这非常简单,直接在文件后面输入就可以了,当然,也可以单独放到另外的文件,然后使用"#load 文件名"的方式引入进来。

   然后,编写解析“20220726Real.txt"的整个逻辑,同样,直接添加一个方法“LoadLocalFile”,这里面的解析逻辑直接从Step1里面复制过来,微调即可:

   继续编写解析"000629.tbt"的方法,添加“LoadOrgFile”方法,

  最后,编写一个方法,调用这两个函数:

  分别解析出两个文件之后,使用Combine方法来计算两个差值,然后把结果更新到其中的一个Dictionary中。最后调用Util函数,将Dictionary的Values写入到CSV文件中。

Step3 结果分析


    使用Excel打开Step2步骤导出的结果.csv文件,然后直接作图,就能清晰直观的显示分析结果。

    从上图可以看到:

  1. 行情供应商那边自己落地的数据本身在早盘开盘阶段存在延迟,在大概开盘后10秒内最高延迟有5000毫秒,15秒后恢复正常。在下午开盘阶段也存在2000豪秒左右的延迟,这个问题是交易所发送数据时限流导致的,只有等交易所解决。
  2. 从行情供应商到我们本地托管机落地数据的延迟,在早盘阶段和下午开盘阶段也存在超过1000毫秒左右的延迟,且在全天各阶段都存在。
  3. 最终到达用户端的行情延迟等于上面两部分延迟的叠加,第一部分我们无法优化,需要优化的是第二部分的延迟。

     到此为止,我们从两份落地的行情数据文件中,得到了需要的信息和看到了存在的问题,下一步就是着手进行优化了。

其它场景


     上面只是我使用LINQPad来实现短平快功能的一个例子。在学习一些C#语言特性或其他类库的时候,使用LINQPad来编写也非常方便,省去了在一个解决方案下面添加过多项目文件的麻烦和性能消耗。比如我最近在看ReactiveExtension,跟着书本里的章节练习,可以将每一个章节作为一个LINQPad文件来直接编写,传统的方式需要在Visual Studio里面创建很多很多个项目文件。

    前几天在某乎上看到大神也在用这个工具,确实非常好用,值的推荐😂

    当然,LINQPad也不是没有缺点,比如在一些场景比如WindowsForm或WPF编程方面,可能使用Visual Studio还是更方便。

 

参考