65.9K
CodeProject 正在变化。 阅读更多。
Home

使用替代的、未公开的方法从 Google Finance 下载数据的简单 C# DLL

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.67/5 (12投票s)

2011 年 7 月 6 日

CPOL

5分钟阅读

viewsIcon

113868

downloadIcon

8925

使用“历史价格”页面中“下载到电子表格”链接的替代方法,从 Google Finance 下载历史和实时价格。

引言

Google 于 2006 年启动了一项金融服务,目前可通过 http://www.google.com/finance 访问。它提供了相当有趣的数据,并包含一个选项,对于某些股票,可以通过位于股票“历史价格”页面上的“下载到电子表格”链接下载历史价格。文章 使用 Silverlight 可视化实时和历史股票数据 深入分析了如何自动执行此操作以自动检索历史数据。该想法包括参数化形式为 http://www.google.com/finance/historical?q={stockCode}&startdate={startDate}&enddate={endDate}&output=csv 的 URL。

但是,此选项并非适用于许多股票,例如属于某些非美国交易所的股票,或适用于货币。幸运的是,存在一种替代的(未公开的)方法,本文探讨的正是这种方法,它几乎可用于“列出”在 Google 上的任何证券。

其背后的想法是利用另一种历史报价来源,该来源可通过类型为 http://www.google.com/finance/getprices?q={code}&x={exchange}&i={interval}&p={period}&f={fields} 的 URL 访问。使用此方法,可以下载(据我所知)Google 上提供的任何证券的信息,只要 Google 为其提供了实时图表。事实上,我认为其主要目的是为该网站的交互式图表提供数据。

为了利用这种第二种方法,本文介绍了一个 C# .NET 2.0 类库,该库自动化了两个操作:

  1. 根据一些输入参数生成下载 URL。
  2. 将从 Google 收到的原始数据转换为更易读的格式。

构建 URL 并下载数据

如前所述,URL 匹配格式:http://www.google.com/finance/getprices?q={Code}&x={Exchange}&i={Interval}&p={Period}&f={Fields}。参数的含义是:

  • Code。证券的代码。例如,Google 为 GOOG,欧元/美元货币对为 EURUSD。此参数区分大小写,必须大写才能识别。
  • Exchange。证券上市的交易所。例如,NASDAQ 用于 GOOGCURRENCY 用于 EURUSD。交易所必须大写,并且可以为空以表示美国交易所。
  • Interval。Google 将数据分组为区间,其长度(以秒为单位)由此参数定义。其最小值是 60 秒。
  • Period。将返回数据的时期。Google 始终返回最新数据。此参数的示例包括 1d(一天)、1w(一周)、1m(一个月)或 1y(一年)。
  • Fields。要返回的字段。此参数似乎被 Google 忽略,因为它总是返回每个区间的日期、开盘价、最高价、最低价、收盘价和成交量。

例如,URL http://www.google.com/finance/getprices?q=LHA&x=ETR&i=60&p=1d&f=d,c,h,l,o,v 的意思是:下载日期、收盘价、最高价、最低价、开盘价和成交量 (f=d,c,h,l,o,v) 的字段,数据按 60 秒的间隔分组 (i=60),用于交易所“ETR” (x=ETR) 上市的证券 LHA (q=LHA) 的最后一天 (p=1d) 的数据。

调用该 URL 后,会下载类似以下内容的数据:

EXCHANGE=ETR
MARKET_OPEN_MINUTE=540
MARKET_CLOSE_MINUTE=1050
INTERVAL=60
COLUMNS=DATE,CLOSE,HIGH,LOW,OPEN,VOLUME
DATA=
TIMEZONE_OFFSET=120
a1306998060,14.84,14.95,14.83,14.93,54359
2,14.84,14.84,14.84,14.84,97
3,14.865,14.865,14.84,14.84,5584
4,14.875,14.875,14.875,14.875,1230
5,14.865,14.885,14.85,14.88,14962
6,14.845,14.86,14.84,14.86,7596
7,14.855,14.855,14.84,14.845,20912
8,14.845,14.85,14.845,14.85,9833
9,14.85,14.85,14.85,14.85,2358

...

如可见,返回的信息由两部分组成:

  • 标题。以 TIMEZONE_OFFSET 条目结束。最有趣的字段是:
    1. COLUMNS:定义数据行字段的出现顺序。
    2. INTERVAL:每行数据代表的秒数。
  • 数据。这部分由几行组成,包含每行数据对应时间段的收盘价/最高价/最低价/开盘价/成交量值,长度为“interval”。日期有两种表示方式:
    1. 绝对。格式:“a” + 自 1970 年 1 月 1 日(UNIX 纪元的开始)以来的秒数。在示例中,只有第一行数据使用它('a1306713600')。
    2. 相对。格式:自最后一个“绝对日期”以来的区间数。

类库

类库包含两个类:

  • DownloadURIBuilder。其任务是创建下载数据的 URL。它公开了以下构造函数和方法:
  • /// <summary>
    /// Define here the exchange and the ticker.
    /// </summary>
    public DownloadURIBuilder(string exchange, string tickerName);
    
    /// <summary>
    /// Constructs the URI, using the object's exchange and ticker and the 
    /// given interval and period. 
    /// </summary>
    public string getGetPricesUri(int interval, string period) {
    
    /// <summary>
    /// Calls getGetPricesUri with Interval = one day and Period = the number of years
    /// since 1970.
    ///
    /// The parameter 'lastDate' must be the current date. DateTime.Now isn't used to
    /// avoid dependencies with the system time.
    /// </summary>
    public string getGetPricesUriToDownloadAllData(DateTime lastDate);
            
    /// </summary>
    /// Calls getGetPricesUri with Interval = 1 day and Period = the number of 
    /// days between 'startDate' and 'endDate'. The aim of this method is to return 
    /// at least the data between 'startDate' and today.
    /// Although the ending date is fixed (Google
    /// doesn't allow to define it), it is passed
    /// as an argument in order to avoid dependencies 
    /// between the library code and the current system time. 
    /// 
    /// Evidently, this method's URL returns data prior
    /// to 'startDate'. To avoid this, things 
    /// like the number of holidays between 'startDate'
    /// and 'endDate' should be taken into account. 
    /// It seems that that would overcomplicate things for this simple example. 
    /// </summary>
    public string getGetPricesUriForRecentData(DateTime startDate, DateTime endDate);
    
    /// <summary>
    /// Calls getGetPricesUri with Interval = 1 minute (the minimum possible value) 
    /// and Period = 1 day.
    /// </summary>
    public string getGetPricesUriForLastQuote();
  • DataProcessor。解释数据并将其转换为更易读的内容。此类包含两个公共方法:
  • /// <summary>
    /// Recovers the current (sometimes real-time) quote from the input stream.
    /// To be used in conjunction with DownloadUriBuilder.getGetPricesUrlForLastQuote().
    /// Extracts today's open, high, low, close and volume (OHLCV) from 'stream'. 
    /// To do this, it scans the returned data. The 'open' is the first value, the 'close'
    /// the last, the high and the low are the highest and lowest of all of the values
    /// returned and the volume is the sum of all the volume fields.
    /// </summary>
    public String processStreamMadeOfOneMinuteBarsToExtractMostRecentOHLCVForCurrentDay(
           Stream stream, out string errorMessage) {
    
    /// <summary>
    /// To be used together with DownloadUriBuilder.getGetPricesUriToDownloadAllData() and 
    /// DownloadUriBuilder.getGetPricesUriForRecentData(). Transforms the input into a CSV
    /// file with Date, Open, High, Low, Close and Volume headers and a line per day. 
    /// </summary>
    public String processStreamMadeOfOneDayLinesToExtractHistoricalData(Stream str, 
                                                           out string errorMessage)

例如,下载欧元/美元货币对所有历史数据的过程如下:

  1. 创建一个 DownloadUriBuilder 对象,将 exchange 参数设置为 CURRENCY,将 tickerName 参数设置为 EURUSD。两个参数都必须大写(也就是说,Google 不会识别 CuRRencyEurUSD)。类库不会自动将此参数设置为大写。这使其更具灵活性,因为它将能够支持未来可能的交易所或包含小写字符的股票代码。
  2. 调用类方法 getGetPricesUriToDownloadAllData(),并使用返回的 URL(例如),通过框架的 WebClient 类下载数据。
  3. 创建 DataProcessor 类型的对象,并调用方法 processStreamMadeOfOneDayLinesToExtractHistoricalData(Stream str, out string errorMessage)。可以使用 WebClient 类的 OpenRead() 方法获取流。如果一切顺利,errorMessage 为 null 或空,您可以使用返回的数据字符串。否则,您可以使用此输出参数显示出了什么问题。

演示工具

演示工具非常简单明了。它是一个 Windows 应用程序,有一个单一窗体,分为三个块:

  • 第一个块允许用户选择 URL 构建参数:交易所、股票代码和下载间隔。
  • 第二个块显示当前 URL。
  • 第三个(也是最后一个)块在按下“下载”按钮后显示下载的数据。它包括通过调用 DataProcessor 公开的方法之一处理的数据,或者通过单击“原始数据”复选框从 Google 返回的数据。还有一个选项可以通过单击“保存”按钮来保存结果。

Sample Image - maximum width is 600 pixels

结论

本文介绍了一种使用 Google Finance 的未公开功能来下载金融数据的简单方法。希望您觉得它对您有所帮助。

历史

  • 2011 年 7 月 4 日
    • 初始版本。
© . All rights reserved.