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

Yahoo! Managed

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.87/5 (56投票s)

2009年9月23日

Apache

12分钟阅读

viewsIcon

567023

downloadIcon

25573

使用 .NET 下载金融数据、管理在线投资组合或使用 Yahoo! 的 Search BOSS。

Showcase

引言

Yahoo! 提供的 Web 服务很不错,但您需要知道正确的标签和符号以及如何构建 URL 来使用它。这个库将承担这项繁琐的任务,并将收到的数据以托管类(managed classes)的形式返回。

本文借助一些示例,提供了该库的基本理解和应用。有关实际信息、发布版或文档等,请参阅项目主页

Using the Code

本文中的每个示例都需要以下导入:

using MaasOne;
using MaasOne.Base;

下载类和命名空间

本节中的每个示例都需要以下导入:

using MaasOne.Finance.YahooFinance;

该库提供了许多不同的类用于下载数据,但每个下载类都遵循相同的原理。每个类都继承自通用 `Base.DownloadClient` 类。此类提供了控制下载会话和获取数据的基本功能。每个下载类的唯一区别是 `Settings` 属性以及类型为 `T` 的结果类。每个下载类都有一个 `Settings` 属性,其中包含一个专门的设置类。此类每次都继承自 `Base.SettingsBase`。结果对象可以是任何类型,并存储托管的结果数据。该库中存在名称标准化。例如,如果下载类名为 QuotesDownload,则设置类名为 QuotesDownloadSettings,结果类名为 QuotesResult。`Base.DownloadClient` 类是抽象的(MustInherit),因此我将以 `Finance.YahooFinance.QuotesDownload` 为例。

QuotesDownload dl = new QuotesDownload();
DownloadClient<QuotesResult> baseDl = dl;

QuotesDownloadSettings settings = dl.Settings;
settings.IDs = new string[] { "MSFT", "GOOG", "YHOO" };
settings.Properties = new QuoteProperty[] { QuoteProperty.Symbol,
                                            QuoteProperty.Name, 
                                            QuoteProperty.LastTradePriceOnly
                                          };            
SettingsBase baseSettings = baseDl.Settings;

在此示例中,您需要设置要获取数据的股票 ID。并且您必须为数据行设置行情属性。`SettingsBase` 类仅提供内部功能,在库外部,它仅对标准化很重要。

现在您可以开始下载数据了。为此,`Base.DownloadClient` 类提供了 `Download` 和 `DownloadAsync` 这两个方法。两者都是无参数的,而 `DownloadAsync` 提供了一个可选的用户参数。`Download` 函数返回通用的 `Base.Response`。

Response<QuotesResult> resp = baseDl.Download();

每个专用下载类,如 `QuotesDownload`,都可以有重载的 `Download` 和 `DownloadAsync` 方法。如果您使用标准的无参数方法(此处不将 `userArgs` 计为参数),则该类将使用 `Settings` 属性对象进行下载。通过重载方法,可能会创建一个新的设置对象,该对象是通过传递的参数创建的。`Settings` 属性对象也可以被克隆,并且只将传递的参数新设置到克隆的对象中。

`Base.Response` 存储结果 `T` 和 `Base.ConnectionInfo`。`Base.ConnectionInfo` 类提供有关下载过程的一些信息,例如下载大小、所需时间、成功状态或异常。

ConnectionInfo connInfo = resp.Connection;
if (connInfo.State == ConnectionState.Success)
{
    QuotesResult result = resp.Result;
    //...
}
else
{
    Exception ex = connInfo.Exception;
    Debug.WriteLine(ex.Message);
}

如果您想启动异步下载,情况几乎相同。您可以使用单个下载类的实例启动多个下载过程。`Base.DownloadClient` 提供了两个在下载过程完成后触发的事件。第一个事件是通用的 `AsyncDownloadCompleted`。

object userArgs = (double)1.5;
dl.AsyncDownloadCompleted += this.QuotesDownload_Completed;
dl.DownloadAsync(userArgs);

private void QuotesDownload_Completed(DownloadClient<QuotesResult> sender, 
                                      DownloadCompletedEventArgs<QuotesResult> e)
{
    sender.AsyncDownloadCompleted -= this.QuotesDownload_Completed;

    object userArgs = e.UserArgs;
    double dbl = (double)userArgs;

    SettingsBase baseSettings = e.Settings;
    QuotesDownloadSettings settings = (QuotesDownloadSettings)baseSettings;

    Response<QuotesResult> resp = e.Response;
    QuotesResult result = resp.Result;
    //...
}

委托传递 `DownloadCompletedEventArgs`。此类提供传递的用户参数、使用的设置以及包含连接信息和结果数据等的响应。在下载开始之前,设置会被克隆。因此,如果在异步下载期间下载对象的设置发生更改,则事件参数中的设置将保留当前下载过程的原始值。

第二个事件是非通用的 `AsyncDownloadCompletedEvent`,它由 `IDownload` 接口实现。`IDownload` 的功能几乎与 `DownloadClient` 一样强大,只是没有泛型部分。

object userArgs = (double)1.5;
dl.AsyncDownloadCompletedEvent += this.IDownload_Completed;
dl.DownloadAsync(userArgs);

private void IDownload_Completed(IDownload sender, IDownloadCompletedEventArgs e) 
{
    sender.AsyncDownloadCompletedEvent -= this.IDownload_Completed;

    object userArgs = e.UserArgs;
    double dbl = (double)userArgs;

    SettingsBase baseSettings = e.Settings;
    QuotesDownloadSettings settings = (QuotesDownloadSettings)baseSettings;

    IResponse resp = e.GetResponse();
    object baseResult = resp.GetObjectResult();
    QuotesResult result = (QuotesResult)baseResult;
    //...
}

在此示例中,我使用了 `Finance.YahooFinance.QuotesDownload` 类。借助以下概述,您可以查看此库中最专业的下载类。

  • Finance.YahooFinance
    • AlphabeticIDIndexDownload:按索引(A-Z)下载有效的 Yahoo! Finance ID。
    • ChartDownload:下载技术分析图表。
    • CompanyInfoDownload:下载公司的主要信息。
    • CompanyProfileDownload:下载公司简介数据。
    • CompanyStatisticsDownload:下载公司的财务统计数据。
    • FuturesChainDownload:下载期货链。
    • HistQuotesDownload:下载历史行情。
    • IDSearchDownload:按关键字搜索有效的 Yahoo! Finance ID。
    • MarketDownload:下载包含行业、细分行业和公司的市场概览。
    • MarketQuotesDownload:下载特定行业、细分行业或公司包含的市场行情。
    • QuotesDownload:下载多达 85 个行情属性。
    • QuoteOptionsDownload:下载看跌期权和看涨期权。
  • Finance.YahooPortfolio
    • YPortfolioManager:管理您的 Yahoo! 投资组合(创建、编辑和删除投资组合、视图和组件)。
    • HoldingsDownload:下载持股数据。
    • PortfolioInfoDownload:下载所有投资组合的概览,不含组件。
    • PortfolioDownload:下载投资组合视图的组件。
  • Finance.YahooScreener
    • BondScreenerDownload:根据特定标准监控债券。
    • StockScreenerDownload:根据特定标准监控股票。
  • Search.BOSS
    • SearchDownload:下载 Web、图像、新闻和拼写服务的搜索查询数据。
    • RelatedSuggestionsDownload:下载相关的搜索建议。
  • Geo.GeoPlanet
    • PlacesDownload:下载 Geo Planet API 的地理数据(Yahoo! 已弃用)。
  • Geo.PlaceFinder
    • PlaceFinderDownload:下载 Place Finder API 的地理数据。
  • Weather.YahooWeather
    • LocationIDSearchDownload:下载天气 API 的位置 ID。
    • WeatherFeedDownload:下载天气预报。

除了这些 Yahoo! 命名空间外,还有一个 RSS 命名空间。一些 Web 服务提供 RSS Feed,此类可用于下载 RSS 2.0 Feed。

  • RSS
    • FeedDownload:下载 RSS 2.0 Feed。

该项目最初是为了封装 Yahoo! Web 服务而开始的,但也可以扩展到其他 Web 服务。目前已经实现了对 MSN Money(Microsoft)的支持。

  • Finance.MSNMoney
    • ChartDownload:下载技术分析图表。
    • HistQuotesDownload:下载历史行情。
    • IDSearchDownload:按关键字搜索有效的 Yahoo! Finance ID。
    • QuotesDownload:下载行情属性。

由于扩展的可能性,命名空间结构如下:MaasOne.[KindOfWebService].[NameOfWebService]。因此,可以利用同类 Web 服务但不同提供商的协同效应。

Finance.YahooFinance

本节中的每个示例都需要以下导入:

using MaasOne.Finance;
using MaasOne.Finance.YahooFinance; 

`Finance.YahooFinance` 命名空间包含 Yahoo! Finance Web 服务的类。下载原理始终相同,但我将展示一些示例以方便理解。

首先,我们想获取一些 ID。为此有不同的类。其中一个就是 `IDSearchDownload`。

IDSearchDownload dl = new IDSearchDownload();
IDQuerySearchDownloadSettings settings = new IDQuerySearchDownloadSettings();
settings.Query = "dow";
settings.Markets = FinancialMarket.AllMarkets;
settings.ResultsIndex = 0;
settings.Server = YahooServer.Germany;
settings.Type = SecurityType.Any;
dl.Settings = settings;

Response<IDSearchResult> resp = dl.Download();

foreach (IDSearchData id in resp.Result.Items)
{
    string idStr = id.ID;
}

使用 `IDQuerySearchDownloadSettings`,您每次请求最多可以下载 20 条结果,并且可以设置起始索引(如果总共有超过 20 条结果)。使用 `IDInstantSearchDownloadSettings`,您最多可以下载 10 条结果,而无需起始索引,也没有服务器、排名或类型等指定。

按字母索引搜索 ID 有点特殊,因为它结合了 `AlphabeticIDIndexDownload` 和 `IDSearchDownload`。

//Download TopIndex (e.g. [A], [B], [1-9])
AlphabeticIDIndexDownload dl = new AlphabeticIDIndexDownload();
dl.Settings.TopIndex = null;
Response<AlphabeticIDIndexResult> resp = dl.Download();

//Download Index (e.g. [C], [Cl], [Ca(1/10)])
AlphabeticalTopIndex topIndex = (AlphabeticalTopIndex)resp.Result.Items[2];
dl.Settings.TopIndex = topIndex;
Response<AlphabeticIDIndexResult> resp2 = dl.Download();

//Download ID Search Results
AlphabeticalIndex index = resp.Result.Items[0];
IDSearchDownload dl2 = new IDSearchDownload();
Response<IDSearchResult> resp3 = dl2.Download(index);

IDSearchData[] idResults = resp3.Result.Items;

利用收到的 ID,可以使用其他类下载数据。我已经在上面的“下载类”部分展示了一个示例。这里是另一个使用 `HistQuotesDownload` 的示例。

HistQuotesDownload dl = new HistQuotesDownload();
dl.Settings.IDs = new string[] { "GOOG" };
dl.Settings.FromDate = new DateTime(2010, 1, 1);
dl.Settings.ToDate = DateTime.Today;
dl.Settings.Interval = HistQuotesInterval.Weekly;

Response<HistQuotesResult> resp = dl.Download();

foreach (HistQuotesDataChain hqc in resp.Result.Chains)
{
    foreach (HistQuotesData hqd in hqc)
    {
        double close = hqd.Close;
        double closeAdj = hqd.CloseAdjusted;
        long volume = hqd.Volume;
        //...
    }
}

此命名空间中的其他下载类(以及该库中的大多数类)都遵循相同的原理:实例化、设置、下载响应、使用结果数据。

Finance.YahooFinance.Support

`Support` 命名空间提供了许多对于直接获取数据不是必需的类。此命名空间仅用于更轻松地处理这些数据。为此,您有不同的数据类。`Support.YID` 类管理所有与 Yahoo! Finance ID 相关的信息。这样的 ID 构建得相当结构化。要获取 Apple 股票(在 XETRA 交易所交易)的数据,您需要 ID "AAPL.DE"。在 NYSE 交易的股票只有一个 ID "AAPL"。这表明在大多数情况下,您可以从 ID 后缀推断出股票交易所(但有多个美国股票交易所没有后缀)。为此,`YID` 类提供了 `StockExchange` 属性来存储名称、ID 或交易时间等信息。您可以证明在机器本地时区或 UTC 时区是否在特定时间进行交易。您可以使用 `IDSearchResult` 创建 `YID` 的新实例。在大多数情况下,搜索结果会提供一个已知的股票交易所,并且 `YID` 构造函数将自动管理结果数据。`Support.WorldMarket` 类管理所有已知的、Yahoo! 支持的股票交易所以及一些指数的集合。您有一个大陆、国家和指数的结构来反映世界市场状况(由 Yahoo! 提供)。股票指数将由 `YIndexID` 类表示,该类继承自 `YID`。这里有一个额外的属性 `DownloadComponents`,它指示下载器是加载指数本身的数据还是指数中股票的数据。另一个 `IID` 类是 `YCurrencyID`。此类表示基准货币和相对货币之间的货币关系。为此,有 `Currency` 属性 `BaseCurrency` 和 `DepCurrency`。您下载的结果(`QuotesDownload` -> `LastTradePriceOnly`)格式为 1 `BaseCurrency` : X `DepCurrency`。

Finance.YahooPortfolio

本节中的每个示例都需要以下导入:

using MaasOne.Finance.YahooPortfolio;

使用该库,您可以管理您的在线投资组合。通常,您会借助 `YPortfolioManager` 类来完成此操作。此类提供了用于创建、编辑和删除投资组合、视图和组件的各种方法。`YPortfolioManager` 继承自 `YAccountManager`,后者提供了管理登录状态的基本方法。

private YAccountManager mManager = new YAccountManager();

private void LogIn()
{
    System.Net.NetworkCredential cred = new System.Net.NetworkCredential();
    cred.UserName = "username@yahoo.com";
    cred.Password = "password";
    bool isLoggeIn = mManager.LogIn(cred);
}

要下载您的投资组合概览,您只需要 `PortfolioInfoDownload` 类和 `YAccountManager`。

if (mManager.IsLoggedIn)
{
    PortfolioInfoDownload dl = new PortfolioInfoDownload();
    dl.Settings.Account = mManager;
    Response<PortfolioInfoResult> resp = dl.Download();
    foreach (PortfolioInfo pfi in resp.Result.Items)
    {
        string id = pfi.ID;
        string name = pfi.Name;
    }
}

如果您想下载单个投资组合的特定视图,您还需要 `YAccountManager` 和 `PortfolioDownload` 设置的特定投资组合 ID。实时视图和基本面视图是静态的。它们不能被编辑或删除。

if (mManager.IsLoggedIn)
{
    PortfolioDownload dl = new PortfolioDownload();
    dl.Settings.Account = mManager;
    dl.Settings.PortfolioID = "your_portfolio_id";
    dl.Settings.ViewIndex = 0; //The first view
    //dl.Settings.DownloadRealTimeView = true; //Real-Time
    //dl.Settings.DownloadFundamentalsView = true; //Fundamentals

    Response<Portfolio> resp = dl.Download();

    Portfolio pf = resp.Result;

    string[] allViews = pf.AvailableViews;
    string selView = pf.SelectedView;

    foreach (IID id in pf.IDs)
    {
        string idStr = id.ID;
    }


    PortfolioColumnType[] columns = pf.Columns;
    foreach (PortfolioColumnType clm in columns)
    {
        Debug.Write(clm.ToString() + "|");
    }
    Debug.Write("\n");
    foreach (PortfolioDataRow row in pf.Rows)
    {
        foreach (PortfolioColumnType clm in row.AvailableColumns)
        {
            object cellValue = row[clm];
            Debug.Write(cellValue.ToString());
        }
        Debug.Write("\n");
    }
}

这些示例仅仅是简单的下载工作。要编辑您的投资组合,您需要上传要更改的新数据。为此,您有 `YPortfolioManager`。这与其他下载类不同。您没有 `Settings` 属性,并且有多个事件用于不同的操作。

private YPortfolioManager mPfManager = new YPortfolioManager();

登录后,您可以添加一个新的投资组合。

Response<Portfolio> createResp = mPfManager.CreatePortfolio("MyPortfolio");
Portfolio pf = createResp.Result;
Debug.WriteLine("New Portfolio: " + pf.Info.Name);

现在您可以更改名称。

mPfManager.EditPortfolio(pf.Info.ID, "MyPortfolio_NewName");
                
Response<Portfolio> editResp = mPfManager.DownloadPortfolio(pf.Info.ID);
pf = editResp.Result;
Debug.WriteLine("Edit Name: " + pf.Info.Name);

或者再次删除它。

Response<PortfolioInfoResult> deleteResp = mPfManager.DeletePortfolio(pf.Info.ID);
PortfolioInfo[] restPortfolios = deleteResp.Result.Items;

下一步是向投资组合添加新股票。

Response<Portfolio> addResp = mPfManager.AddPortfolioItem("portfolioID", "GOOG");
Portfolio pf = addResp.Result;
foreach (IID id in pf.IDs)
{
    if (id.ID == "GOOG")
    {
        Debug.WriteLine("found");
    }
}

当然,您也可以删除它们。

mPfManager.DeletePortfolioItem(pf.Info.ID, "GOOG");

在 Yahoo! Portfolio 中,您可以为您的股票设置持股。首先,您必须下载实际数据。您可以使用 `HoldingsDownload`/`YAccountManager` 或 `YPortfolioManager` 来完成此操作。

HoldingsDownload dl = new HoldingsDownload();
dl.Settings.Account = mManager;
dl.Settings.PortfolioID = "portfolioID";
Response<HoldingsResult> resp = dl.Download();

Holding[] holdings = resp.Result.Items;

foreach (Holding h in holdings)
{
    string id = h.ID;
    int shares = h.Shares;
    double pricePaid = h.PricePaid;
    Nullable<DateTime> tradeDate = h.TradeDate;
    //...
}

现在您可以编辑和更新这些值。

holdings[0].PricePaid = 35.29;
holdings[0].Shares = 100;
holdings[0].TradeDate = DateTime.Today;

mPfManager.EditHoldings("portfolioID", holdings);

提示:您可以使用 `EditHoldings` 方法添加或删除投资组合中的多个项目/ID,或者完全清空投资组合(空数组)。投资组合将由传递的 `Holding` 数组完全更新。

创建、编辑和删除投资组合视图几乎相同,因此我现在跳转到 Yahoo! Search BOSS。

Search.BOSS

本节中的每个示例都需要以下导入:

using MaasOne.Search.BOSS;

Yahoo! Search BOSS 是使用 Yahoo! 的 Web、图像和新闻搜索(还包括拼写和博客)的最新 Web 服务。该库使用 BOSS v2。如果您想使用此服务,您必须注册并创建一个 OAuth 密钥,并为此付费。获得该 OAuth 密钥后,您就可以使用 Yahoo! Managed 的这部分来轻松自动化您的 BOSS 查询。

为此,您可以使用 `Search.BOSS.SearchDownload` 类。主要有一个常规的 `SearchDownloadSettings` 类用于设置 OAuth 凭据等。

SearchDownload dl = new SearchDownload();

SearchDownloadSettings settings = dl.Settings;
dl.Settings.ConsumerKey = "your_oauth_key";
dl.Settings.ConsumerSecret = "your_oauth_secret";
dl.Settings.HttpsUsed = true;

设置通用选项后,您必须设置要使用的服务。可以在单个查询中使用多种服务。

Culture culture = new Culture(Language.en, Country.US);
string queryText = "test";

SearchService service = null;

WebSearchService web = new WebSearchService();
web.LimitedWeb = true;
service = web;
service.Culture = culture;
service.Query = queryText;
service.Index = 0;
service.Count = 10;
dl.Settings.Services.Add(service);

NewsSearchService news = new NewsSearchService();
news.AlwaysLatestDateNow = true;
service = news;
service.Culture = culture;
service.Query = queryText;
service.Index = 0;
service.Count = 10;
dl.Settings.Services.Add(service);

ImageSearchService images = new ImageSearchService();
images.Dimensions = ImageSearchDimensions.All;
service = web;
service.Culture = culture;
service.Query = queryText;
service.Index = 0;
service.Count = 10;
dl.Settings.Services.Add(service);

然后您可以开始下载数据。结果被分成不同的 `SearchDataConatiner` 类,分别对应每种服务类型。在那里,您有一个 `Type` 属性,指示服务类型和专用容器类的类型,例如 `WebSearchDataContainer`。对于 Items,您有 `SearchData` 类及其专用的服务继承类,例如 `WebSearchData`。

Response<SearchResult> resp = dl.Download();

foreach (SearchDataContainer container in resp.Result.Containers)
{
    if (container.Type == SearchResultType.Web)
    {
        WebSearchDataContainer webContainer = (WebSearchDataContainer)container;
        foreach (WebSearchData wsd in webContainer.Items)
        {
            SearchData sd = wsd;
            string title = sd.Title;
            string description = sd.Description;
            Uri url = sd.Url;
            Uri clickUrl = sd.ClickUrl;

            string displyUrl = wsd.DisplayUrl;
            Language lang = wsd.Language;
            DateTime crawlDate = wsd.CrawlingDate;
        }
    }
}

参与项目

我期待将此项目扩展到其他 Web 服务。如果您也有兴趣,可以参与该项目。主要工作将是创建设置类(和 URL)以及结果解析方法。下载数据的框架已经可用。

如果您有兴趣,请发送邮件。

鸣谢

  • Angelo Cresta,感谢他出色的 bug 修复/测试工作。
  • Zvonimir Digas,感谢他提供的股票交易所时间表。
  • Alain Dionne,感谢他提供的加拿大指数信息。

历史

  • 2012 年 5 月 1 日
    • 版本 0.11.2
      • 已更改 `YPortfolioManager`
      • 已更改 `YAccountManager`
      • 已更改 `HistQuotesData`
  • 版本历史记录从 0.7.8 到 0.11.2
  • 2010 年 11 月 26 日
    • 版本 0.7.8
      • 内部更改 `QuotesDownload`
      • 已更改 `HistQuoteData`
  • 2010 年 11 月 12 日
    • 版本 0.7.7
      • 次要更改
      • 内部优化
      • 杂项 bug 修复
      • CF 3.5 版本
  • 2010 年 9 月 15 日
    • 版本 0.7.6
      • 添加了 `Culture` 类
      • 添加了 `Language` 枚举
      • 添加了 `Region` 枚举
      • 已修复 `Base.Download`
      • 已更改 `Support.YID`
      • 已扩展 `ChartDownload`
      • 已扩展 `FeedDownload`
      • 已修复 `KeyStatisticsDownload`
      • 内部优化
      • 杂项 bug 修复
      • 更新 `market.xml`
  • 2010 年 7 月 22 日
    • 版本 0.7.5
      • 已更改 `Country` 枚举
      • 已更改 `WorldMarket`
      • 已更改 `CountryInfo`
      • 已更改 `ContinentInfo`
      • 已更改 `NonAPI.IDSearchDownload`
      • 杂项 bug 修复
      • 更新 `market.xml`
  • 2010 年 7 月 21 日
    • 版本 0.7.4
      • 已扩展 `HistQuotesDownload`
      • 添加了 `HistQuotesDataChain`
      • 已修复 `CompanyStatisticsDownload`
      • `Base.Download` 方法现在是 `Protected` 而不是 `Friend`
      • 已更改 `QuoteData.Values`
      • 内部优化
      • 杂项 bug 修复
  • 2010 年 7 月 20 日
    • 版本 0.7.3
      • 已更改 `IDSearchDownloadChangedEventArgs`
      • 已更改 `FinancialSecurityType`
      • 已更改 `Feed` 和 `FeedDownload`
      • `Base.Download` 方法现在是 `Protected` 而不是 `Friend`
      • XML 自动文本编码
      • 内部下载结构已更改
      • 内部优化
      • 杂项 bug 修复
  • 2010 年 7 月 14 日
    • 版本 0.7.2
      • 已更改 `API.IDSearch`
      • 已更改 `Base.ConnectionInfo`
      • 杂项 bug 修复
  • 2010 年 6 月 29 日
    • 版本 0.7.1
      • 已更改 `RSS.Feed`
      • 杂项 bug 修复
      • 内部优化
      • 更新 `market.xml`
  • 2010 年 6 月 24 日
    • 版本 0.7
      • 下载结构已更改
      • 线程安全的下载
      • 添加了 `Base.Response`
      • 添加了 `Base.ConnectionInfo`
      • 添加了 `CompanyStatisticsDownload`
      • 命名空间结构已更改(Finance 项目的从属关系)
      • 已更改 `MarketDownload`
      • 杂项 bug 修复
      • 内部优化
  • 2010 年 4 月 18 日
    • 版本 0.6
      • 添加了 `QuotesBaseData`
      • 添加了 `QuotesBaseDownload`
      • 添加了 `QuoteOption`
      • 添加了 `QuoteOptionsDownload`
      • 数据导入/导出已更改
      • 已更改 `StockExchange`
      • 优化了 `MarketDownload`
      • 杂项 bug 修复
      • 内部优化
      • 更新 `market.xml`
  • 2010 年 3 月 24 日
    • 版本 0.5
      • 命名空间结构已更改
      • Compact Framework 2.0 版本
      • 实现了 ID 搜索
      • 实现了字母 ID 列表下载
      • 添加了 `ISIN` 类
      • 修正了 `DownloadFailure` 参数(已弃用)
      • 数据导入/导出已更改
      • 次要 bug 修复
      • 内部优化
      • 更新 `market.xml`
  • 2010 年 1 月 14 日
    • 版本 0.4.3
      • YQL URL 更改
  • 2010 年 1 月 6 日
    • 版本 0.4.2
      • 添加了代理支持
  • 2009 年 12 月 14 日
    • 版本 0.4.1
      • 添加了商品
      • 添加了特殊货币
  • 2009 年 12 月 10 日
    • 版本 0.4
      • YQL 实现
      • 数据导入/导出
      • 添加了 `StockExchange`
      • 添加了 `IID` 接口
      • 添加了 `MarketDownload`
      • 次要 bug 修复
      • 更新 `market.xml`
  • 2009 年 11 月 22 日
    • 版本 0.3
      • 货币兑换结构已更改
      • 添加了 `YID`
      • 添加了股票交易所
      • 下载器 bug 修复
      • 完成了 `Servers`
  • 2009 年 10 月 27 日
    • 版本 0.2
      • CSV 读取器 bug 修复
      • 清理下载对象的处置
      • 已修改 `QuoteData`
      • 多个指数的行情下载
      • 添加了指数
      • 完成了 `Currencies`
      • 枚举描述
  • 2009 年 9 月 26 日
    • 版本 0.1
      • 添加了 `Base.Download`
      • 添加了服务器
  • 2009 年 9 月 24 日
    • 更新了源代码
  • 2009 年 9 月 23 日
    • 初次发布
© . All rights reserved.