├── .gitignore ├── CHANGELOG.md ├── IQFeed.CSharpApiClient.sln ├── LICENSE ├── README.md ├── VERSION ├── appveyor.yml ├── data ├── dailies_newest.zip ├── dailies_oldest.zip ├── intervals_1s_newest.zip ├── intervals_1s_oldest.zip ├── intervals_5s_newest.zip ├── intervals_5s_oldest.zip ├── monthlies_newest.zip ├── monthlies_oldest.zip ├── samples │ ├── IOPTION_sample.zip │ └── mktsymbols_v2_sample.zip ├── ticks_newest.zip ├── ticks_oldest.zip ├── ticks_oldest60.zip ├── weeklies_newest.zip └── weeklies_oldest.zip ├── docs └── USING-WITH-PYTHON.md └── src ├── IQFeed.CSharpApiClient.Examples ├── App.config ├── Common │ ├── ConcurrentHistoricalBase.cs │ ├── ConsoleHelper.cs │ ├── DataType.cs │ ├── IExample.cs │ ├── IExampleAsync.cs │ └── MarketData.cs ├── Examples │ ├── BasicFileHistorical │ │ └── BasicFileHistoricalExample.cs │ ├── BasicHistorical │ │ └── BasicHistoricalExample.cs │ ├── ConcurrentFileHistorical │ │ └── ConcurrentFileHistoricalExample.cs │ ├── ConcurrentHistorical │ │ └── ConcurrentHistoricalExample.cs │ ├── ExpiredOptions │ │ └── ExpiredOptionsExample.cs │ ├── OptionableStocks │ │ ├── OptionableStock.cs │ │ └── OptionableStocksExample.cs │ ├── StreamingLevel1 │ │ ├── StreamingLevel1DynamicExample.cs │ │ ├── StreamingLevel1DynamicV2Example.cs │ │ └── StreamingLevel1Example.cs │ └── StreamingLevel2 │ │ └── StreamingLevel2Example.cs ├── IQFeed.CSharpApiClient.Examples.csproj ├── Program.cs └── README.md ├── IQFeed.CSharpApiClient.Extensions.Tests.Integration ├── IQFeed.CSharpApiClient.Extensions.Tests.Integration.csproj ├── Lookup │ └── Historical │ │ └── Resample │ │ ├── IntervalMessageExtensionsTests.cs │ │ └── TickMessageExtensionsTests.cs └── TestData │ ├── TestData.cs │ ├── TestDataTests.cs │ └── TestDataType.cs ├── IQFeed.CSharpApiClient.Extensions.Tests ├── Common │ ├── CultureNameTestCase.cs │ └── TestHelper.cs ├── IQFeed.CSharpApiClient.Extensions.Tests.csproj └── Lookup │ └── Historical │ ├── HistoricalBarTests.cs │ └── Resample │ ├── IntervalMessageExtensionsTests.cs │ └── TickMessageExtensionsTests.cs ├── IQFeed.CSharpApiClient.Extensions ├── Common │ └── DateTimeExtensions.cs ├── IQFeed.CSharpApiClient.Extensions.csproj └── Lookup │ └── Historical │ ├── HistoricalBar.cs │ └── Resample │ ├── IntervalMessageExtensions.cs │ └── TickMessageExtensions.cs ├── IQFeed.CSharpApiClient.Tests.Integration ├── App.config ├── IQFeed.CSharpApiClient.Tests.Integration.csproj ├── Lookup │ ├── Chains │ │ └── ChainsFacadeTests.cs │ ├── Historical │ │ ├── HistoricalFacadeMultiClientTests.cs │ │ ├── HistoricalFacadeTests.cs │ │ └── HistoricalFileFacadeTests.cs │ ├── MarketSummary │ │ ├── MarketSummaryFacadeTests.cs │ │ └── MarketSummaryFileFacadeTests.cs │ ├── News │ │ └── NewsFacadeTests.cs │ └── Symbol │ │ ├── Downloader │ │ └── FileDownloadTests.cs │ │ ├── Settings.cs │ │ └── SymbolFacadeTests.cs └── Streaming │ ├── Admin │ └── AdminClientTests.cs │ ├── Derivative │ └── DerivativeClientTests.cs │ ├── Level1 │ ├── Level1ClientDynamicFieldsetTests.cs │ └── Level1ClientTests.cs │ └── Level2 │ ├── Level2ClientOldProtocolTests.cs │ └── Level2ClientTests.cs ├── IQFeed.CSharpApiClient.Tests ├── Common │ ├── CultureNameTestCase.cs │ ├── ExceptionFactoryTests.cs │ └── TestHelper.cs ├── Extensions │ ├── ByteExtensionsTests.cs │ └── StringExtensionsTests.cs ├── IQFeed.CSharpApiClient.Tests.csproj ├── Lookup │ ├── Chains │ │ ├── Futures │ │ │ └── FutureMonthCodeTests.cs │ │ └── Messages │ │ │ ├── EquityOptionMessageTests.cs │ │ │ ├── FutureMessageTests.cs │ │ │ ├── FutureOptionMessageTests.cs │ │ │ └── FutureSpreadMessageTests.cs │ ├── Common │ │ ├── BaseLookupMessageHandlerTestClass.cs │ │ └── BaseLookupMessageHandlerTests.cs │ ├── Historical │ │ ├── HistoricalRequestFormatterTests.cs │ │ └── Messages │ │ │ ├── DailyWeeklyMonthlyMessageTests.cs │ │ │ ├── IntervalMessageTests.cs │ │ │ └── TickMessageTests.cs │ ├── LookupRateLimiterTests.cs │ ├── MarketSummary │ │ └── MarketSummaryMessageTests.cs │ ├── News │ │ └── NewsRequestFormatterTests.cs │ └── Symbol │ │ ├── Common │ │ └── LocalCacheStrategyTests.cs │ │ ├── Messages │ │ └── SymbolByFilterMessageTests.cs │ │ └── SymbolRequestFormatterTests.cs ├── Socket │ └── SocketMessageHandlerTests.cs └── Streaming │ ├── Admin │ └── AdminRequestFormatterTests.cs │ ├── Common │ └── Messages │ │ ├── ErrorMessageTests.cs │ │ ├── SymbolNotFoundMessageTests.cs │ │ ├── SystemMessageTests.cs │ │ └── TimestampMessageTests.cs │ ├── Derivative │ ├── DerivativeRequestFormatterTests.cs │ └── Messages │ │ └── IntervalBarMessageTest.cs │ ├── Level1 │ ├── Dynamic │ │ ├── Handlers │ │ │ └── Level1DynamicMessageHandlerPerformanceTests.cs │ │ └── Messages │ │ │ └── UpdateSummaryDynamicMessageTypesFactoryTests.cs │ ├── Handlers │ │ ├── Level1MessageDynamicHandlerPerformanceTests.cs │ │ └── Level1MessageHandlerPerformanceTests.cs │ ├── Level1DynamicFieldsPerformanceTests.cs │ ├── Level1DynamicFieldsTests.cs │ ├── Level1RequestFormatterTests.cs │ └── Messages │ │ ├── FundamentalMessageTests.cs │ │ ├── NewsMessageTests.cs │ │ ├── RegionalUpdateMessageTests.cs │ │ ├── TradeCorrectionMessageTests.cs │ │ ├── UpdateSummaryMessagePerformanceTests.cs │ │ └── UpdateSummaryMessageTests.cs │ └── Level2 │ ├── Level2MessageHandlerTests.cs │ ├── Level2RequestFormatterTests.cs │ └── Messages │ └── Level2MessageTests.cs └── IQFeed.CSharpApiClient ├── Common ├── ExceptionFactory.cs ├── Exceptions │ ├── IQFeedException.cs │ ├── InvalidDataIQFeedException.cs │ ├── NoDataIQFeedException.cs │ └── SymbolNotFoundIQFeedException.cs ├── FieldParser.cs ├── Interfaces │ ├── IClient.cs │ └── IRequestFormatter.cs ├── InvalidMessage.cs ├── LoggingLevel.cs ├── MessageContainer.cs ├── Messages │ └── ProtocolMessage.cs └── RequestFormatter.cs ├── Extensions ├── ByteExtensions.cs ├── EnumExtensions.cs ├── EventExtentions.cs ├── NullableExtensions.cs ├── StringExtensions.cs └── TaskExtensions.cs ├── IQFeed.CSharpApiClient.csproj ├── IQFeedDefault.cs ├── IQFeedLauncher.cs ├── Lookup ├── Chains │ ├── ChainsFacade.cs │ ├── ChainsMessageHandler.cs │ ├── ChainsRequestFormatter.cs │ ├── Equities │ │ ├── EquityOption.cs │ │ └── EquityOptionMonthCode.cs │ ├── Futures │ │ ├── Future.cs │ │ ├── FutureMonthCode.cs │ │ ├── FutureOption.cs │ │ └── FutureSpread.cs │ ├── IChainsFacade.cs │ ├── IChainsFacadeSync.cs │ ├── Messages │ │ ├── ChainsMessage.cs │ │ ├── EquityOptionMessage.cs │ │ ├── FutureMessage.cs │ │ ├── FutureOptionMessage.cs │ │ └── FutureSpreadMessage.cs │ ├── OptionFilterType.cs │ ├── OptionSide.cs │ └── OptionSideFilterType.cs ├── Common │ ├── BaseLookupFacade.cs │ ├── BaseLookupMessageHandler.cs │ ├── LookupMessageFileHandler.cs │ └── LookupMessageFileParser.cs ├── Historical │ ├── Enums │ │ ├── DataDirection.cs │ │ └── LabelAtBeginning.cs │ ├── Facades │ │ ├── HistoricalFacade.cs │ │ ├── HistoricalFileFacade.cs │ │ ├── IHistoricalFacade.cs │ │ └── IHistoricalFacadeSync.cs │ ├── HistoricalIntervalType.cs │ ├── HistoricalMessageHandler.cs │ ├── HistoricalRequestFormatter.cs │ ├── IHistoricalMessageHandler.cs │ └── Messages │ │ ├── DailyWeeklyMonthlyMessage.cs │ │ ├── IDailyWeeklyMonthlyMessage.cs │ │ ├── IHistoricalMessage.cs │ │ ├── IIntervalMessage.cs │ │ ├── ITickMessage.cs │ │ ├── IntervalMessage.cs │ │ └── TickMessage.cs ├── LookupClient.cs ├── LookupClientFactory.cs ├── LookupDefault.cs ├── LookupDispatcher.cs ├── LookupRateLimiter.cs ├── MarketSummary │ ├── Facades │ │ ├── IMarketSummaryFacade.cs │ │ ├── MarketSummaryFacade.cs │ │ └── MarketSummaryFileFacade.cs │ ├── MarketSummaryDynamicFieldset.cs │ ├── MarketSummaryFieldsetDescriptor.cs │ ├── MarketSummaryHandler.cs │ ├── MarketSummaryRequestFormatter.cs │ └── Messages │ │ └── MarketSummaryMessage.cs ├── News │ ├── Enums │ │ ├── FormatType.cs │ │ └── NewsFormatType.cs │ ├── INewsFacade.cs │ ├── INewsFacadeSync.cs │ ├── Messages │ │ └── NewsHeadlinesMessage.cs │ ├── NewsFacade.cs │ ├── NewsMessageHandler.cs │ └── NewsRequestFormatter.cs └── Symbol │ ├── Downloader │ ├── FileDownloader.cs │ ├── ILocalCacheStrategy.cs │ └── LocalCacheStrategy.cs │ ├── Enums │ ├── FieldToSearch.cs │ └── FilterType.cs │ ├── ExpiredOptions │ ├── ExpiredOption.cs │ └── ExpiredOptionReader.cs │ ├── ISymbolFacade.cs │ ├── ISymbolFacadeDownload.cs │ ├── ISymbolFacadeSync.cs │ ├── ListedMarket.cs │ ├── MarketSymbols │ ├── MarketSymbol.cs │ ├── MarketSymbolExchange.cs │ ├── MarketSymbolExtensions.cs │ ├── MarketSymbolListedMarket.cs │ ├── MarketSymbolReader.cs │ └── MarketSymbolSecurityType.cs │ ├── Messages │ ├── ListedMarketMessage.cs │ ├── NaicsCodeInfoMessage.cs │ ├── SecurityTypeMessage.cs │ ├── SicCodeInfoMessage.cs │ ├── SymbolByFilterMessage.cs │ ├── SymbolByNaicsCodeMessage.cs │ ├── SymbolBySicCodeMessage.cs │ └── TradeConditionMessage.cs │ ├── SecurityType.cs │ ├── SymbolDefault.cs │ ├── SymbolFacade.cs │ ├── SymbolMessageHandler.cs │ └── SymbolRequestFormatter.cs ├── Socket ├── SocketClient.cs ├── SocketDiagnostic.cs ├── SocketMessageEventArgs.cs └── SocketMessageHandler.cs └── Streaming ├── Admin ├── AdminClient.cs ├── AdminClientFactory.cs ├── AdminMessageHandler.cs ├── AdminRequestFormatter.cs ├── ClientType.cs ├── IAdminClient.cs ├── IAdminMessage.cs ├── Messages │ ├── AutoConnectMessage.cs │ ├── AutoConnectMessageType.cs │ ├── ClientAppMessage.cs │ ├── ClientAppMessageType.cs │ ├── ClientStatsMessage.cs │ ├── LoginIdMessage.cs │ ├── LoginInfoMessage.cs │ ├── LoginInfoMessageType.cs │ ├── PasswordMessage.cs │ └── StatsMessage.cs └── StatsStatusType.cs ├── Common └── Messages │ ├── ErrorMessage.cs │ ├── SymbolNotFoundMessage.cs │ ├── SystemMessage.cs │ └── TimestampMessage.cs ├── Derivative ├── DerivativeClient.cs ├── DerivativeClientFactory.cs ├── DerivativeDefault.cs ├── DerivativeIntervalType.cs ├── DerivativeMessageHandler.cs ├── DerivativeRequestFormatter.cs ├── DerivativeWatchDefinition.cs ├── IDerivativeClient.cs ├── IDerivativeEvent.cs ├── IDerivativeMessageHandler.cs └── Messages │ ├── IIntervalBarMessage.cs │ ├── IntervalBarMessage.cs │ └── IntervalBarType.cs ├── FieldsetDescriptionAttribute.cs ├── Level1 ├── Dynamic │ ├── Handlers │ │ ├── ILevel1DynamicMessageHandler.cs │ │ └── Level1DynamicMessageHandler.cs │ ├── ILevel1DynamicClient.cs │ ├── ILevel1DynamicEvent.cs │ ├── ILevel1DynamicSnapshot.cs │ ├── ILevel1DynamicSnapshotSync.cs │ ├── Level1DynamicClient.cs │ ├── Level1DynamicClientFactory.cs │ ├── Level1DynamicSnapshot.cs │ └── Messages │ │ ├── IUpdateSummaryDynamicMessage.cs │ │ └── UpdateSummaryDynamicMessageTypesFactory.cs ├── DynamicFieldset.cs ├── Handlers │ ├── BaseLevel1MessageHandler.cs │ ├── ILevel1MessageDynamicHandler.cs │ ├── ILevel1MessageHandler.cs │ ├── Level1MessageDynamicHandler.cs │ └── Level1MessageHandler.cs ├── ILevel1Client.cs ├── ILevel1Event.cs ├── ILevel1EventCommon.cs ├── ILevel1Snapshot.cs ├── ILevel1SnapshotSync.cs ├── Level1Client.cs ├── Level1ClientBase.cs ├── Level1ClientFactory.cs ├── Level1Default.cs ├── Level1DynamicFields.cs ├── Level1RequestFormatter.cs ├── Level1Snapshot.cs └── Messages │ ├── FundamentalMessage.cs │ ├── IRegionalUpdateMessage.cs │ ├── ITradeCorrectionMessage.cs │ ├── IUpdateSummaryMessage.cs │ ├── NewsMessage.cs │ ├── RegionalUpdateMessage.cs │ ├── TradeCorrectionMessage.cs │ ├── UpdateSummaryDynamicMessage.cs │ └── UpdateSummaryMessage.cs └── Level2 ├── Enums ├── Level2MessageType.cs └── Level2Side.cs ├── ILevel2Client.cs ├── ILevel2Event.cs ├── ILevel2MessageHandler.cs ├── ILevel2Snapshot.cs ├── Level2Client.cs ├── Level2ClientFactory.cs ├── Level2Default.cs ├── Level2MessageHandler.cs ├── Level2RequestFormatter.cs ├── Level2Snapshot.cs └── Messages ├── IOrderAddUpdateSummaryMessage.cs ├── IOrderDeleteMessage.cs ├── IPriceLevelDeleteMessage.cs ├── IPriceLevelUpdateSummaryMessage.cs ├── IUpdateSummaryMessage.cs ├── MarketMakerNameMessage.cs ├── OrderAddUpdateSummaryMessage.cs ├── OrderDeleteMessage.cs ├── PriceLevelDeleteMessage.cs ├── PriceLevelOrderMessage.cs ├── PriceLevelUpdateSummaryMessage.cs └── UpdateSummaryMessage.cs /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Mathieu Paquette 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /VERSION: -------------------------------------------------------------------------------- 1 | 2.10.0 2 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | image: Visual Studio 2022 2 | 3 | version: '{build}' 4 | 5 | install: 6 | - ps: >- 7 | $FileVersion = Get-Content $env:appveyor_build_folder\VERSION 8 | 9 | $Version = If ($env:appveyor_repo_branch -eq "release") {"$FileVersion"} Else {"$FileVersion.$env:appveyor_build_number"} 10 | 11 | Update-AppveyorBuild -Version $Version 12 | 13 | dotnet_csproj: 14 | patch: true 15 | file: '**\*.csproj' 16 | version: '{version}' 17 | package_version: '{version}' 18 | assembly_version: '{version}' 19 | file_version: '{version}' 20 | informational_version: '{version}' 21 | 22 | configuration: Release 23 | 24 | before_build: 25 | - nuget restore 26 | - dotnet restore 27 | 28 | test_script: 29 | - cmd: dotnet test .\src\IQFeed.CSharpApiClient.Tests\IQFeed.CSharpApiClient.Tests.csproj 30 | - cmd: dotnet test .\src\IQFeed.CSharpApiClient.Extensions.Tests\IQFeed.CSharpApiClient.Extensions.Tests.csproj 31 | - cmd: dotnet test .\src\IQFeed.CSharpApiClient.Extensions.Tests.Integration\IQFeed.CSharpApiClient.Extensions.Tests.Integration.csproj 32 | 33 | build: 34 | project: IQFeed.CSharpApiClient.sln 35 | publish_nuget: true 36 | publish_nuget_symbols: true 37 | verbosity: normal 38 | 39 | deploy: 40 | # Deploying to NuGet feed (MyGet.org) 41 | - provider: NuGet 42 | name: MyGet 43 | server: https://www.myget.org/F/iqfeedcsharpapiclient/api/v2/package 44 | api_key: 45 | secure: UBKXVuF4UwMea9mcl8hGLaHxOTBu3GNgzPvuEUWIzU+Nf6a8eTtBRyKITBepZl6i 46 | skip_symbols: false 47 | symbol_server: https://www.myget.org/F/iqfeedcsharpapiclient/symbols/api/v2/package 48 | artifact: /.*\.nupkg/ 49 | 50 | # Deploying to NuGet feed (NuGet.org) 51 | - provider: NuGet 52 | name: NuGet 53 | on: 54 | branch: release 55 | server: https://www.nuget.org/api/v2/package 56 | api_key: 57 | secure: LVcj56aqBOqfj6uavO70Bjxj6WwrXOH0kzoCfBFcZeZ+Xlmf3CEHIG7sa21TFCoq 58 | skip_symbols: true 59 | symbol_server: https://nuget.smbsrc.net/ 60 | artifact: /.*\.nupkg/ 61 | -------------------------------------------------------------------------------- /data/dailies_newest.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathpaquette/IQFeed.CSharpApiClient/59804b4180b262dea8d5f090417a943b27bf4e4f/data/dailies_newest.zip -------------------------------------------------------------------------------- /data/dailies_oldest.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathpaquette/IQFeed.CSharpApiClient/59804b4180b262dea8d5f090417a943b27bf4e4f/data/dailies_oldest.zip -------------------------------------------------------------------------------- /data/intervals_1s_newest.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathpaquette/IQFeed.CSharpApiClient/59804b4180b262dea8d5f090417a943b27bf4e4f/data/intervals_1s_newest.zip -------------------------------------------------------------------------------- /data/intervals_1s_oldest.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathpaquette/IQFeed.CSharpApiClient/59804b4180b262dea8d5f090417a943b27bf4e4f/data/intervals_1s_oldest.zip -------------------------------------------------------------------------------- /data/intervals_5s_newest.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathpaquette/IQFeed.CSharpApiClient/59804b4180b262dea8d5f090417a943b27bf4e4f/data/intervals_5s_newest.zip -------------------------------------------------------------------------------- /data/intervals_5s_oldest.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathpaquette/IQFeed.CSharpApiClient/59804b4180b262dea8d5f090417a943b27bf4e4f/data/intervals_5s_oldest.zip -------------------------------------------------------------------------------- /data/monthlies_newest.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathpaquette/IQFeed.CSharpApiClient/59804b4180b262dea8d5f090417a943b27bf4e4f/data/monthlies_newest.zip -------------------------------------------------------------------------------- /data/monthlies_oldest.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathpaquette/IQFeed.CSharpApiClient/59804b4180b262dea8d5f090417a943b27bf4e4f/data/monthlies_oldest.zip -------------------------------------------------------------------------------- /data/samples/IOPTION_sample.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathpaquette/IQFeed.CSharpApiClient/59804b4180b262dea8d5f090417a943b27bf4e4f/data/samples/IOPTION_sample.zip -------------------------------------------------------------------------------- /data/samples/mktsymbols_v2_sample.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathpaquette/IQFeed.CSharpApiClient/59804b4180b262dea8d5f090417a943b27bf4e4f/data/samples/mktsymbols_v2_sample.zip -------------------------------------------------------------------------------- /data/ticks_newest.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathpaquette/IQFeed.CSharpApiClient/59804b4180b262dea8d5f090417a943b27bf4e4f/data/ticks_newest.zip -------------------------------------------------------------------------------- /data/ticks_oldest.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathpaquette/IQFeed.CSharpApiClient/59804b4180b262dea8d5f090417a943b27bf4e4f/data/ticks_oldest.zip -------------------------------------------------------------------------------- /data/ticks_oldest60.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathpaquette/IQFeed.CSharpApiClient/59804b4180b262dea8d5f090417a943b27bf4e4f/data/ticks_oldest60.zip -------------------------------------------------------------------------------- /data/weeklies_newest.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathpaquette/IQFeed.CSharpApiClient/59804b4180b262dea8d5f090417a943b27bf4e4f/data/weeklies_newest.zip -------------------------------------------------------------------------------- /data/weeklies_oldest.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mathpaquette/IQFeed.CSharpApiClient/59804b4180b262dea8d5f090417a943b27bf4e4f/data/weeklies_oldest.zip -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient.Examples/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient.Examples/Common/ConcurrentHistoricalBase.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Concurrent; 3 | using System.Threading.Tasks; 4 | using IQFeed.CSharpApiClient.Lookup; 5 | 6 | namespace IQFeed.CSharpApiClient.Examples.Common 7 | { 8 | public abstract class ConcurrentHistoricalBase 9 | { 10 | protected readonly LookupClient LookupClient; 11 | protected readonly ConcurrentQueue Symbols; 12 | protected int InitialCount = 0; 13 | 14 | private readonly Task[] _concurrentTasks; 15 | 16 | protected ConcurrentHistoricalBase(LookupClient lookupClient, int numberOfClients) 17 | { 18 | LookupClient = lookupClient; 19 | Symbols = new ConcurrentQueue(); 20 | _concurrentTasks = new Task[numberOfClients]; 21 | } 22 | 23 | public void Start() 24 | { 25 | InitialCount = Symbols.Count; 26 | 27 | Console.WriteLine($"Number of Concurrent Tasks: {_concurrentTasks.Length}"); 28 | Console.WriteLine($"Number of Symbols: {InitialCount}"); 29 | Console.Write("Status: "); 30 | 31 | for (var i = 0; i < _concurrentTasks.Length; i++) 32 | { 33 | _concurrentTasks[i] = Task.Run(async () => await ProcessSymbols()); 34 | } 35 | 36 | Task.WaitAll(_concurrentTasks); 37 | } 38 | 39 | protected void ShowDownloadStatus() 40 | { 41 | var count = Symbols.Count; 42 | if (count % 10 != 0) return; 43 | 44 | var progress = (InitialCount - count) / (double)InitialCount * 100; 45 | Console.Write($"{progress}%..."); 46 | } 47 | 48 | protected abstract Task ProcessSymbols(); 49 | } 50 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient.Examples/Common/ConsoleHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace IQFeed.CSharpApiClient.Examples.Common 4 | { 5 | public class ConsoleHelper 6 | { 7 | public static void ShowStarted(string name) 8 | { 9 | Console.WriteLine(""); 10 | Console.WriteLine("--------------------------------------------------"); 11 | Console.WriteLine($" {name} started..."); 12 | Console.WriteLine("--------------------------------------------------"); 13 | Console.WriteLine(""); 14 | } 15 | 16 | public static void ShowFinished(string name) 17 | { 18 | Console.WriteLine(""); 19 | Console.WriteLine("--------------------------------------------------"); 20 | Console.WriteLine($" {name} finished!"); 21 | Console.WriteLine("--------------------------------------------------"); 22 | Console.WriteLine(""); 23 | } 24 | 25 | public static void PressEnterToContinue() 26 | { 27 | Console.WriteLine(""); 28 | Console.WriteLine("*************************************"); 29 | Console.WriteLine("** PRESS ENTER TO CONTINUE **"); 30 | Console.WriteLine("*************************************"); 31 | Console.ReadLine(); 32 | } 33 | 34 | public static void ShowExamplesCompleted() 35 | { 36 | Console.ForegroundColor = ConsoleColor.Green; 37 | Console.WriteLine(" EXAMPLE(S) COMPLETED!"); 38 | Console.ForegroundColor = ConsoleColor.Gray; 39 | } 40 | 41 | public static void ShowEnableWarning() 42 | { 43 | Console.ForegroundColor = ConsoleColor.Red; 44 | Console.WriteLine("!!! WARNING !!!"); 45 | Console.WriteLine(" PLEASE ENABLE AT LEAST ONE EXAMPLE BY SETTING TO TRUE THE 'ENABLE' PROPERTY FROM ONE OF THESE FILES:"); 46 | Console.WriteLine("!!! WARNING !!!"); 47 | Console.WriteLine(""); 48 | Console.ForegroundColor = ConsoleColor.Gray; 49 | } 50 | } 51 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient.Examples/Common/DataType.cs: -------------------------------------------------------------------------------- 1 | namespace IQFeed.CSharpApiClient.Examples.Common 2 | { 3 | public class DataType 4 | { 5 | public const string Tick = "tick"; 6 | public const string Interval = "interval"; 7 | public const string EOD = "eod"; 8 | } 9 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient.Examples/Common/IExample.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | 3 | namespace IQFeed.CSharpApiClient.Examples.Common 4 | { 5 | public interface IExample 6 | { 7 | void Run(); 8 | bool Enable { get; } 9 | string Name { get; } 10 | } 11 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient.Examples/Common/IExampleAsync.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | 3 | namespace IQFeed.CSharpApiClient.Examples.Common 4 | { 5 | public interface IExampleAsync : IExample 6 | { 7 | Task RunAsync(); 8 | } 9 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient.Examples/Examples/BasicFileHistorical/BasicFileHistoricalExample.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using IQFeed.CSharpApiClient.Examples.Common; 6 | using IQFeed.CSharpApiClient.Lookup; 7 | using IQFeed.CSharpApiClient.Lookup.Historical.Messages; 8 | 9 | namespace IQFeed.CSharpApiClient.Examples.Examples.BasicFileHistorical 10 | { 11 | public class BasicFileHistoricalExample : IExampleAsync 12 | { 13 | public bool Enable => false; // *** SET TO TRUE TO RUN THIS EXAMPLE *** 14 | public string Name => nameof(BasicFileHistoricalExample); 15 | 16 | private const string DownloadBasePath = "downloads"; 17 | private const string Symbol = "AAPL"; 18 | 19 | public async Task RunAsync() 20 | { 21 | // ************************************* 22 | 23 | // Step 1 - !!! Configure your credentials for IQConnect in user environment variable or app.config !!! 24 | // Check the documentation for more information. 25 | 26 | // Step 2 - Run IQConnect launcher 27 | IQFeedLauncher.Start(); 28 | 29 | // Step 3 - Use the appropriate factory to create the client 30 | var lookupClient = LookupClientFactory.CreateNew(); 31 | 32 | // Step 4 - Connect it 33 | lookupClient.Connect(); 34 | 35 | var tmpFilename = await lookupClient.Historical.File.GetHistoryTickDatapointsAsync(Symbol, 1000); 36 | // Step 5 - Make file request! 37 | 38 | // Step 6 - Move the file 39 | var basePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, DownloadBasePath); 40 | var fullPath = Path.Combine(basePath, $"{DateTime.Now:yyyyMMddHHmmss}-{Symbol}.csv"); 41 | 42 | Directory.CreateDirectory(basePath); 43 | File.Move(tmpFilename, fullPath); 44 | 45 | // Step 7 - Parse TickMessages from saved file 46 | var ticks = TickMessage.ParseFromFile(fullPath).ToList(); 47 | 48 | Console.WriteLine($"Saved {Symbol} ticks in {fullPath}"); 49 | } 50 | 51 | public void Run() 52 | { 53 | throw new System.NotImplementedException(); 54 | } 55 | } 56 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient.Examples/Examples/BasicHistorical/BasicHistoricalExample.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Threading.Tasks; 4 | using IQFeed.CSharpApiClient.Examples.Common; 5 | using IQFeed.CSharpApiClient.Lookup; 6 | 7 | namespace IQFeed.CSharpApiClient.Examples.Examples.BasicHistorical 8 | { 9 | public class BasicHistoricalExample : IExampleAsync 10 | { 11 | public bool Enable => false; // *** SET TO TRUE TO RUN THIS EXAMPLE *** 12 | public string Name => nameof(BasicHistoricalExample); 13 | 14 | public async Task RunAsync() 15 | { 16 | // ************************************* 17 | 18 | // Step 1 - !!! Configure your credentials for IQConnect in user environment variable or app.config !!! 19 | // Check the documentation for more information. 20 | 21 | // Step 2 - Run IQConnect launcher 22 | IQFeedLauncher.Start(); 23 | 24 | // Step 3 - Use the appropriate factory to create the client 25 | var lookupClient = LookupClientFactory.CreateNew(); 26 | 27 | // Step 4 - Connect it 28 | lookupClient.Connect(); 29 | 30 | // Step 5 - Make any requests you need or want! 31 | var tickMessages = await lookupClient.Historical.GetHistoryTickDatapointsAsync("AAPL", 100); 32 | var intervalMessage = await lookupClient.Historical.GetHistoryIntervalDaysAsync("AAPL", 5, 10, 100); 33 | var dailyMessages = await lookupClient.Historical.GetHistoryDailyDatapointsAsync("AAPL", 100); 34 | 35 | Console.WriteLine($"Fetched {tickMessages.Count()} Tick messages"); 36 | Console.WriteLine($"Fetched {intervalMessage.Count()} Interval messages"); 37 | Console.WriteLine($"Fetched {dailyMessages.Count()} Daily messages"); 38 | } 39 | 40 | void IExample.Run() 41 | { 42 | throw new System.NotImplementedException(); 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient.Examples/Examples/ExpiredOptions/ExpiredOptionsExample.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using IQFeed.CSharpApiClient.Examples.Common; 4 | using IQFeed.CSharpApiClient.Lookup; 5 | 6 | namespace IQFeed.CSharpApiClient.Examples.Examples.ExpiredOptions 7 | { 8 | public class ExpiredOptionsExample : IExample 9 | { 10 | public bool Enable => false; // *** SET TO TRUE TO RUN THIS EXAMPLE *** 11 | public string Name => nameof(ExpiredOptionsExample); 12 | 13 | /// 14 | /// Please note that Expired Options file is huge. 15 | /// It's about 600 MB so iterating through all rows 16 | /// will take a while, especially if you don't have SSD. 17 | /// 18 | public void Run() 19 | { 20 | var lookupClient = LookupClientFactory.CreateNew(); 21 | 22 | Console.WriteLine("Downloading and Caching Expired Options file from IQFeed servers..."); 23 | Console.WriteLine("*** This may take a while the first time... ***\n"); 24 | 25 | // Getting the first 10000 expired options with Expiration date >= Today - 180 days 26 | var expiredOptionsGreaterThan180Days = lookupClient.Symbol.GetAllExpiredOptions() 27 | .Select(x => x.EquityOption) 28 | .Where(x => x.Expiration >= DateTime.Now.AddDays(-180)) 29 | .Take(10000) // COMMENT OUT THIS LINE TO GET THEM ALL 30 | .ToList(); 31 | 32 | Console.WriteLine($"Found {expiredOptionsGreaterThan180Days.Count} expired options matching Expiration date >= Today - 180 days"); 33 | 34 | 35 | // Getting the first 10000 expired options for APPL stock 36 | var expiredOptionsForSpecificStock = lookupClient.Symbol.GetAllExpiredOptions() 37 | .Select(x => x.EquityOption) 38 | .Where(x => x.EquitySymbol == "AAPL") 39 | .Take(10000) // COMMENT OUT THIS LINE TO GET THEM ALL 40 | .ToList(); 41 | 42 | Console.WriteLine($"Found {expiredOptionsForSpecificStock.Count} expired options for AAPL stock"); 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient.Examples/Examples/OptionableStocks/OptionableStock.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using IQFeed.CSharpApiClient.Lookup.Chains.Equities; 4 | using IQFeed.CSharpApiClient.Lookup.Symbol.MarketSymbols; 5 | 6 | namespace IQFeed.CSharpApiClient.Examples.Examples.OptionableStocks 7 | { 8 | public class OptionableStock 9 | { 10 | public OptionableStock(MarketSymbol marketSymbol, IEnumerable options) 11 | { 12 | MarketSymbol = marketSymbol; 13 | Options = options; 14 | } 15 | 16 | public MarketSymbol MarketSymbol { get; } 17 | public IEnumerable Options { get; } 18 | 19 | public static IEnumerable GetOptionableStocks(IEnumerable marketSymbols) 20 | { 21 | var options = new List(); 22 | var equities = new List(); 23 | var indexes = new List(); 24 | 25 | foreach (var marketSymbol in marketSymbols) 26 | { 27 | switch (marketSymbol.SecurityType) 28 | { 29 | case MarketSymbolSecurityType.IEOPTION when !string.IsNullOrEmpty(marketSymbol.Description): 30 | options.Add(marketSymbol); 31 | break; 32 | 33 | case MarketSymbolSecurityType.EQUITY: 34 | equities.Add(marketSymbol); 35 | break; 36 | 37 | case MarketSymbolSecurityType.INDEX: 38 | indexes.Add(marketSymbol); 39 | break; 40 | } 41 | } 42 | 43 | var equityOptionsBySymbol = options.Select(x => EquityOption.Parse(x.Symbol)).GroupBy(x => x.EquitySymbol); 44 | var equitiesBySymbol = equities.Concat(indexes).ToDictionary(x => x.Symbol); 45 | 46 | foreach (var equityOptions in equityOptionsBySymbol) 47 | { 48 | if (equitiesBySymbol.TryGetValue(equityOptions.Key, out var equity)) 49 | { 50 | yield return new OptionableStock(equity, equityOptions); 51 | } 52 | } 53 | } 54 | } 55 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient.Examples/Examples/OptionableStocks/OptionableStocksExample.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using IQFeed.CSharpApiClient.Examples.Common; 4 | using IQFeed.CSharpApiClient.Lookup; 5 | 6 | namespace IQFeed.CSharpApiClient.Examples.Examples.OptionableStocks 7 | { 8 | public class OptionableStocksExample : IExample 9 | { 10 | public bool Enable => false; // *** SET TO TRUE TO RUN THIS EXAMPLE *** 11 | public string Name => nameof(OptionableStocksExample); 12 | 13 | public void Run() 14 | { 15 | var lookupClient = LookupClientFactory.CreateNew(); 16 | 17 | Console.WriteLine("Downloading and Caching Market Symbols file from IQFeed servers..."); 18 | Console.WriteLine("Please note that this file is updated every day."); 19 | Console.WriteLine("*** This may take a while the first time... ***\n"); 20 | 21 | var marketSymbols = lookupClient.Symbol.GetAllMarketSymbols(); 22 | var optionableStocks = OptionableStock.GetOptionableStocks(marketSymbols).ToList(); 23 | 24 | foreach (var optionableStock in optionableStocks) 25 | { 26 | Console.WriteLine($"{optionableStock.MarketSymbol.Symbol} has {optionableStock.Options.Count()} options"); 27 | } 28 | 29 | Console.WriteLine($"Found {optionableStocks.Count} stocks with options"); 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient.Examples/IQFeed.CSharpApiClient.Examples.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | net472;net60 4 | 5 | Exe 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient.Examples/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Threading.Tasks; 4 | using IQFeed.CSharpApiClient.Examples.Common; 5 | 6 | namespace IQFeed.CSharpApiClient.Examples 7 | { 8 | class Program 9 | { 10 | static void Main(string[] args) 11 | { 12 | RunExamples().Wait(); 13 | ConsoleHelper.PressEnterToContinue(); 14 | } 15 | 16 | /// 17 | /// Running the examples one by one. You don't need to look here. 18 | /// Check the Example files only. 19 | /// 20 | /// 21 | static async Task RunExamples() 22 | { 23 | var examples = AppDomain.CurrentDomain.GetAssemblies() 24 | .SelectMany(s => s.GetTypes()) 25 | .Where(p => typeof(IExample).IsAssignableFrom(p) && !p.IsInterface).OrderBy(x => x.Name).ToList(); 26 | 27 | var enabledExamples = examples.Select(x => (IExample)Activator.CreateInstance(x)).Where(example => example.Enable).ToList(); 28 | 29 | if (enabledExamples.Count == 0) 30 | { 31 | ConsoleHelper.ShowEnableWarning(); 32 | 33 | foreach (var example in examples) 34 | Console.WriteLine($"{example.Name}.cs"); 35 | } 36 | 37 | foreach (var example in enabledExamples) 38 | { 39 | ConsoleHelper.ShowStarted(example.Name); 40 | if (example is IExampleAsync exampleAsync) 41 | { 42 | await exampleAsync.RunAsync(); 43 | } 44 | else 45 | { 46 | example.Run(); 47 | } 48 | ConsoleHelper.ShowFinished(example.Name); 49 | } 50 | 51 | if (enabledExamples.Count > 0) 52 | ConsoleHelper.ShowExamplesCompleted(); 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient.Extensions.Tests.Integration/IQFeed.CSharpApiClient.Extensions.Tests.Integration.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | net472;net60 4 | OnBuildSuccess 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 23 | 24 | -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient.Extensions.Tests.Integration/Lookup/Historical/Resample/IntervalMessageExtensionsTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using IQFeed.CSharpApiClient.Extensions.Lookup.Historical.Resample; 4 | using IQFeed.CSharpApiClient.Extensions.Tests.Integration.TestData; 5 | using IQFeed.CSharpApiClient.Lookup.Historical.Enums; 6 | using IQFeed.CSharpApiClient.Lookup.Historical.Messages; 7 | using NUnit.Framework; 8 | 9 | namespace IQFeed.CSharpApiClient.Extensions.Tests.Integration.Lookup.Historical.Resample 10 | { 11 | public class IntervalMessageExtensionsTests 12 | { 13 | [Test] 14 | public void Should_Resample_Bars_From_Intervals() 15 | { 16 | // Arrange 17 | var intervals1S = IntervalMessage.ParseFromFile(TestData.TestData.GetFileName(TestDataType.Intervals_1s, DataDirection.Oldest)).ToList(); 18 | var intervals5S = IntervalMessage.ParseFromFile(TestData.TestData.GetFileName(TestDataType.Intervals_5s, DataDirection.Oldest)).ToList(); 19 | 20 | // Act 21 | var bars = intervals1S.ToHistoricalBars(TimeSpan.FromSeconds(5), DataDirection.Oldest).ToList().ToList(); 22 | 23 | // Assert 24 | Assert.IsNotEmpty(intervals5S); 25 | Assert.AreEqual(intervals5S.Count, bars.Count); 26 | 27 | for (var i = 0; i < intervals5S.Count; i++) 28 | { 29 | var interval = intervals5S[i]; 30 | var bar = bars[i]; 31 | 32 | // TODO: create comparable 33 | if (interval.Timestamp == bar.Timestamp && 34 | interval.Open == bar.Open && 35 | interval.High == bar.High && 36 | interval.Low == bar.Low && 37 | interval.Close == bar.Close && 38 | interval.PeriodVolume == bar.PeriodVolume && 39 | interval.TotalVolume == bar.TotalVolume) 40 | { 41 | continue; 42 | } 43 | 44 | throw new Exception(); 45 | } 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient.Extensions.Tests.Integration/TestData/TestData.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | using System.IO.Compression; 3 | using IQFeed.CSharpApiClient.Lookup.Historical.Enums; 4 | using NUnit.Framework; 5 | 6 | namespace IQFeed.CSharpApiClient.Extensions.Tests.Integration.TestData 7 | { 8 | public class TestData 9 | { 10 | public static string GetFileName(TestDataType type, DataDirection direction, bool protocol60 = false) 11 | { 12 | var protocol60String = protocol60 ? "60" : string.Empty; 13 | var filename = $@"{type.ToString().ToLower()}_{direction.ToString().ToLower()}{protocol60String}"; 14 | var path = Path.Combine(TestContext.CurrentContext.TestDirectory, "data", $@"{filename}.zip"); 15 | var tmpDir = GetTemporaryDirectory(); 16 | ZipFile.ExtractToDirectory(path, tmpDir); 17 | return Path.Combine(tmpDir, $@"{filename}.csv"); 18 | } 19 | 20 | public static string GetTemporaryDirectory() 21 | { 22 | string tempDirectory = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); 23 | Directory.CreateDirectory(tempDirectory); 24 | return tempDirectory; 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient.Extensions.Tests.Integration/TestData/TestDataType.cs: -------------------------------------------------------------------------------- 1 | namespace IQFeed.CSharpApiClient.Extensions.Tests.Integration.TestData 2 | { 3 | public enum TestDataType 4 | { 5 | Dailies, 6 | Intervals_1s, 7 | Intervals_5s, 8 | Monthlies, 9 | Ticks, 10 | Weeklies 11 | } 12 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient.Extensions.Tests/Common/CultureNameTestCase.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using NUnit.Framework; 3 | 4 | namespace IQFeed.CSharpApiClient.Extensions.Tests.Common 5 | { 6 | public class CultureNameTestCase 7 | { 8 | public static IEnumerable CultureNames 9 | { 10 | get 11 | { 12 | yield return new TestCaseData("en-US"); 13 | yield return new TestCaseData("fr-FR"); 14 | yield return new TestCaseData("ru-RU"); 15 | yield return new TestCaseData("ja-JP"); 16 | yield return new TestCaseData("ar-SA"); 17 | } 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient.Extensions.Tests/Common/TestHelper.cs: -------------------------------------------------------------------------------- 1 | using System.Globalization; 2 | using System.Threading; 3 | 4 | namespace IQFeed.CSharpApiClient.Extensions.Tests.Common 5 | { 6 | public static class TestHelper 7 | { 8 | public static void SetThreadCulture(string cultureName) 9 | { 10 | var culture = CultureInfo.GetCultureInfo(cultureName); 11 | Thread.CurrentThread.CurrentCulture = culture; 12 | Thread.CurrentThread.CurrentUICulture = culture; 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient.Extensions.Tests/IQFeed.CSharpApiClient.Extensions.Tests.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | net472;net60 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient.Extensions.Tests/Lookup/Historical/HistoricalBarTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using IQFeed.CSharpApiClient.Extensions.Lookup.Historical; 3 | using IQFeed.CSharpApiClient.Extensions.Tests.Common; 4 | using NUnit.Framework; 5 | 6 | namespace IQFeed.CSharpApiClient.Extensions.Tests.Lookup.Historical 7 | { 8 | public class HistoricalBarTests 9 | { 10 | private HistoricalBar _historicalBar; 11 | 12 | [SetUp] 13 | public void SetUp() 14 | { 15 | _historicalBar = new HistoricalBar(new DateTime(2020, 01, 01, 9, 30, 00), 1.21, 1.22, 1.23, 1.24, 1000, 1, 100, 1, 12345.12345); 16 | } 17 | 18 | [Test, TestCaseSource(typeof(CultureNameTestCase), nameof(CultureNameTestCase.CultureNames))] 19 | public void Should_Return_Csv(string cultureName) 20 | { 21 | // Act 22 | TestHelper.SetThreadCulture(cultureName); 23 | var csv = _historicalBar.ToCsv(); 24 | 25 | // Assert 26 | var expectedCsv = "2020-01-01 09:30:00,1.21,1.22,1.23,1.24,1000,1,100,1,12345.1234"; 27 | Assert.AreEqual(expectedCsv, csv); 28 | } 29 | 30 | [Test, TestCaseSource(typeof(CultureNameTestCase), nameof(CultureNameTestCase.CultureNames))] 31 | public void Should_Parse(string cultureName) 32 | { 33 | // Arrange 34 | TestHelper.SetThreadCulture(cultureName); 35 | var csv = "2020-01-01 09:30:00,1.21,1.22,1.23,1.24,1000,1,100,1,12345.12345"; 36 | 37 | // Act 38 | var parsed = HistoricalBar.Parse(csv); 39 | 40 | // Assert 41 | Assert.AreEqual(parsed, _historicalBar); 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient.Extensions/Common/DateTimeExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace IQFeed.CSharpApiClient.Extensions.Common 4 | { 5 | public static class DateTimeExtensions 6 | { 7 | public static DateTime Trim(this DateTime date, long roundTicks) 8 | { 9 | return new DateTime(date.Ticks - date.Ticks % roundTicks, date.Kind); 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient.Extensions/IQFeed.CSharpApiClient.Extensions.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | net472;netstandard2.1 4 | 5 | 6 | Full 7 | 8 | true 9 | Mathieu Paquette 10 | 11 | DTN IQFeed Socket API (Client) 12 | https://github.com/mathpaquette/IQFeed.CSharpApiClient 13 | https://github.com/mathpaquette/IQFeed.CSharpApiClient 14 | LICENSE 15 | Copyright © 2020 Mathieu Paquette 16 | IQFeed.CSharpApiClient is fastest and the most well-designed C# DTN IQFeed socket API connector available to the open source community! 17 | 1.0.0.0 18 | 1.0.0.0 19 | 1.0.0 20 | 21 | 22 | 23 | True 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient.Tests.Integration/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient.Tests.Integration/IQFeed.CSharpApiClient.Tests.Integration.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | net472;net60 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient.Tests.Integration/Lookup/Symbol/Downloader/FileDownloadTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using IQFeed.CSharpApiClient.Lookup.Symbol.Downloader; 4 | using NUnit.Framework; 5 | 6 | namespace IQFeed.CSharpApiClient.Tests.Integration.Lookup.Symbol.Downloader 7 | { 8 | public class FileDownloadTests 9 | { 10 | private FileDownloader _fileDownloader; 11 | 12 | [SetUp] 13 | public void SetUp() 14 | { 15 | _fileDownloader = new FileDownloader(new LocalCacheStrategy()); 16 | } 17 | 18 | [Test] 19 | public void Should_Return_Text_Filename_From_Sample_Archive_File() 20 | { 21 | // Act 22 | var filename = _fileDownloader.GetFile(Settings.MarketSymbolsSampleUrl, false, TimeSpan.FromDays(1)); 23 | 24 | // Assert 25 | Assert.True(filename.EndsWith("mktsymbols_v2_sample.txt")); 26 | } 27 | 28 | [Test] 29 | public void Should_Return_Text_Filename_From_Sample_Archive_File_Folder() 30 | { 31 | // Arrange 32 | var downloadPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "dowload_folder"); 33 | CreateDirectory(downloadPath); 34 | 35 | // Act 36 | var filename = _fileDownloader.GetFile(downloadPath, Settings.MarketSymbolsSampleUrl, false, TimeSpan.FromDays(1)); 37 | 38 | // Assert 39 | Assert.True(filename.EndsWith("mktsymbols_v2_sample.txt")); 40 | } 41 | 42 | private void CreateDirectory(string path) 43 | { 44 | if (!Directory.Exists(path)) 45 | { 46 | Directory.CreateDirectory(path); 47 | } 48 | } 49 | } 50 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient.Tests.Integration/Lookup/Symbol/Settings.cs: -------------------------------------------------------------------------------- 1 | namespace IQFeed.CSharpApiClient.Tests.Integration.Lookup.Symbol 2 | { 3 | public class Settings 4 | { 5 | public const string MarketSymbolsSampleUrl = "https://github.com/mathpaquette/IQFeed.CSharpApiClient/raw/master/data/samples/mktsymbols_v2_sample.zip"; 6 | public const int MarketSymbolsSampleCount = 65; 7 | 8 | public const string ExpiredOptionsSampleUrl = "https://github.com/mathpaquette/IQFeed.CSharpApiClient/raw/master/data/samples/IOPTION_sample.zip"; 9 | public const int ExpiredOptionsSampleCount = 50; 10 | } 11 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient.Tests.Integration/Streaming/Level1/Level1ClientTests.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using IQFeed.CSharpApiClient.Common.Exceptions; 3 | using IQFeed.CSharpApiClient.Streaming.Level1; 4 | using IQFeed.CSharpApiClient.Streaming.Level1.Handlers; 5 | using NUnit.Framework; 6 | 7 | namespace IQFeed.CSharpApiClient.Tests.Integration.Streaming.Level1 8 | { 9 | public class Level1ClientTests 10 | { 11 | private const string Symbol = "AAPL"; 12 | private const string NotFoundSymbol = "NotFoundSymbol"; 13 | private ILevel1Client _level1Client; 14 | 15 | public Level1ClientTests() 16 | { 17 | IQFeedLauncher.Start(); 18 | } 19 | 20 | [SetUp] 21 | public void SetUp() 22 | { 23 | _level1Client = Level1ClientFactory.CreateNew(); 24 | _level1Client.Connect(); 25 | } 26 | 27 | [TearDown] 28 | public void TearDown() 29 | { 30 | _level1Client.Disconnect(); 31 | } 32 | 33 | [Test] 34 | public async Task Should_Return_FundamentalMessage() 35 | { 36 | // Act 37 | var fundamentalMessage = await _level1Client.GetFundamentalSnapshotAsync(Symbol); 38 | 39 | // Assert 40 | Assert.AreEqual(fundamentalMessage.Symbol, Symbol); 41 | } 42 | 43 | [Test] 44 | public async Task Should_Return_UpdateSummaryMessage() 45 | { 46 | // Act 47 | var updateSummaryMessage = await _level1Client.GetUpdateSummarySnapshotAsync(Symbol); 48 | 49 | // Assert 50 | Assert.AreEqual(updateSummaryMessage.Symbol, Symbol); 51 | } 52 | 53 | [Test] 54 | public void Should_Throw_Exceptions_When_SymbolNotFound_FundamentalSnapshot() 55 | { 56 | // Assert 57 | Assert.ThrowsAsync(async () => await _level1Client.GetFundamentalSnapshotAsync(NotFoundSymbol)); 58 | } 59 | 60 | [Test] 61 | public void Should_Throw_Exceptions_When_SymbolNotFound_For_UpdateSummarySnapshot() 62 | { 63 | // Assert 64 | Assert.ThrowsAsync(async () => await _level1Client.GetUpdateSummarySnapshotAsync(NotFoundSymbol)); 65 | 66 | } 67 | } 68 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient.Tests/Common/CultureNameTestCase.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using NUnit.Framework; 3 | 4 | namespace IQFeed.CSharpApiClient.Tests.Common 5 | { 6 | public class CultureNameTestCase 7 | { 8 | public static IEnumerable CultureNames 9 | { 10 | get 11 | { 12 | yield return new TestCaseData("en-US"); 13 | yield return new TestCaseData("fr-FR"); 14 | yield return new TestCaseData("ru-RU"); 15 | yield return new TestCaseData("ja-JP"); 16 | yield return new TestCaseData("ar-SA"); 17 | } 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient.Tests/Common/ExceptionFactoryTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using IQFeed.CSharpApiClient.Common; 4 | using IQFeed.CSharpApiClient.Common.Exceptions; 5 | using IQFeed.CSharpApiClient.Lookup.Historical.Messages; 6 | using NUnit.Framework; 7 | 8 | namespace IQFeed.CSharpApiClient.Tests.Common 9 | { 10 | public class ExceptionFactoryTests 11 | { 12 | private readonly ExceptionFactory _exceptionFactory; 13 | 14 | public ExceptionFactoryTests() 15 | { 16 | _exceptionFactory = new ExceptionFactory(); 17 | } 18 | 19 | [Test] 20 | public void Should_Return_InvalidData_Exception() 21 | { 22 | // Arrange 23 | var request = "request"; 24 | var intervalMessage = new IntervalMessage(new DateTime(2000, 01, 01, 9, 30, 00), 1, 1, 1, 1, 1, 1, 0); 25 | var invalidMessages = new List>() { new InvalidMessage(intervalMessage, intervalMessage.ToCsv()) }; 26 | var messages = new List() { intervalMessage }; 27 | 28 | // Act 29 | var exception = _exceptionFactory.CreateNew(request, invalidMessages, messages); 30 | 31 | // Assert 32 | var expectedException = new InvalidDataIQFeedException(request, invalidMessages, messages); 33 | Assert.AreEqual(exception, expectedException); 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient.Tests/Common/TestHelper.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Globalization; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading; 6 | 7 | namespace IQFeed.CSharpApiClient.Tests.Common 8 | { 9 | public static class TestHelper 10 | { 11 | public static void SetThreadCulture(string cultureName) 12 | { 13 | var culture = CultureInfo.GetCultureInfo(cultureName); 14 | Thread.CurrentThread.CurrentCulture = culture; 15 | Thread.CurrentThread.CurrentUICulture = culture; 16 | } 17 | 18 | public static byte[] GetMessageBytes(IEnumerable messages) 19 | { 20 | return Encoding.ASCII.GetBytes(messages.Aggregate((acc, msg) => acc += msg)); 21 | } 22 | 23 | public static byte[] GetMessageBytes(string message) 24 | { 25 | return GetMessageBytes(new List() { message }); 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient.Tests/Extensions/ByteExtensionsTests.cs: -------------------------------------------------------------------------------- 1 | using System.Text; 2 | using IQFeed.CSharpApiClient.Extensions; 3 | using NUnit.Framework; 4 | 5 | namespace IQFeed.CSharpApiClient.Tests.Extensions 6 | { 7 | public class ByteExtensionsTests 8 | { 9 | private const string EndMessage = IQFeedDefault.ProtocolEndOfMessageCharacters; 10 | 11 | [Test] 12 | public void Should_Return_False_When_Count_Is_Smaller_Then_Pattern_Length() 13 | { 14 | // Arrange 15 | var buffer = new byte[10]; 16 | var pattern = new byte[5]; 17 | 18 | // Act 19 | var result = buffer.EndsWith(4, pattern); 20 | 21 | // Assert 22 | Assert.False(result); 23 | } 24 | 25 | [Test] 26 | public void Should_Return_False_When_Buffer_Size_Is_Smaller_Then_Pattern_Size() 27 | { 28 | // Arrange 29 | var buffer = new byte[5]; 30 | var pattern = new byte[10]; 31 | 32 | // Act 33 | var result = buffer.EndsWith(buffer.Length, pattern); 34 | 35 | // Assert 36 | Assert.False(result); 37 | } 38 | 39 | [Test] 40 | public void Should_Return_True_When_Buffer_Ends_With_Pattern() 41 | { 42 | // Arrange 43 | var buffer = Encoding.ASCII.GetBytes("0123456789" + EndMessage); 44 | var pattern = Encoding.ASCII.GetBytes(EndMessage); 45 | 46 | // Act 47 | var result = buffer.EndsWith(buffer.Length, pattern); 48 | 49 | // Assert 50 | Assert.True(result); 51 | } 52 | 53 | [Test] 54 | public void Should_Return_False_When_Buffer_Doesnt_Match_Pattern() 55 | { 56 | // Arrange 57 | var altMsgEnd = EndMessage.Replace("E", "X"); 58 | var buffer = Encoding.ASCII.GetBytes("0123456789" + altMsgEnd); 59 | var pattern = Encoding.ASCII.GetBytes(EndMessage); 60 | 61 | // Act 62 | var result = buffer.EndsWith(buffer.Length, pattern); 63 | 64 | // Assert 65 | Assert.False(result); 66 | } 67 | } 68 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient.Tests/Extensions/StringExtensionsTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using IQFeed.CSharpApiClient.Extensions; 3 | using NUnit.Framework; 4 | 5 | namespace IQFeed.CSharpApiClient.Tests.Extensions 6 | { 7 | public class StringExtensionTests 8 | { 9 | [Test] 10 | public void SplitFeedMessage_ThrowsArgumentException_WhenNoProtocolDelimiterCharacterFoundInString() 11 | { 12 | // Arrange 13 | var nonDelimitedString = "nonDelimiters"; 14 | 15 | // Assert 16 | Assert.Throws(() => nonDelimitedString.SplitFeedMessage(2)); 17 | } 18 | 19 | [Test] 20 | public void SplitFeedMessage_ThrowsArgumentException_ExpectedPartsGreaterThanDelimitedStrings() 21 | { 22 | // Arrange 23 | var delimitedString = "not,enough"; 24 | 25 | // Assert 26 | Assert.Throws(() => delimitedString.SplitFeedMessage(3)); 27 | } 28 | 29 | [Test] 30 | public void SplitFeedMessage_ThrowsArgumentException_WithInvalidDelimiters() 31 | { 32 | // Arrange 33 | var delimitedString = "wrong.delimiter"; 34 | 35 | // Assert 36 | Assert.Throws(() => delimitedString.SplitFeedMessage(2)); 37 | } 38 | 39 | [Test] 40 | public void SplitFeedMessage_LastPartReturnsAllCharactersUpToTheLastDelimiter_IfSplitSizeLessThanSizeOfDelimitedMessage() 41 | { 42 | // Arrange 43 | var delimitedString = "one,two,my, company name,"; 44 | var splitSize = 3; 45 | 46 | // Act 47 | var values = delimitedString.SplitFeedMessage(splitSize); 48 | 49 | // Assert 50 | var expectedValues = new[] { "one", "two", "my, company name" }; 51 | Assert.AreEqual(values, expectedValues); 52 | } 53 | } 54 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient.Tests/IQFeed.CSharpApiClient.Tests.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | net472;net60 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient.Tests/Lookup/Chains/Futures/FutureMonthCodeTests.cs: -------------------------------------------------------------------------------- 1 | using IQFeed.CSharpApiClient.Lookup.Chains.Futures; 2 | using NUnit.Framework; 3 | 4 | namespace IQFeed.CSharpApiClient.Tests.Lookup.Chains.Futures 5 | { 6 | public class FutureMonthCodeTests 7 | { 8 | [TestCase("F", 1)] 9 | [TestCase("G", 2)] 10 | [TestCase("H", 3)] 11 | [TestCase("J", 4)] 12 | [TestCase("K", 5)] 13 | [TestCase("M", 6)] 14 | [TestCase("N", 7)] 15 | [TestCase("Q", 8)] 16 | [TestCase("U", 9)] 17 | [TestCase("V", 10)] 18 | [TestCase("X", 11)] 19 | [TestCase("Z", 12)] 20 | public void Should_Return_Decoded_Month(string monthCode, int result) 21 | { 22 | // Act 23 | var month = FutureMonthCode.Decode(monthCode); 24 | 25 | // Assert 26 | Assert.AreEqual(month, result); 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient.Tests/Lookup/Chains/Messages/FutureMessageTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using IQFeed.CSharpApiClient.Lookup.Chains.Futures; 4 | using IQFeed.CSharpApiClient.Lookup.Chains.Messages; 5 | using IQFeed.CSharpApiClient.Tests.Common; 6 | using NUnit.Framework; 7 | 8 | namespace IQFeed.CSharpApiClient.Tests.Lookup.Chains.Messages 9 | { 10 | public class FutureMessageTests 11 | { 12 | [Test, TestCaseSource(typeof(CultureNameTestCase), nameof(CultureNameTestCase.CultureNames))] 13 | public void Should_Parse_FutureMessage_Culture_Independent(string cultureName) 14 | { 15 | // Arrange 16 | TestHelper.SetThreadCulture(cultureName); 17 | var message = "LC,@ESU18,@ESZ18,@ESH19,@ESM19,@ESU19,"; 18 | var messageWithRequestId = "TESTREQUEST,LC,@ESU18,@ESZ18,@ESH19,@ESM19,@ESU19,"; 19 | 20 | // Act 21 | var futureMessageParsed = FutureMessage.Parse(message); 22 | var futureMessageWithRequestIdParsed = FutureMessage.ParseWithRequestId(messageWithRequestId); 23 | var futureMessage = new Future("@ESU18", "@ES", new DateTime(2018, 09, 01)); 24 | 25 | // Assert 26 | Assert.AreEqual(futureMessageParsed.Chains.First(), futureMessage); 27 | Assert.AreEqual("TESTREQUEST", futureMessageWithRequestIdParsed.RequestId); 28 | Assert.AreEqual(futureMessageWithRequestIdParsed.Chains.First(), futureMessage); 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient.Tests/Lookup/Chains/Messages/FutureSpreadMessageTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using IQFeed.CSharpApiClient.Lookup.Chains; 4 | using IQFeed.CSharpApiClient.Lookup.Chains.Futures; 5 | using IQFeed.CSharpApiClient.Lookup.Chains.Messages; 6 | using IQFeed.CSharpApiClient.Tests.Common; 7 | using NUnit.Framework; 8 | 9 | namespace IQFeed.CSharpApiClient.Tests.Lookup.Chains.Messages 10 | { 11 | public class FutureSpreadMessageTests 12 | { 13 | [Test, TestCaseSource(typeof(CultureNameTestCase), nameof(CultureNameTestCase.CultureNames))] 14 | public void Should_Parse_FutureSpreadMessage_Culture_Independent(string cultureName) 15 | { 16 | // Arrange 17 | TestHelper.SetThreadCulture(cultureName); 18 | var message = "LC,@ESU18-@ESH19,@ESU18-@ESM19,@ESU18-@ESU19,@ESU18-@ESZ18,@ESZ18-@ESH19,@ESZ18-@ESM19,@ESZ18-@ESU19,@ESH19-@ESM19,@ESH19-@ESU19,@ESM19-@ESU19,"; 19 | var messageWithRequestId = "TESTREQUEST,LC,@ESU18-@ESH19,@ESU18-@ESM19,@ESU18-@ESU19,@ESU18-@ESZ18,@ESZ18-@ESH19,@ESZ18-@ESM19,@ESZ18-@ESU19,@ESH19-@ESM19,@ESH19-@ESU19,@ESM19-@ESU19,"; 20 | 21 | // Act 22 | var futureSpreadMessageParsed = FutureSpreadMessage.Parse(message); 23 | var futureSpreadMessageWithRequestIdParsed = FutureSpreadMessage.ParseWithRequestId(messageWithRequestId); 24 | var futureSpread = new FutureSpread("@ESU18-@ESH19", new Future("@ESU18", "@ES", new DateTime(2018, 09, 01)), new Future("@ESH19", "@ES", new DateTime(2019, 03, 01))); 25 | 26 | // Assert 27 | Assert.AreEqual(futureSpreadMessageParsed.Chains.First(), futureSpread); 28 | Assert.AreEqual("TESTREQUEST", futureSpreadMessageWithRequestIdParsed.RequestId); 29 | Assert.AreEqual(futureSpreadMessageWithRequestIdParsed.Chains.First(), futureSpread); 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient.Tests/Lookup/Common/BaseLookupMessageHandlerTestClass.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using IQFeed.CSharpApiClient.Common; 3 | using IQFeed.CSharpApiClient.Lookup.Common; 4 | 5 | namespace IQFeed.CSharpApiClient.Tests.Lookup.Common 6 | { 7 | /// 8 | /// Test class to access protected static method from BaseLookupMessageHandler 9 | /// 10 | internal class BaseLookupMessageHandlerTestClass : BaseLookupMessageHandler 11 | { 12 | public new MessageContainer ProcessMessages(Func parserFunc, Func errorFunc, byte[] message, int count) 13 | { 14 | return base.ProcessMessages(parserFunc, errorFunc, message, count); 15 | } 16 | 17 | public new MessageContainer ProcessMessages(TryParseDelegate tryParseDelegate, Func errorFunc, byte[] message, int count) 18 | { 19 | return base.ProcessMessages(tryParseDelegate, errorFunc, message, count); 20 | } 21 | 22 | public new string ParseErrorMessage(string[] messages) 23 | { 24 | return base.ParseErrorMessage(messages); 25 | } 26 | 27 | public new string ParseErrorMessageWithRequestId(string[] messages) 28 | { 29 | return base.ParseErrorMessageWithRequestId(messages); 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient.Tests/Lookup/MarketSummary/MarketSummaryMessageTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using IQFeed.CSharpApiClient.Lookup.MarketSummary; 3 | using IQFeed.CSharpApiClient.Lookup.MarketSummary.Messages; 4 | using NUnit.Framework; 5 | 6 | namespace IQFeed.CSharpApiClient.Tests.Lookup.MarketSummary 7 | { 8 | public class MarketSummaryMessageTests 9 | { 10 | [Test] 11 | public void Should_Parse_MarketSummaryMessage() 12 | { 13 | // Arrange 14 | var requestId = "TEST"; 15 | var symbol = "MSFT"; 16 | var last = 1.234D; 17 | var tradeDate = new DateTime(2021, 03, 24); 18 | var tradeTime = new TimeSpan(11, 42, 12); 19 | var message1 = "RequestId,Symbol,Last,TradeDate,TradeTime"; 20 | var message2 = "TEST,MSFT,1.234,20210324,114212"; 21 | var values = new string[] {"TEST", "MSFT", "1.234", "20210324", "114212"}; 22 | 23 | var marketSummaryHandler = new MarketSummaryHandler(); 24 | 25 | // Act 26 | var marketSummaryMessage1Parsed = MarketSummaryMessage.Parse(message1, marketSummaryHandler); 27 | var marketSummaryMessage2Parsed = MarketSummaryMessage.Parse(message2, marketSummaryHandler); 28 | var marketSummaryMessage1 = new MarketSummaryMessage(symbol, 0, 0, last, null, null, tradeDate, 29 | tradeTime, null, null, null, null, null, null, null, null, null, null, null, 30 | null, null, null, null, null, null, null, null, null, 31 | null, null, null, null, null, null, null, requestId); 32 | var marketSummaryMessage2 = new MarketSummaryMessage(values, marketSummaryHandler); 33 | 34 | // Assert 35 | // MarketSummaryMessage1Parsed should be null, as it was the Fieldname pass 36 | Assert.IsNull(marketSummaryMessage1Parsed); 37 | Assert.IsNotNull(marketSummaryMessage2Parsed); 38 | Assert.AreEqual(marketSummaryMessage2Parsed, marketSummaryMessage1); 39 | Assert.AreEqual(marketSummaryMessage2Parsed, marketSummaryMessage2); 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient.Tests/Lookup/Symbol/Common/LocalCacheStrategyTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using IQFeed.CSharpApiClient.Lookup.Symbol.Downloader; 4 | using NUnit.Framework; 5 | 6 | namespace IQFeed.CSharpApiClient.Tests.Lookup.Symbol.Common 7 | { 8 | public class LocalCacheStrategyTests 9 | { 10 | private LocalCacheStrategy _localCacheStrategy; 11 | 12 | [SetUp] 13 | public void SetUp() 14 | { 15 | _localCacheStrategy = new LocalCacheStrategy(); 16 | } 17 | 18 | [Test] 19 | public void Should_Expire_When_File_Does_Not_Exist() 20 | { 21 | // Act 22 | var expired = _localCacheStrategy.HasExpired("invalid_path.txt", TimeSpan.MaxValue); 23 | 24 | // Assert 25 | Assert.True(expired); 26 | } 27 | 28 | [Test] 29 | public void Should_Not_Expire_When_File_Recently_Written() 30 | { 31 | // Arrange 32 | var file = Path.GetTempFileName(); 33 | File.AppendAllText(file, "content"); 34 | 35 | // Act 36 | var expired = _localCacheStrategy.HasExpired(file, TimeSpan.FromMinutes(1)); 37 | 38 | // Assert 39 | Assert.False(expired); 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient.Tests/Streaming/Common/Messages/ErrorMessageTests.cs: -------------------------------------------------------------------------------- 1 | using IQFeed.CSharpApiClient.Streaming.Common.Messages; 2 | using IQFeed.CSharpApiClient.Tests.Common; 3 | using NUnit.Framework; 4 | 5 | namespace IQFeed.CSharpApiClient.Tests.Streaming.Common.Messages 6 | { 7 | public class ErrorMessageTests 8 | { 9 | 10 | [Test, TestCaseSource(typeof(CultureNameTestCase), nameof(CultureNameTestCase.CultureNames))] 11 | public void Should_Parse_ErrorMessage_Culture_Indepedant(string cultureName) 12 | { 13 | // Arrange 14 | TestHelper.SetThreadCulture(cultureName); 15 | var message = "E,Disconnected from server"; 16 | 17 | // Act 18 | var errorMessageParsed = ErrorMessage.Parse(message); 19 | var errorMessage = new ErrorMessage("Disconnected from server"); 20 | 21 | // Assert 22 | Assert.AreEqual(errorMessageParsed, errorMessage); 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient.Tests/Streaming/Common/Messages/SymbolNotFoundMessageTests.cs: -------------------------------------------------------------------------------- 1 | using IQFeed.CSharpApiClient.Streaming.Common.Messages; 2 | using IQFeed.CSharpApiClient.Tests.Common; 3 | using NUnit.Framework; 4 | 5 | namespace IQFeed.CSharpApiClient.Tests.Streaming.Common.Messages 6 | { 7 | public class SymbolNotFoundMessageTests 8 | { 9 | [Test, TestCaseSource(typeof(CultureNameTestCase), nameof(CultureNameTestCase.CultureNames))] 10 | public void Should_Parse_SymbolNotFoundMessage_Culture_Independent(string cultureName) 11 | { 12 | // Arrange 13 | TestHelper.SetThreadCulture(cultureName); 14 | var message = "n,AAPL"; 15 | 16 | // Act 17 | var symbolNotFoundMessageParsed = SymbolNotFoundMessage.Parse(message); 18 | var symbolNotFoundMessage = new SymbolNotFoundMessage("AAPL"); 19 | 20 | // Assert 21 | Assert.AreEqual(symbolNotFoundMessageParsed, symbolNotFoundMessage); 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient.Tests/Streaming/Common/Messages/SystemMessageTests.cs: -------------------------------------------------------------------------------- 1 | using IQFeed.CSharpApiClient.Streaming.Common.Messages; 2 | using IQFeed.CSharpApiClient.Tests.Common; 3 | using NUnit.Framework; 4 | 5 | namespace IQFeed.CSharpApiClient.Tests.Streaming.Common.Messages 6 | { 7 | public class SystemMessageTests 8 | { 9 | [Test, TestCaseSource(typeof(CultureNameTestCase), nameof(CultureNameTestCase.CultureNames))] 10 | public void Should_Parse_SystemMessage_Culture_Invariant(string cultureName) 11 | { 12 | // Arrange 13 | TestHelper.SetThreadCulture(cultureName); 14 | var message = "S,STATS,,,0,0,1,0,0,0,,,Not Connected,6.0.0.4,474614,0,0,,0.02,0.02,,"; 15 | 16 | // Act 17 | var systemMessageParsed = SystemMessage.Parse(message); 18 | var systemMessage = new SystemMessage("STATS", message); 19 | 20 | // Assert 21 | Assert.AreEqual(systemMessageParsed, systemMessage); 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient.Tests/Streaming/Common/Messages/TimestampMessageTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using IQFeed.CSharpApiClient.Streaming.Common.Messages; 3 | using IQFeed.CSharpApiClient.Streaming.Level1.Messages; 4 | using IQFeed.CSharpApiClient.Tests.Common; 5 | using NUnit.Framework; 6 | 7 | namespace IQFeed.CSharpApiClient.Tests.Streaming.Common.Messages 8 | { 9 | public class TimestampMessageTests 10 | { 11 | [Test, TestCaseSource(typeof(CultureNameTestCase), nameof(CultureNameTestCase.CultureNames))] 12 | public void Should_Parse_TimestampMessage_Culture_Independent(string cultureName) 13 | { 14 | // Arrange 15 | TestHelper.SetThreadCulture(cultureName); 16 | var message = "T,20180709 14:18:31"; 17 | 18 | // Act 19 | var timestampMessageParsed = TimestampMessage.Parse(message); 20 | var timestampMessage = new TimestampMessage(new DateTime(2018, 07, 09, 14, 18, 31)); 21 | 22 | // Assert 23 | Assert.AreEqual(timestampMessageParsed, timestampMessage); 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient.Tests/Streaming/Derivative/DerivativeRequestFormatterTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using IQFeed.CSharpApiClient.Streaming.Derivative; 3 | using NUnit.Framework; 4 | 5 | namespace IQFeed.CSharpApiClient.Tests.Streaming.Derivative 6 | { 7 | public class DerivativeRequestFormatterTests 8 | { 9 | private DerivativeRequestFormatter _derivativeRequestFormatter; 10 | 11 | [SetUp] 12 | public void SetUp() 13 | { 14 | _derivativeRequestFormatter = new DerivativeRequestFormatter(); 15 | } 16 | 17 | [Test] 18 | public void Should_Format_BarWatch() 19 | { 20 | var request = _derivativeRequestFormatter.ReqBarWatch("aapl", 60, new DateTime(2018, 01, 01, 09, 30, 00), 10, 1000, new TimeSpan(9, 30, 00), new TimeSpan(16, 00, 00), "TEST", DerivativeIntervalType.S, 5); 21 | Assert.AreEqual(request, "BW,AAPL,60,20180101 093000,10,1000,093000,160000,TEST,s,,5\r\n"); 22 | } 23 | 24 | [Test] 25 | public void Should_Format_BarUnwatch() 26 | { 27 | var request = _derivativeRequestFormatter.ReqBarUnwatch("aapl", "TEST"); 28 | Assert.AreEqual(request, "BR,AAPL,TEST,\r\n"); 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient.Tests/Streaming/Derivative/Messages/IntervalBarMessageTest.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using IQFeed.CSharpApiClient.Streaming.Derivative.Messages; 3 | using IQFeed.CSharpApiClient.Tests.Common; 4 | using NUnit.Framework; 5 | 6 | namespace IQFeed.CSharpApiClient.Tests.Streaming.Derivative.Messages 7 | { 8 | public class IntervalBarMessageTest 9 | { 10 | [Test, TestCaseSource(typeof(CultureNameTestCase), nameof(CultureNameTestCase.CultureNames))] 11 | public void Should_Parse(string cultureName) 12 | { 13 | // Arrange 14 | TestHelper.SetThreadCulture(cultureName); 15 | var message = "BC,AAPL,2018-01-01 09:30:00,100.01,101.23,99.98,100.93,143562,745,0"; 16 | 17 | // Act 18 | var intervalBarMessage = new IntervalBarMessage(IntervalBarType.C, "AAPL", new DateTime(2018, 1, 1, 9, 30, 0), 100.01, 101.23, 99.98, 100.93, 143562, 745, 0); 19 | var intervalBarMessageParsed = IntervalBarMessage.Parse(message); 20 | 21 | // Assert 22 | Assert.AreEqual(intervalBarMessage, intervalBarMessageParsed); 23 | } 24 | 25 | [Test, TestCaseSource(typeof(CultureNameTestCase), nameof(CultureNameTestCase.CultureNames))] 26 | public void Should_Parse_Without_RequestId(string cultureName) 27 | { 28 | // Arrange 29 | TestHelper.SetThreadCulture(cultureName); 30 | var message = "TESTREQUEST,BC,AAPL,2018-01-01 09:30:00,100.01,101.23,99.98,100.93,143562,745,0"; 31 | 32 | // Act 33 | var intervalBarMessage = new IntervalBarMessage(IntervalBarType.C, "AAPL", new DateTime(2018, 1, 1, 9, 30, 0), 100.01, 101.23, 99.98, 100.93, 143562, 745, 0, "TESTREQUEST"); 34 | var intervalBarMessageParsed = IntervalBarMessage.ParseWithRequestId(message); 35 | 36 | // Assert 37 | Assert.AreEqual(intervalBarMessage, intervalBarMessageParsed); 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient.Tests/Streaming/Level1/Handlers/Level1MessageHandlerPerformanceTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using System.Linq; 4 | using System.Text; 5 | using IQFeed.CSharpApiClient.Streaming.Level1.Handlers; 6 | using NUnit.Framework; 7 | 8 | namespace IQFeed.CSharpApiClient.Tests.Streaming.Level1.Handlers 9 | { 10 | [Category("Performance")] 11 | [Explicit] 12 | public class Level1MessageHandlerPerformanceTests 13 | { 14 | [Test] 15 | public void Should_Process_Update_Message() 16 | { 17 | var level1MessageHandler = new Level1MessageHandler(); 18 | 19 | // Arrange 20 | var msg = "Q,AAPL,322.7500,40,16:53:23.256494,11,37629453,322.6800,100,322.8700,100,312.6000,318.4000,312.1900,308.9500,ba,873D17,2,17\r\n"; 21 | var msgBytes = Encoding.ASCII.GetBytes(msg); 22 | var count = msgBytes.Length; 23 | 24 | level1MessageHandler.Update += message => { }; 25 | 26 | const int ExecutionsCount = 5; 27 | var results = new double[ExecutionsCount]; 28 | 29 | for (int i = 0; i < ExecutionsCount; i++) 30 | { 31 | var sw = Stopwatch.StartNew(); 32 | for (var j = 0; j < 1000000; j++) 33 | { 34 | level1MessageHandler.ProcessMessages(msgBytes, count); 35 | } 36 | sw.Stop(); 37 | 38 | results[i] = sw.Elapsed.TotalMilliseconds; 39 | Console.WriteLine(sw.Elapsed.TotalMilliseconds); 40 | } 41 | 42 | Console.WriteLine($"Min: {results.Min()}"); 43 | Console.WriteLine($"Avg: {results.Average()}"); 44 | Console.WriteLine($"Max: {results.Max()}"); 45 | } 46 | } 47 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient.Tests/Streaming/Level1/Level1DynamicFieldsPerformanceTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using IQFeed.CSharpApiClient.Streaming.Level1; 4 | using NUnit.Framework; 5 | 6 | namespace IQFeed.CSharpApiClient.Tests.Streaming.Level1 7 | { 8 | [Explicit] 9 | [Category("Performance")] 10 | public class Level1DynamicFieldsPerformanceTests 11 | { 12 | [Test] 13 | public void Should_Convert_SevenDayYield() 14 | { 15 | // Arrange 16 | var message = "AAPL,"; 17 | var fields = new[] { DynamicFieldset.Symbol }; 18 | 19 | // Act 20 | for (int i = 0; i < 5; i++) 21 | { 22 | var sw = Stopwatch.StartNew(); 23 | 24 | for (int j = 0; j < 1000000; j++) 25 | { 26 | var dynamicFields = Level1DynamicFields.Parse(message, fields); 27 | } 28 | 29 | sw.Stop(); 30 | Console.WriteLine(sw.Elapsed.TotalMilliseconds); 31 | } 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient.Tests/Streaming/Level1/Messages/NewsMessageTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using IQFeed.CSharpApiClient.Streaming.Level1.Messages; 3 | using IQFeed.CSharpApiClient.Tests.Common; 4 | using NUnit.Framework; 5 | 6 | namespace IQFeed.CSharpApiClient.Tests.Streaming.Level1.Messages 7 | { 8 | public class NewsMessageTests 9 | { 10 | [Test, TestCaseSource(typeof(CultureNameTestCase), nameof(CultureNameTestCase.CultureNames))] 11 | public void Should_Parse_NewsMessage_Culture_Independent(string cultureName) 12 | { 13 | // Arrange 14 | TestHelper.SetThreadCulture(cultureName); 15 | var message = "N,1234,1122,AAPL:NFLX,20000102 152001,Very cool news,"; 16 | 17 | // Act 18 | var newsMessageParsed = NewsMessage.Parse(message); 19 | var newsMessage = new NewsMessage("1234", "1122", "AAPL:NFLX",new DateTime(2000,01,02, 15,20,01),"Very cool news"); 20 | 21 | // Arrange 22 | Assert.AreEqual(newsMessageParsed, newsMessage); 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient.Tests/Streaming/Level1/Messages/RegionalUpdateMessageTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using IQFeed.CSharpApiClient.Streaming.Level1.Messages; 3 | using IQFeed.CSharpApiClient.Tests.Common; 4 | using NUnit.Framework; 5 | 6 | namespace IQFeed.CSharpApiClient.Tests.Streaming.Level1.Messages 7 | { 8 | public class RegionalUpdateMessageTests 9 | { 10 | [Test, TestCaseSource(typeof(CultureNameTestCase), nameof(CultureNameTestCase.CultureNames))] 11 | public void Should_Parse_RegionalUpdateMessage_Culture_Independent(string cultureName) 12 | { 13 | // Arrange 14 | TestHelper.SetThreadCulture(cultureName); 15 | var message = "R,AAPL,X,1.23,100,13:00:00,1.24,200,13:00:01,0,1,2,"; 16 | 17 | // Act 18 | var regionalUpdateMessageParsed = RegionalUpdateMessage.Parse(message); 19 | var regionalUpdateMessage = new RegionalUpdateMessage("AAPL", "X", 1.23, 100, new DateTime(2000, 1, 2, 13, 00, 00), 1.24, 200, new DateTime(2000, 1, 2, 13, 00, 01), 0, 1, 2); 20 | 21 | // Arrange 22 | Assert.AreEqual(regionalUpdateMessageParsed, regionalUpdateMessage); 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient.Tests/Streaming/Level1/Messages/TradeCorrectionMessageTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using IQFeed.CSharpApiClient.Streaming.Level1.Messages; 4 | using IQFeed.CSharpApiClient.Tests.Common; 5 | using NUnit.Framework; 6 | 7 | namespace IQFeed.CSharpApiClient.Tests.Streaming.Level1.Messages 8 | { 9 | public class TradeCorrectionMessageTests 10 | { 11 | [Test, TestCaseSource(typeof(CultureNameTestCase), nameof(CultureNameTestCase.CultureNames))] 12 | public void Should_Parse_TradeCorrectionMessage_Culture_Independent(string cultureName) 13 | { 14 | // Arrange 15 | TestHelper.SetThreadCulture(cultureName); 16 | var message = "C,AAPL,I,03/30/2021,19:59:14.503633,183.3600,13,101123,8801,17"; 17 | 18 | // Act 19 | var tradeCorrectionMessageParsed = TradeCorrectionMessage.Parse(message); 20 | DateTime.TryParseExact("03/30/2021", TradeCorrectionMessage.TradeCorrectionMessageDateFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out var tradeDate); 21 | TimeSpan.TryParseExact("19:59:14.503633", TradeCorrectionMessage.TradeCorrectionMessageTimeFormat, CultureInfo.InvariantCulture, out var tradeTime); 22 | var tradeCorrectionMessage = new TradeCorrectionMessage("AAPL", "I", tradeDate, tradeTime, 183.3600, 13, 101123, "8801", 17); 23 | 24 | // Assert 25 | Assert.AreEqual(tradeCorrectionMessageParsed, tradeCorrectionMessage); 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient.Tests/Streaming/Level1/Messages/UpdateSummaryMessagePerformanceTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Diagnostics; 4 | using IQFeed.CSharpApiClient.Streaming.Level1.Messages; 5 | using NUnit.Framework; 6 | 7 | namespace IQFeed.CSharpApiClient.Tests.Streaming.Level1.Messages 8 | { 9 | [Category("Performance")] 10 | [Explicit] 11 | public class UpdateSummaryMessagePerformanceTests 12 | { 13 | public const string Message = "Q,AAPL,322.9100,13,16:53:16.164236,11,37620407,322.8700,100,323.0000,3300,312.6000,318.4000,312.1900,308.9500,O,8717,2,17"; 14 | 15 | [Test] 16 | public void Should_Parse_Double() 17 | { 18 | var messages = new List(); 19 | 20 | var sw = Stopwatch.StartNew(); 21 | 22 | for (var i = 0; i < 1000000; i++) 23 | { 24 | var parsed = UpdateSummaryMessage.Parse(Message); 25 | messages.Add(parsed); 26 | } 27 | 28 | sw.Stop(); 29 | 30 | Console.WriteLine(sw.Elapsed.Ticks); 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient.Tests/Streaming/Level1/Messages/UpdateSummaryMessageTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using IQFeed.CSharpApiClient.Streaming.Level1.Messages; 4 | using IQFeed.CSharpApiClient.Tests.Common; 5 | using NUnit.Framework; 6 | 7 | namespace IQFeed.CSharpApiClient.Tests.Streaming.Level1.Messages 8 | { 9 | public class UpdateSummaryMessageTests 10 | { 11 | [Test, TestCaseSource(typeof(CultureNameTestCase), nameof(CultureNameTestCase.CultureNames))] 12 | public void Should_Parse_UpdateSummaryMessage_Culture_Independent(string cultureName) 13 | { 14 | // Arrange 15 | TestHelper.SetThreadCulture(cultureName); 16 | var message = "P,AAPL,188.3500,52500,19:59:14.503633,19,0,188.2500,100,188.3600,100,,,,187.9700,Cbacv,8801,2,17"; 17 | 18 | // Act 19 | var updateSummaryMessageParsed = UpdateSummaryMessage.Parse(message); 20 | DateTime.TryParseExact("19:59:14.503633", UpdateSummaryMessage.UpdateMessageTimeFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out var timestamp); 21 | var updateSummaryMessage = new UpdateSummaryMessage("AAPL", 188.35, 52500, timestamp, 19, 0, 188.25, 100, 188.36, 100, 0, 0, 0, 187.97, "Cbacv", "8801"); 22 | 23 | // Assert 24 | Assert.AreEqual(updateSummaryMessageParsed, updateSummaryMessage); 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient.Tests/Streaming/Level2/Level2RequestFormatterTests.cs: -------------------------------------------------------------------------------- 1 | using IQFeed.CSharpApiClient.Streaming.Level2; 2 | using NUnit.Framework; 3 | 4 | namespace IQFeed.CSharpApiClient.Tests.Streaming.Level2 5 | { 6 | public class Level2RequestFormatterTests 7 | { 8 | private Level2RequestFormatter _level2RequestFormatter; 9 | [SetUp] 10 | public void SetUp() 11 | { 12 | _level2RequestFormatter = new Level2RequestFormatter(); 13 | } 14 | 15 | [Test] 16 | public void Should_Format_ReqWatch() 17 | { 18 | var request = _level2RequestFormatter.ReqWatch("aapl"); 19 | Assert.AreEqual(request, "wAAPL\r\n"); 20 | } 21 | 22 | [Test] 23 | public void Should_Format_ReqMarketMakerNameById() 24 | { 25 | var request = _level2RequestFormatter.ReqMarketMakerNameById("md02"); 26 | Assert.AreEqual(request, "mMD02\r\n"); 27 | } 28 | 29 | [Test] 30 | public void Should_Format_ReqUnwatch() 31 | { 32 | var request = _level2RequestFormatter.ReqUnwatch("aapl"); 33 | Assert.AreEqual(request, "rAAPL\r\n"); 34 | } 35 | 36 | [Test] 37 | public void Should_Format_ReqServerConnect() 38 | { 39 | var request = _level2RequestFormatter.ReqServerConnect(); 40 | Assert.AreEqual(request, "c\r\n"); 41 | } 42 | 43 | [Test] 44 | public void Should_Format_ReqServerDisconnect() 45 | { 46 | var request = _level2RequestFormatter.ReqServerDisconnect(); 47 | Assert.AreEqual(request, "x\r\n"); 48 | } 49 | } 50 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Common/ExceptionFactory.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using IQFeed.CSharpApiClient.Common.Exceptions; 3 | 4 | namespace IQFeed.CSharpApiClient.Common 5 | { 6 | public class ExceptionFactory 7 | { 8 | private const string DefaultMessage = "IQFeed exception received."; 9 | 10 | public IQFeedException CreateNew(string request, string errorMessage, string messageTrace) 11 | { 12 | switch (errorMessage) 13 | { 14 | case IQFeedDefault.ProtocolNoDataCharacters: 15 | return new NoDataIQFeedException(request, errorMessage, messageTrace); 16 | default: 17 | return new IQFeedException(request, DefaultMessage, errorMessage, messageTrace); 18 | } 19 | } 20 | 21 | public InvalidDataIQFeedException CreateNew(string request, IEnumerable> invalidMessages, IEnumerable messages) 22 | { 23 | return new InvalidDataIQFeedException(request, invalidMessages, messages); 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Common/Exceptions/IQFeedException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace IQFeed.CSharpApiClient.Common.Exceptions 4 | { 5 | // ReSharper disable once InconsistentNaming 6 | public class IQFeedException : Exception 7 | { 8 | /// 9 | /// Request sent to IQFeed 10 | /// 11 | public string Request { get; } 12 | 13 | /// 14 | /// Parsed exception contained in the message 15 | /// 16 | public string ErrorMessage { get; } 17 | 18 | /// 19 | /// Last messages received by IQFeed before throwing the exception 20 | /// 21 | public string MessageTrace { get; } 22 | 23 | public IQFeedException(string request, string message, string errorMessage, string messageTrace) : base(message) 24 | { 25 | Request = request; 26 | ErrorMessage = errorMessage; 27 | MessageTrace = messageTrace; 28 | } 29 | 30 | public override string ToString() 31 | { 32 | return $"{base.ToString()}, {nameof(Request)}: {Request}, {nameof(ErrorMessage)}: {ErrorMessage}, {nameof(MessageTrace)}: {MessageTrace}"; 33 | } 34 | 35 | protected bool Equals(IQFeedException other) 36 | { 37 | return Request == other.Request && ErrorMessage == other.ErrorMessage && MessageTrace == other.MessageTrace; 38 | } 39 | 40 | public override bool Equals(object obj) 41 | { 42 | if (ReferenceEquals(null, obj)) return false; 43 | if (ReferenceEquals(this, obj)) return true; 44 | if (obj.GetType() != this.GetType()) return false; 45 | return Equals((IQFeedException)obj); 46 | } 47 | 48 | public override int GetHashCode() 49 | { 50 | unchecked 51 | { 52 | var hashCode = (Request != null ? Request.GetHashCode() : 0); 53 | hashCode = (hashCode * 397) ^ (ErrorMessage != null ? ErrorMessage.GetHashCode() : 0); 54 | hashCode = (hashCode * 397) ^ (MessageTrace != null ? MessageTrace.GetHashCode() : 0); 55 | return hashCode; 56 | } 57 | } 58 | } 59 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Common/Exceptions/InvalidDataIQFeedException.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace IQFeed.CSharpApiClient.Common.Exceptions 4 | { 5 | // ReSharper disable once InconsistentNaming 6 | public class InvalidDataIQFeedException : IQFeedException 7 | { 8 | public IEnumerable> InvalidMessages { get; } 9 | public IEnumerable Messages { get; } 10 | 11 | public InvalidDataIQFeedException(string request, IEnumerable> invalidMessages, IEnumerable messages) : 12 | base(request, "Unable to parse received data.", "Invalid data", $"Please check ${nameof(InvalidMessages)} property.") 13 | { 14 | InvalidMessages = invalidMessages; 15 | Messages = messages; 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Common/Exceptions/NoDataIQFeedException.cs: -------------------------------------------------------------------------------- 1 | namespace IQFeed.CSharpApiClient.Common.Exceptions 2 | { 3 | // ReSharper disable once InconsistentNaming 4 | public class NoDataIQFeedException : IQFeedException 5 | { 6 | private const string NoDataMessage = "IQFeed doesn't have any data for the request sent."; 7 | 8 | public NoDataIQFeedException(string request, string errorMessage, string messageTrace) : base(request, NoDataMessage, errorMessage, messageTrace) { } 9 | } 10 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Common/Exceptions/SymbolNotFoundIQFeedException.cs: -------------------------------------------------------------------------------- 1 | namespace IQFeed.CSharpApiClient.Common.Exceptions 2 | { 3 | // ReSharper disable once InconsistentNaming 4 | public class SymbolNotFoundIQFeedException : IQFeedException 5 | { 6 | public SymbolNotFoundIQFeedException(string request, string symbol) : base(request, $"The specified Symbol '{symbol}' wasn't found on IQFeed.", string.Empty, string.Empty) { } 7 | } 8 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Common/FieldParser.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | 4 | namespace IQFeed.CSharpApiClient.Common 5 | { 6 | /// 7 | /// Helper class used for parsing IQ Feed fields 8 | /// 9 | public static class FieldParser 10 | { 11 | public static double ParseDouble(string value) 12 | { 13 | double.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out var parsedValue); 14 | return parsedValue; 15 | } 16 | 17 | public static int ParseInt(string value) 18 | { 19 | int.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out var parsedValue); 20 | return parsedValue; 21 | } 22 | 23 | public static TimeSpan ParseTime(string value, string format) 24 | { 25 | DateTime.TryParseExact(value, format, CultureInfo.InvariantCulture, DateTimeStyles.None, out var parsedValue); 26 | return parsedValue.TimeOfDay; 27 | } 28 | 29 | public static DateTime ParseDate(string value, string format) 30 | { 31 | DateTime.TryParseExact(value, format, CultureInfo.InvariantCulture, DateTimeStyles.None, out var parsedValue); 32 | return parsedValue; 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Common/Interfaces/IClient.cs: -------------------------------------------------------------------------------- 1 | namespace IQFeed.CSharpApiClient.Common.Interfaces 2 | { 3 | public interface IClient 4 | { 5 | void Connect(); 6 | void Disconnect(); 7 | } 8 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Common/Interfaces/IRequestFormatter.cs: -------------------------------------------------------------------------------- 1 | namespace IQFeed.CSharpApiClient.Common.Interfaces 2 | { 3 | public interface IRequestFormatter 4 | { 5 | string SetClientName(string name); 6 | string SetProtocol(string version); 7 | } 8 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Common/InvalidMessage.cs: -------------------------------------------------------------------------------- 1 | namespace IQFeed.CSharpApiClient.Common 2 | { 3 | public class InvalidMessage 4 | { 5 | public T Message { get; } 6 | public string Data { get; } 7 | 8 | public InvalidMessage(T message, string data) 9 | { 10 | Message = message; 11 | Data = data; 12 | } 13 | 14 | public override string ToString() 15 | { 16 | return $"{nameof(Message)}: {Message}, {nameof(Data)}: {Data}"; 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Common/LoggingLevel.cs: -------------------------------------------------------------------------------- 1 | namespace IQFeed.CSharpApiClient.Common 2 | { 3 | public enum LoggingLevel 4 | { 5 | Off = 0, 6 | Admin = 2, 7 | L1Data = 4, 8 | L1Request = 8, 9 | L1System = 16, 10 | L1Error = 32, 11 | L2Data = 64, 12 | L2Request = 128, 13 | L2System = 256, 14 | L2Error = 512, 15 | LookupData = 1024, 16 | LookupRequest = 2048, 17 | LookupError = 4096, 18 | Information = 8192, 19 | Debug = 16384, 20 | Connectivity = 32768 21 | } 22 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Common/MessageContainer.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace IQFeed.CSharpApiClient.Common 4 | { 5 | public class MessageContainer 6 | { 7 | public IEnumerable Messages { get; } 8 | public IEnumerable> InvalidMessages { get; } 9 | public bool End { get; } 10 | public string ErrorMessage { get; } 11 | public string MessageTrace { get; } 12 | 13 | public MessageContainer(IEnumerable messages, bool end) 14 | { 15 | Messages = messages; 16 | InvalidMessages = new List>(); 17 | End = end; 18 | } 19 | 20 | public MessageContainer(IEnumerable messages, IEnumerable> invalidMessages, bool end) 21 | { 22 | Messages = messages; 23 | InvalidMessages = invalidMessages; 24 | End = end; 25 | } 26 | 27 | public MessageContainer(string errorMessage, string messageTrace) 28 | { 29 | Messages = new List(); 30 | InvalidMessages = new List>(); 31 | End = true; 32 | ErrorMessage = errorMessage; 33 | MessageTrace = messageTrace; 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Common/Messages/ProtocolMessage.cs: -------------------------------------------------------------------------------- 1 | namespace IQFeed.CSharpApiClient.Common.Messages 2 | { 3 | public class ProtocolMessage 4 | { 5 | public string Version { get; private set; } 6 | 7 | public ProtocolMessage(string version) 8 | { 9 | Version = version; 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Common/RequestFormatter.cs: -------------------------------------------------------------------------------- 1 | using IQFeed.CSharpApiClient.Common.Interfaces; 2 | 3 | namespace IQFeed.CSharpApiClient.Common 4 | { 5 | public class RequestFormatter : IRequestFormatter 6 | { 7 | public string SetClientName(string name) 8 | { 9 | return $"S,SET CLIENT NAME,{name}{IQFeedDefault.ProtocolTerminatingCharacters}"; 10 | } 11 | 12 | public string SetProtocol(string version) 13 | { 14 | return $"S,SET PROTOCOL,{version}{IQFeedDefault.ProtocolTerminatingCharacters}"; 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Extensions/ByteExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace IQFeed.CSharpApiClient.Extensions 2 | { 3 | public static class ByteExtensions 4 | { 5 | public static int GetLastDelimeterIndex(this byte[] buffer, int offset, int length, char delimeter) 6 | { 7 | for (var i = offset + length - 1; i >= offset; i--) 8 | { 9 | if (buffer[i] == delimeter) 10 | return i; 11 | } 12 | return -1; 13 | } 14 | 15 | public static bool EndsWith(this byte[] self, int count, byte[] pattern) 16 | { 17 | var bufferIdx = count - 1; 18 | 19 | if (self.Length < pattern.Length) 20 | return false; 21 | 22 | if (count < pattern.Length) 23 | return false; 24 | 25 | for (var patternIndex = pattern.Length - 1; patternIndex >= 0; patternIndex--) 26 | { 27 | if (pattern[patternIndex] != self[bufferIdx]) 28 | return false; 29 | 30 | bufferIdx--; 31 | } 32 | 33 | return true; 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Extensions/EnumExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | 4 | namespace IQFeed.CSharpApiClient.Extensions 5 | { 6 | public static class EnumExtensions 7 | { 8 | public static TAttribute GetAttribute(this Enum value) 9 | where TAttribute : Attribute 10 | { 11 | var type = value.GetType(); 12 | var name = Enum.GetName(type, value); 13 | return type.GetField(name) 14 | .GetCustomAttributes(false) 15 | .OfType() 16 | .SingleOrDefault(); 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Extensions/EventExtentions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace IQFeed.CSharpApiClient.Extensions 4 | { 5 | public static class EventExtensions 6 | { 7 | public static void RaiseEvent(this EventHandler @event, object sender, EventArgs e) 8 | { 9 | if (@event != null) 10 | @event(sender, e); 11 | } 12 | 13 | public static void RaiseEvent(this EventHandler @event, object sender, T e) 14 | where T : EventArgs 15 | { 16 | if (@event != null) 17 | @event(sender, e); 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Extensions/NullableExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | 4 | namespace IQFeed.CSharpApiClient.Extensions 5 | { 6 | public static class NullableExtensions 7 | { 8 | public static string ToInvariantString(this DateTime? date, string format) 9 | { 10 | return date.HasValue ? date.Value.ToString(format, CultureInfo.InvariantCulture) : string.Empty; 11 | } 12 | 13 | public static string ToInvariantString(this TimeSpan? time, string format) 14 | { 15 | return time.HasValue ? time.Value.ToString(format, CultureInfo.InvariantCulture) : string.Empty; 16 | } 17 | 18 | public static string ToInvariantString(this double? value) 19 | { 20 | return value.HasValue ? value.Value.ToString(CultureInfo.InvariantCulture) : string.Empty; 21 | } 22 | 23 | public static string ToInvariantString(this int? value) 24 | { 25 | return value.HasValue ? value.Value.ToString(CultureInfo.InvariantCulture) : string.Empty; 26 | } 27 | } 28 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Extensions/TaskExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | 3 | namespace IQFeed.CSharpApiClient.Extensions 4 | { 5 | public static class TaskExtensions 6 | { 7 | /// 8 | /// Safely blocks until the specified task has completed executing 9 | /// 10 | /// The task's result type 11 | /// The task to be awaited 12 | /// The result of the task 13 | public static TResult SynchronouslyAwaitTaskResult(this Task task) 14 | { 15 | return task.ConfigureAwait(false).GetAwaiter().GetResult(); 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/IQFeed.CSharpApiClient.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | net472;netstandard2.1 4 | 5 | 6 | Full 7 | 8 | true 9 | Mathieu Paquette 10 | 11 | DTN IQFeed Socket API (Client) 12 | https://github.com/mathpaquette/IQFeed.CSharpApiClient 13 | https://github.com/mathpaquette/IQFeed.CSharpApiClient 14 | LICENSE 15 | Copyright © 2023 Mathieu Paquette 16 | IQFeed.CSharpApiClient is fastest and the most well-designed C# DTN IQFeed socket API connector available to the open source community! 17 | 1.0.0.0 18 | 1.0.0.0 19 | 1.0.0 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/IQFeedDefault.cs: -------------------------------------------------------------------------------- 1 | namespace IQFeed.CSharpApiClient 2 | { 3 | // ReSharper disable once InconsistentNaming 4 | public class IQFeedDefault 5 | { 6 | public const string Hostname = "localhost"; 7 | 8 | public const string ProtocolVersion = "6.2"; 9 | 10 | public const string ProtocolTerminatingCharacters = "\r\n"; 11 | public const string ProtocolEndOfMessageCharacters = "!ENDMSG!"; 12 | public const string ProtocolNoDataCharacters = "!NO_DATA!"; 13 | public const string ProtocolSyntaxErrorCharacters = "!SYNTAX_ERROR!"; 14 | 15 | public const char ProtocolLineFeedCharacter ='\n'; 16 | public const char ProtocolDelimiterCharacter = ','; 17 | 18 | public const char PrototolErrorCharacter = 'E'; 19 | 20 | public const int Level1Port = 5009; 21 | public const int LookupPort = 9100; 22 | public const int Level2Port = 9200; 23 | public const int AdminPort = 9300; 24 | public const int DerivativePort = 9400; 25 | public const int LoginPort = 60020; 26 | } 27 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Lookup/Chains/ChainsMessageHandler.cs: -------------------------------------------------------------------------------- 1 | using IQFeed.CSharpApiClient.Common; 2 | using IQFeed.CSharpApiClient.Lookup.Chains.Messages; 3 | using IQFeed.CSharpApiClient.Lookup.Common; 4 | 5 | namespace IQFeed.CSharpApiClient.Lookup.Chains 6 | { 7 | public class ChainsMessageHandler : BaseLookupMessageHandler 8 | { 9 | public MessageContainer GetFutureMessages(byte[] message, int count) 10 | { 11 | return ProcessMessages(FutureMessage.Parse, ParseErrorMessage, message, count); 12 | } 13 | 14 | public MessageContainer GetFutureMessagesWithRequestId(byte[] message, int count) 15 | { 16 | return ProcessMessages(FutureMessage.ParseWithRequestId, ParseErrorMessage, message, count); 17 | } 18 | 19 | public MessageContainer GetFutureSpreadMessages(byte[] message, int count) 20 | { 21 | return ProcessMessages(FutureSpreadMessage.Parse, ParseErrorMessage, message, count); 22 | } 23 | 24 | public MessageContainer GetFutureSpreadMessagesWithRequestId(byte[] message, int count) 25 | { 26 | return ProcessMessages(FutureSpreadMessage.ParseWithRequestId, ParseErrorMessage, message, count); 27 | } 28 | 29 | public MessageContainer GetFutureOptionMessages(byte[] message, int count) 30 | { 31 | return ProcessMessages(FutureOptionMessage.Parse, ParseErrorMessage, message, count); 32 | } 33 | 34 | public MessageContainer GetFutureOptionMessagesWithRequestId(byte[] message, int count) 35 | { 36 | return ProcessMessages(FutureOptionMessage.ParseWithRequestId, ParseErrorMessage, message, count); 37 | } 38 | 39 | public MessageContainer GetEquityOptionMessages(byte[] message, int count) 40 | { 41 | return ProcessMessages(EquityOptionMessage.Parse, ParseErrorMessage, message, count); 42 | } 43 | public MessageContainer GetEquityOptionMessagesWithRequestId(byte[] message, int count) 44 | { 45 | return ProcessMessages(EquityOptionMessage.ParseWithRequestId, ParseErrorMessage, message, count); 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Lookup/Chains/ChainsRequestFormatter.cs: -------------------------------------------------------------------------------- 1 | using System.Net.PeerToPeer.Collaboration; 2 | 3 | namespace IQFeed.CSharpApiClient.Lookup.Chains 4 | { 5 | public class ChainsRequestFormatter 6 | { 7 | public string ReqChainFuture(string symbol, string monthCodes, string years, int? nearMonths = null, string requestId = null) 8 | { 9 | var request = $"CFU,{symbol.ToUpper()},{monthCodes.ToUpper()},{years},{nearMonths},{requestId}{IQFeedDefault.ProtocolTerminatingCharacters}"; 10 | return request; 11 | } 12 | 13 | public string ReqChainFutureSpreads(string symbol, string monthCodes, string years, int? nearMonths = null, string requestId = null) 14 | { 15 | var request = $"CFS,{symbol.ToUpper()},{monthCodes},{years},{nearMonths},{requestId}{IQFeedDefault.ProtocolTerminatingCharacters}"; 16 | return request; 17 | } 18 | 19 | public string ReqChainFutureOption(string symbol, OptionSideFilterType optionSideFilter, string monthCodes, string years, int? nearMonths = null, string requestId = null) 20 | { 21 | var request = $"CFO,{symbol.ToUpper()},{optionSideFilter.ToString().ToLower()},{monthCodes},{years},{nearMonths},{requestId}{IQFeedDefault.ProtocolTerminatingCharacters}"; 22 | return request; 23 | } 24 | 25 | // Protocol Update to 6.1 - Added "includeNonStandardOptions" - IQ Default is false 26 | public string ReqChainIndexEquityOption(string symbol, OptionSideFilterType optionSideFilter, string monthCodes, int? nearMonths = null, 27 | OptionFilterType optionFilter = OptionFilterType.None, int? filterValue1 = null, int? filterValue2 = null, string requestId = null, bool includeNonStandardOptions = false) 28 | { 29 | var wireFormatIncludeNonStandardOptions = includeNonStandardOptions ? 1 : 0; 30 | var request = $"CEO,{symbol},{optionSideFilter.ToString().ToLower()},{monthCodes},{nearMonths},{(int)optionFilter}," + 31 | $"{filterValue1},{filterValue2},{requestId},{wireFormatIncludeNonStandardOptions}{IQFeedDefault.ProtocolTerminatingCharacters}"; 32 | return request; 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Lookup/Chains/Futures/FutureMonthCode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace IQFeed.CSharpApiClient.Lookup.Chains.Futures 4 | { 5 | public static class FutureMonthCode 6 | { 7 | public static int Decode(string monthCode) 8 | { 9 | switch (monthCode) 10 | { 11 | case "F": 12 | return 1; 13 | case "G": 14 | return 2; 15 | case "H": 16 | return 3; 17 | case "J": 18 | return 4; 19 | case "K": 20 | return 5; 21 | case "M": 22 | return 6; 23 | case "N": 24 | return 7; 25 | case "Q": 26 | return 8; 27 | case "U": 28 | return 9; 29 | case "V": 30 | return 10; 31 | case "X": 32 | return 11; 33 | case "Z": 34 | return 12; 35 | default: 36 | throw new NotSupportedException("MonthCode not supported"); 37 | } 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Lookup/Chains/Futures/FutureSpread.cs: -------------------------------------------------------------------------------- 1 | using System.Text.RegularExpressions; 2 | 3 | namespace IQFeed.CSharpApiClient.Lookup.Chains.Futures 4 | { 5 | public class FutureSpread 6 | 7 | { 8 | private const string FutureSpreadSymbolPattern = "(.*)(-)(.*)"; 9 | 10 | private const int FutureSymbol1Component = 1; 11 | private const int FutureSymbol2Component = 3; 12 | 13 | public string Symbol { get; } 14 | public Future Spread1 { get; } 15 | public Future Spread2 { get; } 16 | 17 | public FutureSpread(string symbol, Future spread1, Future spread2) 18 | { 19 | Symbol = symbol; 20 | Spread1 = spread1; 21 | Spread2 = spread2; 22 | } 23 | 24 | public static FutureSpread Parse(string futureSpreadSymbol) 25 | { 26 | var m = Regex.Match(futureSpreadSymbol, FutureSpreadSymbolPattern); 27 | var futureSymbol1 = m.Groups[FutureSymbol1Component].Value; 28 | var futureSymbol2 = m.Groups[FutureSymbol2Component].Value; 29 | 30 | return new FutureSpread( 31 | futureSpreadSymbol, 32 | Future.Parse(futureSymbol1), 33 | Future.Parse(futureSymbol2) 34 | ); 35 | } 36 | 37 | public override bool Equals(object obj) 38 | { 39 | return obj is FutureSpread message && 40 | Symbol == message.Symbol && 41 | Spread1.Equals(message.Spread1) && 42 | Spread2.Equals(message.Spread2); 43 | } 44 | 45 | public override int GetHashCode() 46 | { 47 | unchecked 48 | { 49 | var hash = 17; 50 | hash = hash * 29 + Symbol.GetHashCode(); 51 | hash = hash * 29 + Spread1.GetHashCode(); 52 | hash = hash * 29 + Spread2.GetHashCode(); 53 | return hash; 54 | } 55 | } 56 | 57 | public override string ToString() 58 | { 59 | return $"{Spread1} - {Spread2}"; 60 | } 61 | } 62 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Lookup/Chains/IChainsFacadeSync.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using IQFeed.CSharpApiClient.Lookup.Chains.Equities; 3 | using IQFeed.CSharpApiClient.Lookup.Chains.Futures; 4 | 5 | namespace IQFeed.CSharpApiClient.Lookup.Chains 6 | { 7 | public interface IChainsFacadeSync 8 | { 9 | IEnumerable GetChainFuture(string symbol, string monthCodes, string years, int? nearMonths = null, string requestId = null); 10 | 11 | IEnumerable GetChainFutureSpreads(string symbol, string monthCodes, string years, int? nearMonths = null, string requestId = null); 12 | 13 | IEnumerable GetChainFutureOption(string symbol, OptionSideFilterType optionSideFilter, string monthCodes, string years, int? nearMonths = null, string requestId = null); 14 | 15 | IEnumerable GetChainIndexEquityOption(string symbol, OptionSideFilterType optionSideFilter, string monthCodes, int? nearMonths = null, OptionFilterType optionFilter = OptionFilterType.None, int? filterValue1 = null, int? filterValue2 = null, string requestId = null); 16 | } 17 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Lookup/Chains/Messages/ChainsMessage.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using IQFeed.CSharpApiClient.Extensions; 4 | 5 | namespace IQFeed.CSharpApiClient.Lookup.Chains.Messages 6 | { 7 | public class ChainsMessage 8 | { 9 | public const string ChainsDataId = "LC"; 10 | 11 | public ChainsMessage() 12 | { 13 | Chains = new List(); 14 | } 15 | 16 | public ChainsMessage(IList chains) 17 | { 18 | Chains = chains; 19 | } 20 | 21 | public IList Chains { get; private set; } 22 | 23 | public string RequestId { get; set; } 24 | 25 | protected IEnumerable GetSymbols(string message, bool hasRequestId) 26 | { 27 | // we now have either: LC,ListOfSymbols OR requestId,LC,ListOfSymbols 28 | var values = message.SplitFeedMessage(); 29 | RequestId = hasRequestId ? values[0] : null; 30 | var symbolBase = hasRequestId ? 2 : 1; 31 | var length = values.Length - symbolBase; 32 | var symbols = new Memory(values, symbolBase, length).ToArray(); 33 | 34 | foreach (var symbol in symbols) 35 | { 36 | // skip characters 37 | if (symbol == ":" || symbol == string.Empty || symbol == " ") 38 | continue; 39 | 40 | yield return symbol; 41 | } 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Lookup/Chains/Messages/EquityOptionMessage.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using IQFeed.CSharpApiClient.Lookup.Chains.Equities; 3 | 4 | namespace IQFeed.CSharpApiClient.Lookup.Chains.Messages 5 | { 6 | public class EquityOptionMessage : ChainsMessage 7 | { 8 | public EquityOptionMessage(string message, bool hasRequestId) 9 | { 10 | ParseInner(message, hasRequestId); 11 | } 12 | 13 | public static EquityOptionMessage Parse(string message) 14 | { 15 | return new EquityOptionMessage(message, false); 16 | } 17 | 18 | public static EquityOptionMessage ParseWithRequestId(string message) 19 | { 20 | return new EquityOptionMessage(message, true); 21 | } 22 | 23 | private void ParseInner(string message, bool hasRequestid) 24 | { 25 | foreach (var symbol in GetSymbols(message, hasRequestid)) 26 | { 27 | Chains.Add(EquityOption.Parse(symbol)); 28 | } 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Lookup/Chains/Messages/FutureMessage.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using IQFeed.CSharpApiClient.Lookup.Chains.Futures; 3 | 4 | namespace IQFeed.CSharpApiClient.Lookup.Chains.Messages 5 | { 6 | public class FutureMessage : ChainsMessage 7 | { 8 | public FutureMessage(string message, bool hasRequestId) 9 | { 10 | ParseInner(message, hasRequestId); 11 | } 12 | 13 | public static FutureMessage Parse(string message) 14 | { 15 | return new FutureMessage(message, false); 16 | } 17 | 18 | public static FutureMessage ParseWithRequestId(string message) 19 | { 20 | return new FutureMessage(message, true); 21 | } 22 | 23 | public void ParseInner(string message, bool hasRequestId) 24 | { 25 | foreach (var symbol in GetSymbols(message, hasRequestId)) 26 | { 27 | Chains.Add(Future.Parse(symbol)); 28 | } 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Lookup/Chains/Messages/FutureOptionMessage.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using IQFeed.CSharpApiClient.Lookup.Chains.Futures; 3 | 4 | namespace IQFeed.CSharpApiClient.Lookup.Chains.Messages 5 | { 6 | public class FutureOptionMessage : ChainsMessage 7 | { 8 | public FutureOptionMessage(string message, bool hasRequestId) 9 | { 10 | ParseInner(message, hasRequestId); 11 | } 12 | 13 | public static FutureOptionMessage Parse(string message) 14 | { 15 | return new FutureOptionMessage(message, false); 16 | } 17 | 18 | public static FutureOptionMessage ParseWithRequestId(string message) 19 | { 20 | return new FutureOptionMessage(message, true); 21 | } 22 | 23 | private void ParseInner(string message, bool hasRequestId) 24 | { 25 | foreach (var symbol in GetSymbols(message, hasRequestId)) 26 | { 27 | Chains.Add(FutureOption.Parse(symbol)); 28 | } 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Lookup/Chains/Messages/FutureSpreadMessage.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using IQFeed.CSharpApiClient.Lookup.Chains.Futures; 3 | 4 | namespace IQFeed.CSharpApiClient.Lookup.Chains.Messages 5 | { 6 | public class FutureSpreadMessage : ChainsMessage 7 | { 8 | public FutureSpreadMessage(string message, bool hasRequestId) 9 | { 10 | ParseInner(message, hasRequestId); 11 | } 12 | 13 | public static FutureSpreadMessage Parse(string message) 14 | { 15 | return new FutureSpreadMessage(message, false); 16 | } 17 | 18 | public static FutureSpreadMessage ParseWithRequestId(string message) 19 | { 20 | return new FutureSpreadMessage(message, true); 21 | } 22 | 23 | public void ParseInner(string message, bool hasRequestId) 24 | { 25 | foreach (var symbol in GetSymbols(message, hasRequestId)) 26 | { 27 | Chains.Add(FutureSpread.Parse(symbol)); 28 | } 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Lookup/Chains/OptionFilterType.cs: -------------------------------------------------------------------------------- 1 | namespace IQFeed.CSharpApiClient.Lookup.Chains 2 | { 3 | public enum OptionFilterType 4 | { 5 | None = 0, 6 | StrikeRange = 1, 7 | NumberOfInOutTheMoneyContracts = 2 8 | } 9 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Lookup/Chains/OptionSide.cs: -------------------------------------------------------------------------------- 1 | namespace IQFeed.CSharpApiClient.Lookup.Chains 2 | { 3 | public enum OptionSide 4 | { 5 | Call, 6 | Put 7 | } 8 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Lookup/Chains/OptionSideFilterType.cs: -------------------------------------------------------------------------------- 1 | namespace IQFeed.CSharpApiClient.Lookup.Chains 2 | { 3 | public enum OptionSideFilterType 4 | { 5 | /// 6 | /// Call options only 7 | /// 8 | C, 9 | /// 10 | /// Put options only 11 | /// 12 | P, 13 | /// 14 | /// Call and Put options 15 | /// 16 | CP 17 | } 18 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Lookup/Common/LookupMessageFileParser.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.IO.Compression; 5 | 6 | namespace IQFeed.CSharpApiClient.Lookup.Common 7 | { 8 | public class LookupMessageFileParser 9 | { 10 | public static IEnumerable ParseFromFile(Func parseFunc, string path) 11 | { 12 | return ParseFromFile(parseFunc, new StreamReader(path)); 13 | } 14 | 15 | public static IEnumerable ParseFromFile(Func parseFunc, Stream stream) 16 | { 17 | return ParseFromFile(parseFunc, new StreamReader(stream)); 18 | } 19 | 20 | public static IEnumerable ParseFromFile(Func parseFunc, StreamReader file) 21 | { 22 | using (file) 23 | { 24 | string line; 25 | while ((line = file.ReadLine()) != null) 26 | { 27 | if (string.IsNullOrEmpty(line) || line[0] == '!') 28 | continue; 29 | 30 | yield return parseFunc(line); 31 | } 32 | } 33 | } 34 | 35 | public static IEnumerable ParseFromArchive(Func parseFunc, string zipPath) 36 | { 37 | using (ZipArchive archive = ZipFile.OpenRead(zipPath)) 38 | { 39 | foreach (var entry in archive.Entries) 40 | { 41 | using (var stream = entry.Open()) 42 | { 43 | foreach (var message in ParseFromFile(parseFunc, stream)) 44 | { 45 | yield return message; 46 | } 47 | } 48 | } 49 | } 50 | } 51 | } 52 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Lookup/Historical/Enums/DataDirection.cs: -------------------------------------------------------------------------------- 1 | namespace IQFeed.CSharpApiClient.Lookup.Historical.Enums 2 | { 3 | public enum DataDirection 4 | { 5 | /// 6 | /// newest to oldest = 0 (default) 7 | /// 8 | Newest = 0, 9 | /// 10 | /// oldest to newest = 1 11 | /// 12 | Oldest = 1 13 | } 14 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Lookup/Historical/Enums/LabelAtBeginning.cs: -------------------------------------------------------------------------------- 1 | namespace IQFeed.CSharpApiClient.Lookup.Historical.Enums 2 | { 3 | public enum LabelAtBeginning 4 | { 5 | End = 0, 6 | Beginning = 1 // default 7 | } 8 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Lookup/Historical/HistoricalIntervalType.cs: -------------------------------------------------------------------------------- 1 | namespace IQFeed.CSharpApiClient.Lookup.Historical 2 | { 3 | public enum HistoricalIntervalType 4 | { 5 | /// 6 | /// time intervals in seconds 7 | /// 8 | S, 9 | 10 | /// 11 | /// volume intervals 12 | /// 13 | V, 14 | 15 | /// 16 | /// tick intervals 17 | /// 18 | T 19 | } 20 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Lookup/Historical/HistoricalMessageHandler.cs: -------------------------------------------------------------------------------- 1 | using IQFeed.CSharpApiClient.Common; 2 | using IQFeed.CSharpApiClient.Lookup.Common; 3 | using IQFeed.CSharpApiClient.Lookup.Historical.Messages; 4 | 5 | namespace IQFeed.CSharpApiClient.Lookup.Historical 6 | { 7 | public class HistoricalMessageHandler : BaseLookupMessageHandler, IHistoricalMessageHandler 8 | { 9 | public const string HistoricalDataId = "LH"; 10 | 11 | public static readonly TryParseDelegate TryParseTick = TickMessage.TryParse; 12 | public static readonly TryParseDelegate TryParseInterval = IntervalMessage.TryParse; 13 | public static readonly TryParseDelegate TryParseDaily = DailyWeeklyMonthlyMessage.TryParse; 14 | 15 | // tick 16 | public MessageContainer GetTickMessages(byte[] message, int count) 17 | { 18 | return ProcessMessages(TryParseTick, ParseErrorMessage, message, count); 19 | } 20 | 21 | public MessageContainer GetTickMessagesWithRequestId(byte[] message, int count) 22 | { 23 | return ProcessMessages(TickMessage.ParseWithRequestId, ParseErrorMessageWithRequestId, message, count); 24 | } 25 | 26 | // interval 27 | public MessageContainer GetIntervalMessages(byte[] message, int count) 28 | { 29 | return ProcessMessages(TryParseInterval, ParseErrorMessage, message, count); 30 | } 31 | 32 | public MessageContainer GetIntervalMessagesWithRequestId(byte[] message, int count) 33 | { 34 | return ProcessMessages(IntervalMessage.ParseWithRequestId, ParseErrorMessageWithRequestId, message, count); 35 | } 36 | 37 | // daily 38 | public MessageContainer GetDailyWeeklyMonthlyMessages(byte[] message, int count) 39 | { 40 | return ProcessMessages(TryParseDaily, ParseErrorMessage, message, count); 41 | } 42 | 43 | public MessageContainer GetDailyWeeklyMonthlyMessagesWithRequestId(byte[] message, int count) 44 | { 45 | return ProcessMessages(DailyWeeklyMonthlyMessage.ParseWithRequestId, ParseErrorMessageWithRequestId, message, count); 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Lookup/Historical/IHistoricalMessageHandler.cs: -------------------------------------------------------------------------------- 1 | using IQFeed.CSharpApiClient.Common; 2 | using IQFeed.CSharpApiClient.Lookup.Historical.Messages; 3 | 4 | namespace IQFeed.CSharpApiClient.Lookup.Historical 5 | { 6 | public interface IHistoricalMessageHandler 7 | { 8 | MessageContainer GetTickMessages(byte[] message, int count); 9 | MessageContainer GetTickMessagesWithRequestId(byte[] message, int count); 10 | MessageContainer GetIntervalMessages(byte[] message, int count); 11 | MessageContainer GetIntervalMessagesWithRequestId(byte[] message, int count); 12 | MessageContainer GetDailyWeeklyMonthlyMessages(byte[] message, int count); 13 | MessageContainer GetDailyWeeklyMonthlyMessagesWithRequestId(byte[] message, int count); 14 | } 15 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Lookup/Historical/Messages/IDailyWeeklyMonthlyMessage.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace IQFeed.CSharpApiClient.Lookup.Historical.Messages 4 | { 5 | public interface IDailyWeeklyMonthlyMessage : IHistoricalMessage 6 | { 7 | double Close { get; } 8 | double High { get; } 9 | double Low { get; } 10 | double Open { get; } 11 | int OpenInterest { get; } 12 | long PeriodVolume { get; } 13 | } 14 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Lookup/Historical/Messages/IHistoricalMessage.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace IQFeed.CSharpApiClient.Lookup.Historical.Messages 4 | { 5 | public interface IHistoricalMessage 6 | { 7 | DateTime Timestamp { get; } 8 | string RequestId { get; } 9 | } 10 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Lookup/Historical/Messages/IIntervalMessage.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace IQFeed.CSharpApiClient.Lookup.Historical.Messages 4 | { 5 | public interface IIntervalMessage : IHistoricalMessage 6 | { 7 | double Close { get; } 8 | double High { get; } 9 | double Low { get; } 10 | int NumberOfTrades { get; } 11 | double Open { get; } 12 | long PeriodVolume { get; } 13 | long TotalVolume { get; } 14 | } 15 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Lookup/Historical/Messages/ITickMessage.cs: -------------------------------------------------------------------------------- 1 | namespace IQFeed.CSharpApiClient.Lookup.Historical.Messages 2 | { 3 | public interface ITickMessage : IHistoricalMessage 4 | { 5 | double Ask { get; } 6 | char BasisForLast { get; } 7 | double Bid { get; } 8 | double Last { get; } 9 | int LastSize { get; } 10 | long TickId { get; } 11 | int TotalVolume { get; } 12 | string TradeConditions { get; } 13 | int TradeMarketCenter { get; } 14 | } 15 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Lookup/LookupClient.cs: -------------------------------------------------------------------------------- 1 | using IQFeed.CSharpApiClient.Common.Interfaces; 2 | using IQFeed.CSharpApiClient.Lookup.Chains; 3 | using IQFeed.CSharpApiClient.Lookup.Historical.Facades; 4 | using IQFeed.CSharpApiClient.Lookup.MarketSummary.Facades; 5 | using IQFeed.CSharpApiClient.Lookup.News; 6 | using IQFeed.CSharpApiClient.Lookup.Symbol; 7 | 8 | namespace IQFeed.CSharpApiClient.Lookup 9 | { 10 | public class LookupClient: IClient 11 | { 12 | private readonly LookupDispatcher _lookupDispatcher; 13 | 14 | public LookupClient( 15 | LookupDispatcher lookupDispatcher, 16 | HistoricalFacade historical, 17 | NewsFacade news, 18 | SymbolFacade symbol, 19 | ChainsFacade chains, 20 | MarketSummaryFacade marketSummary) 21 | { 22 | _lookupDispatcher = lookupDispatcher; 23 | Historical = historical; 24 | News = news; 25 | Symbol = symbol; 26 | Chains = chains; 27 | MarketSummary = marketSummary; 28 | } 29 | 30 | public HistoricalFacade Historical { get; } 31 | public NewsFacade News { get; } 32 | public SymbolFacade Symbol { get; } 33 | public ChainsFacade Chains { get; } 34 | public MarketSummaryFacade MarketSummary { get; } 35 | 36 | public void Connect() 37 | { 38 | _lookupDispatcher.ConnectAll(); 39 | } 40 | 41 | public void Disconnect() 42 | { 43 | _lookupDispatcher.DisconnectAll(); 44 | } 45 | } 46 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Lookup/LookupDefault.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace IQFeed.CSharpApiClient.Lookup 4 | { 5 | public class LookupDefault 6 | { 7 | /// 8 | /// Default timeout before canceling tasks (5 minutes) 9 | /// This can be changed using LookupClientFactory parameters 10 | /// 11 | public static TimeSpan Timeout = TimeSpan.FromMinutes(5); 12 | 13 | /// 14 | /// Default buffer size for Lookup SocketClient 15 | /// Note: SocketClients connected to the lookup port, we need to assign them larger buffer 16 | /// than usual because since we're waiting for the \r\n pattern to notify upper layer that we 17 | /// completed a new message, some particular responses such on GetChainIndexEquityOptionAsync 18 | /// IQFeed will return on the same line all matching symbols causing overflow 19 | /// 20 | public const int BufferSize = 32 * 1024; 21 | 22 | /// 23 | /// Default requests per second allowed by IQFeed 24 | /// IQFeed can tolerate very short burst around 75 requests/second. 25 | /// and corresponding tests for more info. 26 | /// 27 | public const int RequestsPerSecond = 50; 28 | } 29 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Lookup/MarketSummary/Facades/IMarketSummaryFacade.cs: -------------------------------------------------------------------------------- 1 | using IQFeed.CSharpApiClient.Lookup.Symbol; 2 | using System; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace IQFeed.CSharpApiClient.Lookup.MarketSummary.Facades 8 | { 9 | public interface IMarketSummaryFacade 10 | { 11 | Task GetEndOfDaySummaryAsync(SecurityType securityType, int listedMarketGroupId, DateTime date, string requestId = null); 12 | Task GetEndOfDayFundamentalSummaryAsync(SecurityType securityType, int listedMarketGroupId, DateTime date, string requestId = null); 13 | Task Get5MinuteSnapshotSummaryAsync(SecurityType securityType, int listedMarketGroupId, string requestId = null); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Lookup/MarketSummary/Facades/MarketSummaryFileFacade.cs: -------------------------------------------------------------------------------- 1 | using IQFeed.CSharpApiClient.Lookup.Common; 2 | using IQFeed.CSharpApiClient.Lookup.Symbol; 3 | using System; 4 | using System.Threading.Tasks; 5 | 6 | namespace IQFeed.CSharpApiClient.Lookup.MarketSummary.Facades 7 | { 8 | public class MarketSummaryFileFacade : IMarketSummaryFacade 9 | { 10 | private readonly MarketSummaryRequestFormatter _marketSummaryRequestFormatter; 11 | private readonly LookupMessageFileHandler _lookupMessageFileHandler; 12 | 13 | public MarketSummaryFileFacade( 14 | MarketSummaryRequestFormatter marketSummaryRequestFormatter, 15 | LookupMessageFileHandler lookupMessageFileHandler) 16 | { 17 | _lookupMessageFileHandler = lookupMessageFileHandler; 18 | _marketSummaryRequestFormatter = marketSummaryRequestFormatter; 19 | } 20 | 21 | public Task GetEndOfDaySummaryAsync(SecurityType securityType, int listedMarketGroupId, DateTime date, string requestId = null) 22 | { 23 | var request = _marketSummaryRequestFormatter.ReqEndOfDaySummary(securityType, listedMarketGroupId, date, requestId); 24 | return _lookupMessageFileHandler.GetFilenameAsync(request); 25 | } 26 | 27 | public Task GetEndOfDayFundamentalSummaryAsync(SecurityType securityType, int listedMarketGroupId, DateTime date, string requestId = null) 28 | { 29 | var request = _marketSummaryRequestFormatter.ReqFundamentalSummary(securityType, listedMarketGroupId, date, requestId); 30 | return _lookupMessageFileHandler.GetFilenameAsync(request); 31 | } 32 | 33 | public Task Get5MinuteSnapshotSummaryAsync(SecurityType securityType, int listedMarketGroupId, string requestId = null) 34 | { 35 | var request = _marketSummaryRequestFormatter.Req5MinuteSnapshotSummary(securityType, listedMarketGroupId, requestId); 36 | return _lookupMessageFileHandler.GetFilenameAsync(request); 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Lookup/MarketSummary/MarketSummaryDynamicFieldset.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace IQFeed.CSharpApiClient.Lookup.MarketSummary 8 | { 9 | public enum MarketSummaryDynamicFieldset 10 | { 11 | RequestId, 12 | LM, // Protocol 6.2 DataId Constant 'LM' 13 | Symbol, 14 | Exchange, // ExchangeId 15 | Type, // SecurityType 16 | Last, 17 | TradeSize, 18 | TradedMarket, 19 | TradeDate, 20 | TradeTime, 21 | Open, 22 | High, 23 | Low, 24 | Close, 25 | Bid, 26 | BidMarket, 27 | BidSize, 28 | Ask, 29 | AskMarket, 30 | AskSize, 31 | Volume, 32 | PDayVolume, 33 | UpVolume, 34 | DownVolume, 35 | NeutralVolume, 36 | TradeCount, 37 | UpTrades, 38 | DownTrades, 39 | NeutralTrades, 40 | VWAP, 41 | MutualDiv, 42 | SevenDayYield, 43 | OpenInterest, 44 | Settlement, 45 | SettlementDate, 46 | ExpirationDate, 47 | Strike 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Lookup/MarketSummary/MarketSummaryFieldsetDescriptor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace IQFeed.CSharpApiClient.Lookup.MarketSummary 8 | { 9 | /// 10 | /// Until Market Summaries are out of beta and fixed, the field names/orders/count could change, 11 | /// so we need to handle them dynamically, which is slightly slower 12 | /// 13 | public class MarketSummaryFieldsetDescriptor 14 | { 15 | 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Lookup/MarketSummary/MarketSummaryRequestFormatter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using IQFeed.CSharpApiClient.Common; 3 | using IQFeed.CSharpApiClient.Lookup.Symbol; 4 | 5 | namespace IQFeed.CSharpApiClient.Lookup.MarketSummary 6 | { 7 | public class MarketSummaryRequestFormatter : RequestFormatter 8 | { 9 | public const string SourceDataDateFormat = "yyyyMMdd"; 10 | 11 | public string ReqEndOfDaySummary(SecurityType securityType, int groupId, DateTime date, string requestId = null) 12 | { 13 | // EDS,[SecurityType],[GroupID],[Date],[RequestID] 14 | var wireDate = date.ToString(SourceDataDateFormat); 15 | var request = $"EDS,{((int)securityType)},{groupId},{wireDate},{requestId}{IQFeedDefault.ProtocolTerminatingCharacters}"; 16 | return request; 17 | } 18 | 19 | public string ReqFundamentalSummary(SecurityType securityType, int groupId, DateTime date, string requestId = null) 20 | { 21 | // FDS,[SecurityType],[GroupID],[Date],[RequestID] 22 | var wireDate = date.ToString(SourceDataDateFormat); 23 | var request = $"FDS,{((int)securityType)},{groupId},{wireDate},{requestId}{IQFeedDefault.ProtocolTerminatingCharacters}"; 24 | return request; 25 | } 26 | 27 | public string Req5MinuteSnapshotSummary(SecurityType securityType, int groupId, string requestId = null) 28 | { 29 | // 5MS,[SecurityType],[GroupID],[Date],[RequestID] 30 | var request = $"5MS,{((int)securityType)},{groupId},{requestId}{IQFeedDefault.ProtocolTerminatingCharacters}"; 31 | return request; 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Lookup/News/Enums/FormatType.cs: -------------------------------------------------------------------------------- 1 | namespace IQFeed.CSharpApiClient.Lookup.News.Enums 2 | { 3 | public enum FormatType 4 | { 5 | XML, 6 | Text 7 | } 8 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Lookup/News/Enums/NewsFormatType.cs: -------------------------------------------------------------------------------- 1 | namespace IQFeed.CSharpApiClient.Lookup.News.Enums 2 | { 3 | public enum NewsFormatType 4 | { 5 | XML, 6 | Text, 7 | Email 8 | } 9 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Lookup/News/INewsFacade.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Threading.Tasks; 4 | using IQFeed.CSharpApiClient.Lookup.News.Enums; 5 | using IQFeed.CSharpApiClient.Lookup.News.Messages; 6 | 7 | namespace IQFeed.CSharpApiClient.Lookup.News 8 | { 9 | public interface INewsFacade : INewsFacadeSync 10 | { 11 | Task> GetNewsConfigurationAsync(FormatType formatType, string requestId = null); 12 | 13 | Task> GetNewsHeadlinesAsync(string[] sources = null, string[] symbols = null, FormatType? formatType = null, int? limit = null, DateTime? date = null, string requestId = null); 14 | 15 | Task> GetNewsStoryAsync(string id, NewsFormatType? formatType = null, string deliverTo = null, string requestId = null); 16 | 17 | Task> GetNewsStoryCountAsync(string[] symbols, FormatType? formatType = null, string[] sources = null, DateTime? fromDate = null, DateTime? toDate = null, string requestId = null); 18 | } 19 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Lookup/News/INewsFacadeSync.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using IQFeed.CSharpApiClient.Lookup.News.Enums; 4 | using IQFeed.CSharpApiClient.Lookup.News.Messages; 5 | 6 | namespace IQFeed.CSharpApiClient.Lookup.News 7 | { 8 | public interface INewsFacadeSync 9 | { 10 | IEnumerable GetNewsConfiguration(FormatType formatType, string requestId = null); 11 | 12 | IEnumerable GetNewsHeadlines(string[] sources = null, string[] symbols = null, FormatType? formatType = null, int? limit = null, DateTime? date = null, string requestId = null); 13 | 14 | IEnumerable GetNewsStory(string id, NewsFormatType? formatType = null, string deliverTo = null, string requestId = null); 15 | 16 | IEnumerable GetNewsStoryCount(string[] symbols, FormatType? formatType = null, string[] sources = null, DateTime? fromDate = null, DateTime? toDate = null, string requestId = null); 17 | } 18 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Lookup/News/NewsMessageHandler.cs: -------------------------------------------------------------------------------- 1 | using IQFeed.CSharpApiClient.Common; 2 | using IQFeed.CSharpApiClient.Lookup.Common; 3 | using IQFeed.CSharpApiClient.Lookup.News.Messages; 4 | 5 | namespace IQFeed.CSharpApiClient.Lookup.News 6 | { 7 | public class NewsMessageHandler : BaseLookupMessageHandler 8 | { 9 | public MessageContainer GetString(byte[] message, int count) 10 | { 11 | return ProcessMessages(s => s, ParseErrorMessage, message, count); 12 | } 13 | 14 | public MessageContainer GetStringWithRequestId(byte[] message, int count) 15 | { 16 | return ProcessMessages(s => s, ParseErrorMessageWithRequestId, message, count); 17 | } 18 | 19 | public MessageContainer GetNewsHeadlines(byte[] message, int count) 20 | { 21 | return ProcessMessages(NewsHeadlinesMessage.Parse, ParseErrorMessage, message, count); 22 | } 23 | 24 | public MessageContainer GetNewsHeadlinesWithRequestId(byte[] message, int count) 25 | { 26 | return ProcessMessages(NewsHeadlinesMessage.ParseWithRequestId, ParseErrorMessageWithRequestId, message, count); 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Lookup/Symbol/Downloader/ILocalCacheStrategy.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace IQFeed.CSharpApiClient.Lookup.Symbol.Downloader 4 | { 5 | public interface ILocalCacheStrategy 6 | { 7 | bool HasExpired(string path, TimeSpan expiration); 8 | } 9 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Lookup/Symbol/Downloader/LocalCacheStrategy.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | 4 | namespace IQFeed.CSharpApiClient.Lookup.Symbol.Downloader 5 | { 6 | public class LocalCacheStrategy : ILocalCacheStrategy 7 | { 8 | public bool HasExpired(string path, TimeSpan expiration) 9 | { 10 | if (!File.Exists(path)) 11 | return true; 12 | 13 | return DateTime.Now > File.GetCreationTime(path) + expiration; 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Lookup/Symbol/Enums/FieldToSearch.cs: -------------------------------------------------------------------------------- 1 | namespace IQFeed.CSharpApiClient.Lookup.Symbol.Enums 2 | { 3 | public enum FieldToSearch 4 | { 5 | /// 6 | /// Search symbols 7 | /// 8 | Symbols = 's', 9 | 10 | /// 11 | /// Search descriptions 12 | /// 13 | Descriptions = 'd' 14 | } 15 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Lookup/Symbol/Enums/FilterType.cs: -------------------------------------------------------------------------------- 1 | namespace IQFeed.CSharpApiClient.Lookup.Symbol.Enums 2 | { 3 | public enum FilterType 4 | { 5 | /// 6 | /// Search within specific Listed Markets 7 | /// 8 | ListedMarkets = 'e', 9 | 10 | /// 11 | /// Search within specific Security Types 12 | /// 13 | SecurityTypes = 't' 14 | } 15 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Lookup/Symbol/ExpiredOptions/ExpiredOption.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using IQFeed.CSharpApiClient.Lookup.Chains.Equities; 4 | 5 | namespace IQFeed.CSharpApiClient.Lookup.Symbol.ExpiredOptions 6 | { 7 | public class ExpiredOption 8 | { 9 | public const string LastUpdateDateTimeFormat = "yyyyMMdd"; 10 | 11 | public EquityOption EquityOption { get; } 12 | public int SecurityType { get; } 13 | public string Description { get; } 14 | public int Exchange { get; } 15 | public DateTime LastUpdate { get; } 16 | 17 | public static ExpiredOption Parse(string line) 18 | { 19 | // Symbol,SecurityType,Description,ExpirationDate,Exchange,LastUpdate 20 | // CIEN1808R23.5,2,CIEN JUN 2018 P 23.50,20180608,14,20180612 21 | var values = line.Split(','); 22 | 23 | var equityOption = EquityOption.Parse(values[0]); 24 | int.TryParse(values[1], out var securityType); 25 | var title = values[2].Trim(); 26 | // skip values[3] ExpirationDate already part of EquityOption 27 | int.TryParse(values[4], out var exchange); 28 | DateTime.TryParseExact(values[5], LastUpdateDateTimeFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out var lastUpdate); 29 | 30 | return new ExpiredOption(equityOption, securityType, title, exchange, lastUpdate); 31 | } 32 | 33 | public ExpiredOption(EquityOption equityOption, int securityType, string description, int exchange, DateTime lastUpdate) 34 | { 35 | EquityOption = equityOption; 36 | SecurityType = securityType; 37 | Description = description; 38 | Exchange = exchange; 39 | LastUpdate = lastUpdate; 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Lookup/Symbol/ExpiredOptions/ExpiredOptionReader.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.IO; 3 | 4 | namespace IQFeed.CSharpApiClient.Lookup.Symbol.ExpiredOptions 5 | { 6 | public class ExpiredOptionReader 7 | { 8 | public IEnumerable GetExpiredOptions(string filename) 9 | { 10 | var lineCount = 0; 11 | using (var file = new StreamReader(filename)) 12 | { 13 | string line; 14 | while ((line = file.ReadLine()) != null) 15 | { 16 | lineCount++; 17 | 18 | // ignore the header 19 | if (lineCount == 1) 20 | continue; 21 | 22 | yield return ExpiredOption.Parse(line); 23 | } 24 | } 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Lookup/Symbol/ISymbolFacadeDownload.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using IQFeed.CSharpApiClient.Lookup.Symbol.ExpiredOptions; 4 | using IQFeed.CSharpApiClient.Lookup.Symbol.MarketSymbols; 5 | 6 | namespace IQFeed.CSharpApiClient.Lookup.Symbol 7 | { 8 | public interface ISymbolFacadeDownload 9 | { 10 | IEnumerable GetAllMarketSymbols(string url = SymbolDefault.MarketSymbolsArchiveUrl, bool useCache = true, TimeSpan? expiration = null); 11 | IEnumerable GetAllMarketSymbols(string downloadFolder, string url = SymbolDefault.MarketSymbolsArchiveUrl, bool useCache = true, TimeSpan? expiration = null); 12 | 13 | IEnumerable GetAllExpiredOptions(string url = SymbolDefault.ExpiredOptionsArchiveUrl, bool useCache = true, TimeSpan? expiration = null); 14 | IEnumerable GetAllExpiredOptions(string downloadFolder, string url = SymbolDefault.ExpiredOptionsArchiveUrl, bool useCache = true, TimeSpan? expiration = null); 15 | } 16 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Lookup/Symbol/ISymbolFacadeSync.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using IQFeed.CSharpApiClient.Lookup.Symbol.Enums; 3 | using IQFeed.CSharpApiClient.Lookup.Symbol.Messages; 4 | 5 | namespace IQFeed.CSharpApiClient.Lookup.Symbol 6 | { 7 | public interface ISymbolFacadeSync 8 | { 9 | IEnumerable GetSymbolsByFilter(FieldToSearch fieldToSearch, string searchString, FilterType? filterType, IEnumerable filterValues, string requestId = null); 10 | IEnumerable GetSymbolsBySicCode(string sicCodePrefix, string requestId = null); 11 | IEnumerable GetSymbolsByNaicsCode(string naicsCodePrefix, string requestId = null); 12 | IEnumerable GetListedMarkets(string requestId = null); 13 | IEnumerable GetSecurityTypes(string requestId = null); 14 | IEnumerable GetTradeConditions(string requestId = null); 15 | IEnumerable GetSicCodes(string requestId = null); 16 | IEnumerable GetNaicsCodes(string requestId = null); 17 | } 18 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Lookup/Symbol/MarketSymbols/MarketSymbol.cs: -------------------------------------------------------------------------------- 1 | namespace IQFeed.CSharpApiClient.Lookup.Symbol.MarketSymbols 2 | { 3 | public class MarketSymbol 4 | { 5 | public string Symbol { get; private set; } 6 | public string Description { get; private set; } 7 | public string Exchange { get; private set; } 8 | public string ListedMarket { get; private set; } 9 | public string SecurityType { get; private set; } 10 | public string Sic { get; private set; } 11 | public string Frontmonth { get; private set; } 12 | public string Naics { get; private set; } 13 | 14 | public MarketSymbol(string symbol, string description, string exchange, string listedMarket, string securityType, string sic, string frontmonth, string naics) 15 | { 16 | Symbol = symbol; 17 | Description = description; 18 | Exchange = exchange; 19 | ListedMarket = listedMarket; 20 | SecurityType = securityType; 21 | Sic = sic; 22 | Frontmonth = frontmonth; 23 | Naics = naics; 24 | } 25 | 26 | public override string ToString() 27 | { 28 | return $"{nameof(Symbol)}: {Symbol}, {nameof(Description)}: {Description}, {nameof(Exchange)}: {Exchange}, {nameof(ListedMarket)}: {ListedMarket}, {nameof(SecurityType)}: {SecurityType}, {nameof(Sic)}: {Sic}, {nameof(Frontmonth)}: {Frontmonth}, {nameof(Naics)}: {Naics}"; 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Lookup/Symbol/MarketSymbols/MarketSymbolExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | 4 | namespace IQFeed.CSharpApiClient.Lookup.Symbol.MarketSymbols 5 | { 6 | public static class MarketSymbolExtensions 7 | { 8 | public static IEnumerable AreEquitiesOrIndexes(this IEnumerable marketSymbols) 9 | { 10 | return marketSymbols.Where(x => x.SecurityType == MarketSymbolSecurityType.EQUITY || x.SecurityType == MarketSymbolSecurityType.INDEX); 11 | } 12 | } 13 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Lookup/Symbol/MarketSymbols/MarketSymbolReader.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.IO; 3 | 4 | namespace IQFeed.CSharpApiClient.Lookup.Symbol.MarketSymbols 5 | { 6 | public class MarketSymbolReader 7 | { 8 | public IEnumerable GetMarketSymbols(string filename) 9 | { 10 | var lineCount = 0; 11 | 12 | using (var file = new StreamReader(filename)) 13 | { 14 | string line; 15 | string[] values; 16 | 17 | while ((line = file.ReadLine()) != null && (values = line.Split('\t')).Length == 8) 18 | { 19 | lineCount++; 20 | 21 | if (lineCount == 1) // ignore the header 22 | continue; 23 | 24 | yield return new MarketSymbol(values[0], values[1], values[2], values[3], values[4], values[5], values[6], values[7]); 25 | } 26 | } 27 | } 28 | } 29 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Lookup/Symbol/MarketSymbols/MarketSymbolSecurityType.cs: -------------------------------------------------------------------------------- 1 | namespace IQFeed.CSharpApiClient.Lookup.Symbol.MarketSymbols 2 | { 3 | public class MarketSymbolSecurityType 4 | { 5 | public const string STRIP = "STRIP"; 6 | public const string FUTURE = "FUTURE"; 7 | public const string COMBINED_FUTURE = "COMBINED_FUTURE"; 8 | public const string INDEX = "INDEX"; 9 | public const string COMBINED_FOPTION = "COMBINED_FOPTION"; 10 | public const string FOPTION = "FOPTION"; 11 | public const string STRATSPREAD = "STRATSPREAD"; 12 | public const string SPREAD = "SPREAD"; 13 | public const string ICSPREAD = "ICSPREAD"; 14 | public const string EQUITY = "EQUITY"; 15 | public const string IEOPTION = "IEOPTION"; 16 | public const string BONDS = "BONDS"; 17 | public const string SPOT = "SPOT"; 18 | public const string MUTUAL = "MUTUAL"; 19 | public const string MONEY = "MONEY"; 20 | public const string FOREX = "FOREX"; 21 | public const string MKTSTATS = "MKTSTATS"; 22 | public const string PRECMTL = "PRECMTL"; 23 | public const string MKTRPT = "MKTRPT"; 24 | public const string TREASURIES = "TREASURIES"; 25 | public const string FORWARD = "FORWARD"; 26 | public const string SWAPS = "SWAPS"; 27 | } 28 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Lookup/Symbol/SecurityType.cs: -------------------------------------------------------------------------------- 1 | namespace IQFeed.CSharpApiClient.Lookup.Symbol 2 | { 3 | public enum SecurityType 4 | { 5 | /// 6 | /// Equity 7 | /// 8 | EQUITY = 1, 9 | 10 | /// 11 | /// Index/Equity Option 12 | /// 13 | IEOPTION = 2, 14 | 15 | /// 16 | /// Mutual Fund 17 | /// 18 | MUTUAL = 3, 19 | 20 | /// 21 | /// Money Market Fund 22 | /// 23 | MONEY = 4, 24 | 25 | /// 26 | /// Bond 27 | /// 28 | BONDS = 5, 29 | 30 | /// 31 | /// Index 32 | /// 33 | INDEX = 6, 34 | 35 | /// 36 | /// Market Statistic 37 | /// 38 | MKTSTATS = 7, 39 | 40 | /// 41 | /// Future 42 | /// 43 | FUTURE = 8, 44 | 45 | /// 46 | /// Future Option 47 | /// 48 | FOPTION = 9, 49 | 50 | /// 51 | /// Future Spread 52 | /// 53 | SPREAD = 10, 54 | 55 | /// 56 | /// Spot (Cash) Price 57 | /// 58 | SPOT = 11, 59 | 60 | /// 61 | /// Forward 62 | /// 63 | FORWARD = 12, 64 | 65 | /// 66 | /// DTN Calculated Statistic 67 | /// 68 | CALC = 13, 69 | 70 | /// 71 | /// Calculated Strip 72 | /// 73 | STRIP = 14, 74 | 75 | /// 76 | /// Single Stock Future 77 | /// 78 | SSFUTURE = 15, 79 | 80 | /// 81 | /// Foreign Monetary Exchange 82 | /// 83 | FOREX = 16, 84 | 85 | /// 86 | /// Future Market Depth 87 | /// 88 | MKTDEPTH = 17, 89 | 90 | /// 91 | /// Precious Metals 92 | /// 93 | PRECMTL = 18, 94 | } 95 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Lookup/Symbol/SymbolDefault.cs: -------------------------------------------------------------------------------- 1 | namespace IQFeed.CSharpApiClient.Lookup.Symbol 2 | { 3 | public class SymbolDefault 4 | { 5 | public const string MarketSymbolsArchiveUrl = "http://www.dtniq.com/product/mktsymbols_v2.zip"; 6 | 7 | public const string ExpiredOptionsArchiveUrl = "http://www.iqfeed.net/downloads/beta/IEOPTION.zip"; 8 | 9 | /// 10 | /// We can't check the length of values on most of the messages in this group, 11 | /// as some description fields can contain commas (giving us a variable number of 12 | /// fields, so we need to look for this DataId in the correct field instead. 13 | /// 14 | public const string SymbolsDataId = "LS"; 15 | } 16 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Socket/SocketDiagnostic.cs: -------------------------------------------------------------------------------- 1 | using System.Net.Sockets; 2 | using System.Threading; 3 | 4 | namespace IQFeed.CSharpApiClient.Socket 5 | { 6 | public static class SocketDiagnostic 7 | { 8 | public static bool IsPortOpen(string host, int port, int timeout, int retry) 9 | { 10 | var retryCount = 0; 11 | while (retryCount < retry) 12 | { 13 | if (retryCount > 0) 14 | Thread.Sleep(timeout); 15 | 16 | try 17 | { 18 | using (var client = new TcpClient(AddressFamily.InterNetwork)) 19 | { 20 | var result = client.BeginConnect(host, port, null, null); 21 | var success = result.AsyncWaitHandle.WaitOne(timeout); 22 | if (success) 23 | return true; 24 | 25 | client.EndConnect(result); 26 | } 27 | } 28 | catch 29 | { 30 | // ignored 31 | } 32 | finally { retryCount++; } 33 | } 34 | 35 | return false; 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Socket/SocketMessageEventArgs.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace IQFeed.CSharpApiClient.Socket 4 | { 5 | public class SocketMessageEventArgs : EventArgs 6 | { 7 | public byte[] Message { get; set;} 8 | public int Count { get; set; } 9 | } 10 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Streaming/Admin/AdminClientFactory.cs: -------------------------------------------------------------------------------- 1 | using IQFeed.CSharpApiClient.Socket; 2 | 3 | namespace IQFeed.CSharpApiClient.Streaming.Admin 4 | { 5 | public class AdminClientFactory 6 | { 7 | public static AdminClient CreateNew(string host, int port) 8 | { 9 | return new AdminClient( 10 | new SocketClient(host, port), 11 | new AdminRequestFormatter(), 12 | new AdminMessageHandler() 13 | ); 14 | } 15 | 16 | public static AdminClient CreateNew() 17 | { 18 | return new AdminClient( 19 | new SocketClient(IQFeedDefault.Hostname, IQFeedDefault.AdminPort), 20 | new AdminRequestFormatter(), 21 | new AdminMessageHandler() 22 | ); 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Streaming/Admin/AdminRequestFormatter.cs: -------------------------------------------------------------------------------- 1 | using IQFeed.CSharpApiClient.Common; 2 | 3 | namespace IQFeed.CSharpApiClient.Streaming.Admin 4 | { 5 | public class AdminRequestFormatter : RequestFormatter 6 | { 7 | public string RegisterClientApp(string productId, string productVersion) 8 | { 9 | return $"S,REGISTER CLIENT APP,{productId},{productVersion}{IQFeedDefault.ProtocolTerminatingCharacters}".ToUpper(); 10 | } 11 | 12 | public string RemoveClientApp(string productId, string productVersion) 13 | { 14 | return $"S,REMOVE CLIENT APP,{productId},{productVersion}{IQFeedDefault.ProtocolTerminatingCharacters}".ToUpper(); 15 | } 16 | 17 | public string SetLoginId(string userLoginId) 18 | { 19 | return $"S,SET LOGINID,{userLoginId}{IQFeedDefault.ProtocolTerminatingCharacters}"; 20 | } 21 | 22 | public string SetPassword(string userPassword) 23 | { 24 | return $"S,SET PASSWORD,{userPassword}{IQFeedDefault.ProtocolTerminatingCharacters}"; 25 | } 26 | 27 | public string SetSaveLoginInfo(bool on) 28 | { 29 | var value = on ? "On" : "Off"; 30 | return $"S,SET SAVE LOGIN INFO,{value}{IQFeedDefault.ProtocolTerminatingCharacters}"; 31 | } 32 | 33 | public string SetAutoconnect(bool on) 34 | { 35 | var value = on ? "On" : "Off"; 36 | return $"S,SET AUTOCONNECT,{value}{IQFeedDefault.ProtocolTerminatingCharacters}"; 37 | } 38 | 39 | public string ReqServerConnect() 40 | { 41 | return $"S,CONNECT{IQFeedDefault.ProtocolTerminatingCharacters}"; 42 | } 43 | 44 | public string ReqServerDisconnect() 45 | { 46 | return $"S,DISCONNECT{IQFeedDefault.ProtocolTerminatingCharacters}"; 47 | } 48 | 49 | public string SetClientStats(bool on) 50 | { 51 | var value = on ? "ON" : "OFF"; 52 | return $"S,CLIENTSTATS {value}{IQFeedDefault.ProtocolTerminatingCharacters}"; 53 | } 54 | } 55 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Streaming/Admin/ClientType.cs: -------------------------------------------------------------------------------- 1 | namespace IQFeed.CSharpApiClient.Streaming.Admin 2 | { 3 | public enum ClientType 4 | { 5 | Admin = 0, 6 | Level1 = 1, 7 | Level2 = 2, 8 | Lookup = 3, 9 | } 10 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Streaming/Admin/IAdminClient.cs: -------------------------------------------------------------------------------- 1 | using IQFeed.CSharpApiClient.Common; 2 | using IQFeed.CSharpApiClient.Common.Interfaces; 3 | 4 | namespace IQFeed.CSharpApiClient.Streaming.Admin 5 | { 6 | public interface IAdminClient: IClient, IAdminMessage 7 | { 8 | void RegisterClientApp(string productId, string productVersion); 9 | void RemoveClientApp(string productId, string productVersion); 10 | void SetLoginId(string userLoginId); 11 | void SetPassword(string userPassword); 12 | void SetSaveLoginInfo(bool on = true); 13 | void SetAutoconnect(bool on = true); 14 | void ReqServerConnect(); 15 | void ReqServerDisconnect(); 16 | void SetClientStats(bool on = true); 17 | 18 | 19 | // TODO: should be part from another interface 20 | void SetProtocol(string version); 21 | void SetClientName(string name); 22 | } 23 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Streaming/Admin/IAdminMessage.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using IQFeed.CSharpApiClient.Common.Messages; 3 | using IQFeed.CSharpApiClient.Streaming.Admin.Messages; 4 | 5 | namespace IQFeed.CSharpApiClient.Streaming.Admin 6 | { 7 | public interface IAdminMessage 8 | { 9 | event Action Protocol; 10 | event Action ClientApp; 11 | event Action LoginId; 12 | event Action Password; 13 | event Action LoginInfo; 14 | event Action AutoConnect; 15 | event Action Stats; 16 | event Action ClientStats; 17 | } 18 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Streaming/Admin/Messages/AutoConnectMessage.cs: -------------------------------------------------------------------------------- 1 | namespace IQFeed.CSharpApiClient.Streaming.Admin.Messages 2 | { 3 | public class AutoConnectMessage 4 | { 5 | public AutoConnectMessageType Type { get; private set; } 6 | 7 | public AutoConnectMessage(AutoConnectMessageType type) 8 | { 9 | Type = type; 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Streaming/Admin/Messages/AutoConnectMessageType.cs: -------------------------------------------------------------------------------- 1 | namespace IQFeed.CSharpApiClient.Streaming.Admin.Messages 2 | { 3 | public enum AutoConnectMessageType 4 | { 5 | On, 6 | Off 7 | } 8 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Streaming/Admin/Messages/ClientAppMessage.cs: -------------------------------------------------------------------------------- 1 | namespace IQFeed.CSharpApiClient.Streaming.Admin.Messages 2 | { 3 | public class ClientAppMessage 4 | { 5 | public ClientAppMessageType Type { get; private set; } 6 | 7 | public ClientAppMessage(ClientAppMessageType type) 8 | { 9 | Type = type; 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Streaming/Admin/Messages/ClientAppMessageType.cs: -------------------------------------------------------------------------------- 1 | namespace IQFeed.CSharpApiClient.Streaming.Admin.Messages 2 | { 3 | public enum ClientAppMessageType 4 | { 5 | Register, 6 | Remove 7 | } 8 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Streaming/Admin/Messages/ClientStatsMessage.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using IQFeed.CSharpApiClient.Extensions; 4 | 5 | namespace IQFeed.CSharpApiClient.Streaming.Admin.Messages 6 | { 7 | public class ClientStatsMessage 8 | { 9 | public const string ClientStatsDatetimeFormat = "yyyyMMdd HHmmss"; 10 | 11 | public ClientType Type { get; private set; } 12 | public int ClientId { get; private set; } 13 | public string ClientName { get; private set; } 14 | public DateTime StartTime { get; private set; } 15 | public int? Symbols { get; private set; } 16 | public int? RegionalSymbols { get; private set; } 17 | public double KbReceived { get; private set; } 18 | public double KbSent { get; private set; } 19 | public double KbQueued { get; private set; } 20 | 21 | public ClientStatsMessage(ClientType type, int clientId, string clientName, DateTime startTime, int? symbols, int? regionalSymbols, double kbReceived, double kbSent, double kbQueued) 22 | { 23 | Type = type; 24 | ClientId = clientId; 25 | ClientName = clientName; 26 | StartTime = startTime; 27 | Symbols = symbols; 28 | RegionalSymbols = regionalSymbols; 29 | KbReceived = kbReceived; 30 | KbSent = kbSent; 31 | KbQueued = kbQueued; 32 | } 33 | 34 | public static ClientStatsMessage CreateClientStatsMessage(string[] values) 35 | { 36 | int.TryParse(values[1], out var clientTypeInt); 37 | var clientType = (ClientType)clientTypeInt; 38 | int.TryParse(values[2], out var clientId); 39 | var clientName = values[3]; 40 | DateTime.TryParseExact(values[4], ClientStatsDatetimeFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out var startTime); 41 | var symbols = values[5].ToNullableInt(); 42 | var regionalSymbols = values[6].ToNullableInt(); 43 | double.TryParse(values[7], out var kbReceived); 44 | double.TryParse(values[8], out var kbSent); 45 | double.TryParse(values[9], out var kbQueued); 46 | 47 | return new ClientStatsMessage(clientType, clientId, clientName, startTime, symbols, regionalSymbols, kbReceived, kbSent, kbQueued); 48 | } 49 | } 50 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Streaming/Admin/Messages/LoginIdMessage.cs: -------------------------------------------------------------------------------- 1 | namespace IQFeed.CSharpApiClient.Streaming.Admin.Messages 2 | { 3 | public class LoginIdMessage 4 | { 5 | public string UserLoginId { get; private set; } 6 | 7 | public LoginIdMessage(string userLoginId) 8 | { 9 | UserLoginId = userLoginId; 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Streaming/Admin/Messages/LoginInfoMessage.cs: -------------------------------------------------------------------------------- 1 | namespace IQFeed.CSharpApiClient.Streaming.Admin.Messages 2 | { 3 | public class LoginInfoMessage 4 | { 5 | public LoginInfoMessageType Type { get; private set; } 6 | 7 | public LoginInfoMessage(LoginInfoMessageType type) 8 | { 9 | Type = type; 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Streaming/Admin/Messages/LoginInfoMessageType.cs: -------------------------------------------------------------------------------- 1 | namespace IQFeed.CSharpApiClient.Streaming.Admin.Messages 2 | { 3 | public enum LoginInfoMessageType 4 | { 5 | Saved, 6 | NotSaved 7 | } 8 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Streaming/Admin/Messages/PasswordMessage.cs: -------------------------------------------------------------------------------- 1 | namespace IQFeed.CSharpApiClient.Streaming.Admin.Messages 2 | { 3 | public class PasswordMessage 4 | { 5 | public PasswordMessage(string userPassword) 6 | { 7 | UserPassword = userPassword; 8 | } 9 | public string UserPassword { get; private set; } 10 | } 11 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Streaming/Admin/StatsStatusType.cs: -------------------------------------------------------------------------------- 1 | namespace IQFeed.CSharpApiClient.Streaming.Admin 2 | { 3 | public enum StatsStatusType 4 | { 5 | NotConnected, 6 | Connected 7 | } 8 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Streaming/Common/Messages/ErrorMessage.cs: -------------------------------------------------------------------------------- 1 | using IQFeed.CSharpApiClient.Extensions; 2 | 3 | namespace IQFeed.CSharpApiClient.Streaming.Common.Messages 4 | { 5 | public class ErrorMessage 6 | { 7 | public ErrorMessage(string error) 8 | { 9 | Error = error; 10 | } 11 | 12 | public string Error { get; private set; } 13 | 14 | public static ErrorMessage Parse(string message) 15 | { 16 | var values = message.SplitFeedMessage(); 17 | return new ErrorMessage(values[1]); 18 | } 19 | 20 | public override bool Equals(object obj) 21 | { 22 | return obj is ErrorMessage message && Error == message.Error; 23 | } 24 | 25 | public override int GetHashCode() 26 | { 27 | unchecked 28 | { 29 | return 2010064793 + Error.GetHashCode(); 30 | } 31 | } 32 | 33 | public override string ToString() 34 | { 35 | return $"{nameof(Error)}: {Error}"; 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Streaming/Common/Messages/SymbolNotFoundMessage.cs: -------------------------------------------------------------------------------- 1 | using IQFeed.CSharpApiClient.Extensions; 2 | 3 | namespace IQFeed.CSharpApiClient.Streaming.Common.Messages 4 | { 5 | public class SymbolNotFoundMessage 6 | { 7 | public SymbolNotFoundMessage(string symbol) 8 | { 9 | Symbol = symbol; 10 | } 11 | 12 | public string Symbol { get; private set; } 13 | 14 | public static SymbolNotFoundMessage Parse(string message) 15 | { 16 | var values = message.SplitFeedMessage(); 17 | return new SymbolNotFoundMessage(values[1]); 18 | } 19 | 20 | public override bool Equals(object obj) 21 | { 22 | return obj is SymbolNotFoundMessage message && 23 | Symbol == message.Symbol; 24 | } 25 | 26 | public override int GetHashCode() 27 | { 28 | unchecked 29 | { 30 | return -1758840423 + Symbol.GetHashCode(); 31 | } 32 | } 33 | 34 | public override string ToString() 35 | { 36 | return $"{nameof(Symbol)}: {Symbol}"; 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Streaming/Common/Messages/SystemMessage.cs: -------------------------------------------------------------------------------- 1 | using IQFeed.CSharpApiClient.Extensions; 2 | 3 | namespace IQFeed.CSharpApiClient.Streaming.Common.Messages 4 | { 5 | public class SystemMessage 6 | { 7 | public string Type { get; private set; } 8 | public string Message { get; private set; } 9 | 10 | public SystemMessage(string type, string message) 11 | { 12 | Type = type; 13 | Message = message; 14 | } 15 | 16 | public static SystemMessage Parse(string message) 17 | { 18 | var values = message.SplitFeedMessage(); 19 | 20 | return new SystemMessage(values[1], message); 21 | } 22 | 23 | public override bool Equals(object obj) 24 | { 25 | return obj is SystemMessage message && 26 | Type == message.Type && 27 | Message == message.Message; 28 | } 29 | 30 | public override int GetHashCode() 31 | { 32 | unchecked 33 | { 34 | var hashCode = 17; 35 | hashCode = hashCode * 29 + Type.GetHashCode(); 36 | hashCode = hashCode * 29 + Message.GetHashCode(); 37 | return hashCode; 38 | } 39 | } 40 | 41 | public override string ToString() 42 | { 43 | return $"{nameof(Type)}: {Type}, {nameof(Message)}: {Message}"; 44 | } 45 | } 46 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Streaming/Common/Messages/TimestampMessage.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using IQFeed.CSharpApiClient.Extensions; 4 | 5 | namespace IQFeed.CSharpApiClient.Streaming.Common.Messages 6 | { 7 | // T,[YYYYMMDD HH:mm:SS] 8 | public class TimestampMessage 9 | { 10 | public const string TimestampMessageDateTimeFormat = "yyyyMMdd HH:mm:ss"; 11 | 12 | public TimestampMessage(DateTime timestamp) 13 | { 14 | Timestamp = timestamp; 15 | } 16 | 17 | public DateTime Timestamp { get; private set; } 18 | 19 | public static TimestampMessage Parse(string message) 20 | { 21 | var values = message.SplitFeedMessage(); 22 | 23 | DateTime.TryParseExact(values[1], TimestampMessageDateTimeFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out var timestamp); 24 | return new TimestampMessage(timestamp); 25 | } 26 | 27 | public override bool Equals(object obj) 28 | { 29 | return obj is TimestampMessage message && 30 | Timestamp == message.Timestamp; 31 | } 32 | 33 | public override int GetHashCode() 34 | { 35 | unchecked 36 | { 37 | return 227403579 + Timestamp.GetHashCode(); 38 | } 39 | } 40 | 41 | public override string ToString() 42 | { 43 | return $"{nameof(Timestamp)}: {Timestamp}"; 44 | } 45 | } 46 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Streaming/Derivative/DerivativeClientFactory.cs: -------------------------------------------------------------------------------- 1 | using IQFeed.CSharpApiClient.Socket; 2 | 3 | namespace IQFeed.CSharpApiClient.Streaming.Derivative 4 | { 5 | public class DerivativeClientFactory 6 | { 7 | public static DerivativeClient CreateNew(string host, int port, int bufferSize) 8 | { 9 | return new DerivativeClient(new SocketClient(host, port, bufferSize), new DerivativeRequestFormatter(), new DerivativeMessageHandler()); 10 | } 11 | 12 | public static DerivativeClient CreateNew() 13 | { 14 | return CreateNew(IQFeedDefault.Hostname, IQFeedDefault.DerivativePort, DerivativeDefault.BufferSize); 15 | } 16 | 17 | public static DerivativeClient CreateNew(string host, int port) 18 | { 19 | return CreateNew(host, port, DerivativeDefault.BufferSize); 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Streaming/Derivative/DerivativeDefault.cs: -------------------------------------------------------------------------------- 1 | namespace IQFeed.CSharpApiClient.Streaming.Derivative 2 | { 3 | public class DerivativeDefault 4 | { 5 | public const int BufferSize = 32 * 1024; 6 | } 7 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Streaming/Derivative/DerivativeIntervalType.cs: -------------------------------------------------------------------------------- 1 | namespace IQFeed.CSharpApiClient.Streaming.Derivative 2 | { 3 | public enum DerivativeIntervalType 4 | { 5 | /// 6 | /// (default) for time intervals in seconds 7 | /// 8 | S, 9 | /// 10 | /// Volume intervals 11 | /// 12 | V, 13 | /// 14 | /// Tick intervals 15 | /// 16 | T 17 | } 18 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Streaming/Derivative/DerivativeRequestFormatter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using IQFeed.CSharpApiClient.Common; 3 | 4 | namespace IQFeed.CSharpApiClient.Streaming.Derivative 5 | { 6 | public class DerivativeRequestFormatter : RequestFormatter 7 | { 8 | public const string DerivativeTimeFormat = "hhmmss"; 9 | public const string DerivativeDatetimeFormat = "yyyyMMdd HHmmss"; 10 | 11 | public string ReqBarWatch(string symbol, int interval, DateTime? beginDate = null, int? maxDaysOfDatapoints = null, int? maxDatapoints = null, 12 | TimeSpan? beginFilterTime = null, TimeSpan? endFilterTime = null, string requestId = null, DerivativeIntervalType? intervalType = null, int? updateInterval = null) 13 | { 14 | // BW,[Symbol],[Interval],[BeginDate BeginTime],[MaxDaysOfDatapoints],[MaxDatapoints],[BeginFilterTime],[EndFilterTime],[RequestID],[Interval Type],[Reserved],[UpdateInterval] 15 | var request = $"BW,{symbol.ToUpper()},{interval},{beginDate?.ToString(DerivativeDatetimeFormat)},{maxDaysOfDatapoints},{maxDatapoints},{beginFilterTime?.ToString(DerivativeTimeFormat)},{endFilterTime?.ToString(DerivativeTimeFormat)},{requestId},{intervalType?.ToString().ToLower()},,{updateInterval}{IQFeedDefault.ProtocolTerminatingCharacters}"; 16 | return request; 17 | } 18 | 19 | public string ReqBarUnwatch(string symbol, string requestId) 20 | { 21 | return $"BR,{symbol.ToUpper()},{requestId},{IQFeedDefault.ProtocolTerminatingCharacters}"; 22 | } 23 | 24 | public string ReqWatches() 25 | { 26 | return $"S,REQUEST WATCHES,{IQFeedDefault.ProtocolTerminatingCharacters}"; 27 | } 28 | 29 | public string UnwatchAll() 30 | { 31 | return $"S,UNWATCH ALL,{IQFeedDefault.ProtocolTerminatingCharacters}"; 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Streaming/Derivative/DerivativeWatchDefinition.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Text.RegularExpressions; 3 | using IQFeed.CSharpApiClient.Extensions; 4 | 5 | namespace IQFeed.CSharpApiClient.Streaming.Derivative 6 | { 7 | public class DerivativeWatchDefinition 8 | { 9 | private const string DerivativeWatchesPattern = "^S,WATCHES,(.*)$"; 10 | private static readonly Regex DerivativeWatchesRegex = new Regex(DerivativeWatchesPattern); 11 | 12 | public DerivativeWatchDefinition(string symbol, string interval, string requestId) 13 | { 14 | Symbol = symbol; 15 | Interval = interval; 16 | RequestId = requestId; 17 | } 18 | 19 | public string Symbol { get; } 20 | public string Interval { get; } 21 | public string RequestId { get; } 22 | 23 | public static IEnumerable Parse(string message) 24 | { 25 | var match = DerivativeWatchesRegex.Match(message); 26 | if (match.Success) 27 | { 28 | var watches = match.Groups[1].Value.SplitFeedMessage(); 29 | var offset = 0; 30 | 31 | while (offset < watches.Length) 32 | { 33 | yield return new DerivativeWatchDefinition(watches[offset], watches[offset + 1], watches[offset + 2]); 34 | offset += 3; 35 | } 36 | } 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Streaming/Derivative/IDerivativeClient.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using IQFeed.CSharpApiClient.Common.Interfaces; 3 | 4 | namespace IQFeed.CSharpApiClient.Streaming.Derivative 5 | { 6 | public interface IDerivativeClient: IClient, IDerivativeEvent 7 | { 8 | void SetClientName(string name); 9 | 10 | void ReqBarWatch(string symbol, int interval, DateTime? beginDate = null, int? maxDaysOfDatapoints = null, int? maxDatapoints = null, TimeSpan? beginFilterTime = null, 11 | TimeSpan? endFilterTime = null, string requestId = null, DerivativeIntervalType? intervalType = null, int? updateInterval = null); 12 | 13 | void ReqBarUnwatch(string symbol, string requestId); 14 | void ReqWatches(); 15 | void UnwatchAll(); 16 | } 17 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Streaming/Derivative/IDerivativeEvent.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using IQFeed.CSharpApiClient.Streaming.Common.Messages; 3 | using IQFeed.CSharpApiClient.Streaming.Derivative.Messages; 4 | 5 | namespace IQFeed.CSharpApiClient.Streaming.Derivative 6 | { 7 | public interface IDerivativeEvent 8 | { 9 | event Action Error; 10 | event Action IntervalBar; 11 | event Action SymbolNotFound; 12 | event Action System; 13 | } 14 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Streaming/Derivative/IDerivativeMessageHandler.cs: -------------------------------------------------------------------------------- 1 | namespace IQFeed.CSharpApiClient.Streaming.Derivative 2 | { 3 | public interface IDerivativeMessageHandler : IDerivativeEvent 4 | { 5 | void ProcessMessages(byte[] messageBytes, int count); 6 | } 7 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Streaming/Derivative/Messages/IIntervalBarMessage.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace IQFeed.CSharpApiClient.Streaming.Derivative.Messages 4 | { 5 | public interface IIntervalBarMessage 6 | { 7 | IntervalBarType Type { get; } 8 | string Symbol { get; } 9 | DateTime Timestamp { get; } 10 | double Open { get; } 11 | double High { get; } 12 | double Low { get; } 13 | double Last { get; } 14 | 15 | /// 16 | /// Last cummulative volume in the interval 17 | /// 18 | int CummulativeVolume { get; } 19 | 20 | /// 21 | /// Interval volume for the interval 22 | /// 23 | int IntervalVolume { get; } 24 | 25 | /// 26 | /// Number of trades in the interval (only valid for tick interval) 27 | /// 28 | int NumberOfTrades { get; } 29 | 30 | string RequestId { get; } 31 | } 32 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Streaming/Derivative/Messages/IntervalBarType.cs: -------------------------------------------------------------------------------- 1 | namespace IQFeed.CSharpApiClient.Streaming.Derivative.Messages 2 | { 3 | public enum IntervalBarType 4 | { 5 | /// 6 | /// Update type; 'U' - updated interval bar 7 | /// 8 | U, 9 | 10 | /// 11 | /// 'H' - complete interval bar from history 12 | /// 13 | H, 14 | 15 | /// 16 | /// 'C' - complete interval bar from stream 17 | /// 18 | C 19 | } 20 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Streaming/FieldsetDescriptionAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace IQFeed.CSharpApiClient.Streaming 4 | { 5 | internal class FieldsetDescriptionAttribute : Attribute 6 | { 7 | public string Name { get; } 8 | public Type Type { get; } 9 | 10 | public FieldsetDescriptionAttribute(string name, Type type) 11 | { 12 | Name = name; 13 | Type = type; 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Streaming/Level1/Dynamic/Handlers/ILevel1DynamicMessageHandler.cs: -------------------------------------------------------------------------------- 1 | namespace IQFeed.CSharpApiClient.Streaming.Level1.Dynamic.Handlers 2 | { 3 | public interface ILevel1DynamicMessageHandler : ILevel1DynamicEvent 4 | { 5 | void ProcessMessages(byte[] messageBytes, int count); 6 | void SetDynamicFields(params DynamicFieldset[] fieldNames); 7 | } 8 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Streaming/Level1/Dynamic/ILevel1DynamicClient.cs: -------------------------------------------------------------------------------- 1 | using IQFeed.CSharpApiClient.Common; 2 | using IQFeed.CSharpApiClient.Common.Interfaces; 3 | 4 | namespace IQFeed.CSharpApiClient.Streaming.Level1.Dynamic 5 | { 6 | public interface ILevel1DynamicClient : IClient, ILevel1DynamicEvent, ILevel1DynamicSnapshot 7 | { 8 | void ReqWatch(string symbol); 9 | void ReqTradesOnlyWatch(string symbol); 10 | void ReqUnwatch(string symbol); 11 | void ReqForcedRefresh(string symbol); 12 | void ReqTimestamp(); 13 | void ReqTimestamps(bool on); 14 | void ReqRegionalWatch(string symbol); 15 | void ReqRegionalUnwatch(string symbol); 16 | void ReqNews(bool on); 17 | void ReqStats(); 18 | void ReqFundamentalFieldnames(); 19 | void ReqUpdateFieldnames(); 20 | void ReqCurrentUpdateFieldNames(); 21 | void SetLogLevels(params LoggingLevel[] logLevels); 22 | void ReqWatchList(); 23 | void ReqUnwatchAll(); 24 | void ReqServerConnect(); 25 | void ReqServerDisconnect(); 26 | } 27 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Streaming/Level1/Dynamic/ILevel1DynamicEvent.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using IQFeed.CSharpApiClient.Streaming.Level1.Dynamic.Messages; 3 | 4 | namespace IQFeed.CSharpApiClient.Streaming.Level1.Dynamic 5 | { 6 | public interface ILevel1DynamicEvent : ILevel1EventCommon 7 | { 8 | event Action Summary; 9 | event Action Update; 10 | } 11 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Streaming/Level1/Dynamic/ILevel1DynamicSnapshot.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using IQFeed.CSharpApiClient.Streaming.Level1.Dynamic.Messages; 3 | using IQFeed.CSharpApiClient.Streaming.Level1.Messages; 4 | 5 | namespace IQFeed.CSharpApiClient.Streaming.Level1.Dynamic 6 | { 7 | public interface ILevel1DynamicSnapshot : ILevel1DynamicSnapshotSync 8 | { 9 | Task GetFundamentalSnapshotAsync(string symbol); 10 | Task GetUpdateSummarySnapshotAsync(string symbol); 11 | } 12 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Streaming/Level1/Dynamic/ILevel1DynamicSnapshotSync.cs: -------------------------------------------------------------------------------- 1 | using IQFeed.CSharpApiClient.Streaming.Level1.Dynamic.Messages; 2 | using IQFeed.CSharpApiClient.Streaming.Level1.Messages; 3 | 4 | namespace IQFeed.CSharpApiClient.Streaming.Level1.Dynamic 5 | { 6 | public interface ILevel1DynamicSnapshotSync 7 | { 8 | FundamentalMessage GetFundamentalSnapshot(string symbol); 9 | IUpdateSummaryDynamicMessage GetUpdateSummarySnapshot(string symbol); 10 | } 11 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Streaming/Level1/Dynamic/Level1DynamicClientFactory.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using IQFeed.CSharpApiClient.Socket; 3 | using IQFeed.CSharpApiClient.Streaming.Level1.Dynamic.Handlers; 4 | 5 | namespace IQFeed.CSharpApiClient.Streaming.Level1.Dynamic 6 | { 7 | public static class Level1DynamicClientFactory 8 | { 9 | public static ILevel1DynamicClient CreateNew(string host, int port, TimeSpan snapshotTimeout, ILevel1DynamicMessageHandler level1DynamicMessageHandler, params DynamicFieldset[] fieldNames) 10 | { 11 | var socketClient = new SocketClient(host, port); 12 | var level1RequestFormatter = new Level1RequestFormatter(); 13 | 14 | return new Level1DynamicClient( 15 | socketClient, 16 | level1RequestFormatter, 17 | level1DynamicMessageHandler, 18 | new Level1DynamicSnapshot(socketClient, level1RequestFormatter, level1DynamicMessageHandler, snapshotTimeout), 19 | fieldNames 20 | ); 21 | } 22 | 23 | public static ILevel1DynamicClient CreateNew(params DynamicFieldset[] fieldNames) 24 | { 25 | return CreateNew(IQFeedDefault.Hostname, IQFeedDefault.Level1Port, Level1Default.SnapshotTimeout, new Level1DynamicMessageHandler(), fieldNames); 26 | } 27 | 28 | public static ILevel1DynamicClient CreateNew(ILevel1DynamicMessageHandler level1DynamicMessageHandler, params DynamicFieldset[] fieldNames) 29 | { 30 | return CreateNew(IQFeedDefault.Hostname, IQFeedDefault.Level1Port, Level1Default.SnapshotTimeout, level1DynamicMessageHandler, fieldNames); 31 | } 32 | 33 | public static ILevel1DynamicClient CreateNew(string host, int port, params DynamicFieldset[] fieldNames) 34 | { 35 | return CreateNew(host, port, Level1Default.SnapshotTimeout, new Level1DynamicMessageHandler(), fieldNames); 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Streaming/Level1/Handlers/ILevel1MessageDynamicHandler.cs: -------------------------------------------------------------------------------- 1 | namespace IQFeed.CSharpApiClient.Streaming.Level1.Handlers 2 | { 3 | public interface ILevel1MessageDynamicHandler : ILevel1MessageHandler 4 | { 5 | void SetDynamicFields(params DynamicFieldset[] fieldNames); 6 | } 7 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Streaming/Level1/Handlers/ILevel1MessageHandler.cs: -------------------------------------------------------------------------------- 1 | namespace IQFeed.CSharpApiClient.Streaming.Level1.Handlers 2 | { 3 | public interface ILevel1MessageHandler : ILevel1Event 4 | { 5 | void ProcessMessages(byte[] messageBytes, int count); 6 | } 7 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Streaming/Level1/Handlers/Level1MessageDynamicHandler.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using IQFeed.CSharpApiClient.Streaming.Level1.Messages; 3 | 4 | namespace IQFeed.CSharpApiClient.Streaming.Level1.Handlers 5 | { 6 | [Obsolete("Please use ILevel1DynamicClient instead. This handler will be removed soon!")] 7 | public class Level1MessageDynamicHandler : BaseLevel1MessageHandler, ILevel1MessageDynamicHandler 8 | { 9 | public event Action Summary; 10 | public event Action Update; 11 | 12 | private DynamicFieldset[] _dynamicFieldsets; // not thread-safe 13 | 14 | public void SetDynamicFields(params DynamicFieldset[] fieldNames) 15 | { 16 | if (fieldNames[0] != DynamicFieldset.Symbol) 17 | throw new ArgumentException("Symbol must be the first dynamic field specified."); 18 | 19 | foreach (var fieldName in fieldNames) 20 | { 21 | if (fieldName == DynamicFieldset.Type) 22 | throw new ArgumentException("Type is implicitly included in dynamic fields and must not be included in the dynamic fields requested."); 23 | } 24 | 25 | _dynamicFieldsets = fieldNames; 26 | } 27 | 28 | protected override void ProcessSummaryMessage(string msg) 29 | { 30 | var dynamicFields = Level1DynamicFields.Parse(msg, _dynamicFieldsets); 31 | Summary?.Invoke(new UpdateSummaryDynamicMessage(dynamicFields)); 32 | } 33 | 34 | protected override void ProcessUpdateMessage(string msg) 35 | { 36 | var dynamicFields = Level1DynamicFields.Parse(msg, _dynamicFieldsets); 37 | Update?.Invoke(new UpdateSummaryDynamicMessage(dynamicFields)); 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Streaming/Level1/Handlers/Level1MessageHandler.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using IQFeed.CSharpApiClient.Streaming.Level1.Messages; 3 | 4 | namespace IQFeed.CSharpApiClient.Streaming.Level1.Handlers 5 | { 6 | public class Level1MessageHandler : BaseLevel1MessageHandler, ILevel1MessageHandler 7 | { 8 | public event Action Summary; 9 | public event Action Update; 10 | 11 | protected override void ProcessSummaryMessage(string msg) 12 | { 13 | var updateSummaryMessage = UpdateSummaryMessage.Parse(msg); 14 | Summary?.Invoke(updateSummaryMessage); 15 | } 16 | 17 | protected override void ProcessUpdateMessage(string msg) 18 | { 19 | var updateSummaryMessage = UpdateSummaryMessage.Parse(msg); 20 | Update?.Invoke(updateSummaryMessage); 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Streaming/Level1/ILevel1Client.cs: -------------------------------------------------------------------------------- 1 | using IQFeed.CSharpApiClient.Common; 2 | using IQFeed.CSharpApiClient.Common.Interfaces; 3 | 4 | namespace IQFeed.CSharpApiClient.Streaming.Level1 5 | { 6 | public interface ILevel1Client: IClient, ILevel1Event, ILevel1Snapshot 7 | { 8 | void ReqWatch(string symbol); 9 | void ReqTradesOnlyWatch(string symbol); 10 | void ReqUnwatch(string symbol); 11 | void ReqForcedRefresh(string symbol); 12 | void ReqTimestamp(); 13 | void ReqTimestamps(bool on); 14 | void ReqRegionalWatch(string symbol); 15 | void ReqRegionalUnwatch(string symbol); 16 | void ReqNews(bool on); 17 | void ReqStats(); 18 | void ReqFundamentalFieldnames(); 19 | void ReqUpdateFieldnames(); 20 | void ReqCurrentUpdateFieldNames(); 21 | void SelectUpdateFieldName(params DynamicFieldset[] fieldNames); 22 | void SetLogLevels(params LoggingLevel[] logLevels); 23 | void ReqWatchList(); 24 | void ReqUnwatchAll(); 25 | void ReqServerConnect(); 26 | void ReqServerDisconnect(); 27 | } 28 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Streaming/Level1/ILevel1Event.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using IQFeed.CSharpApiClient.Streaming.Level1.Messages; 3 | 4 | namespace IQFeed.CSharpApiClient.Streaming.Level1 5 | { 6 | public interface ILevel1Event : ILevel1EventCommon 7 | { 8 | event Action Summary; 9 | event Action Update; 10 | } 11 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Streaming/Level1/ILevel1EventCommon.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using IQFeed.CSharpApiClient.Streaming.Common.Messages; 3 | using IQFeed.CSharpApiClient.Streaming.Level1.Messages; 4 | 5 | namespace IQFeed.CSharpApiClient.Streaming.Level1 6 | { 7 | public interface ILevel1EventCommon 8 | { 9 | event Action Fundamental; 10 | event Action System; 11 | event Action SymbolNotFound; 12 | event Action Error; 13 | event Action Timestamp; 14 | event Action Regional; 15 | event Action News; 16 | } 17 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Streaming/Level1/ILevel1Snapshot.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using IQFeed.CSharpApiClient.Streaming.Level1.Messages; 3 | 4 | namespace IQFeed.CSharpApiClient.Streaming.Level1 5 | { 6 | public interface ILevel1Snapshot : ILevel1SnapshotSync 7 | { 8 | Task GetFundamentalSnapshotAsync(string symbol); 9 | Task GetUpdateSummarySnapshotAsync(string symbol); 10 | } 11 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Streaming/Level1/ILevel1SnapshotSync.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using IQFeed.CSharpApiClient.Streaming.Level1.Messages; 3 | 4 | namespace IQFeed.CSharpApiClient.Streaming.Level1 5 | { 6 | public interface ILevel1SnapshotSync 7 | { 8 | FundamentalMessage GetFundamentalSnapshot(string symbol); 9 | IUpdateSummaryMessage GetUpdateSummarySnapshot(string symbol); 10 | } 11 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Streaming/Level1/Level1ClientFactory.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using IQFeed.CSharpApiClient.Socket; 3 | using IQFeed.CSharpApiClient.Streaming.Level1.Handlers; 4 | 5 | namespace IQFeed.CSharpApiClient.Streaming.Level1 6 | { 7 | public static class Level1ClientFactory 8 | { 9 | public static Level1Client CreateNew(string host, int port, TimeSpan snapshotTimeout, ILevel1MessageHandler level1MessageHandler) 10 | { 11 | var socketClient = new SocketClient(host, port); 12 | var level1RequestFormatter = new Level1RequestFormatter(); 13 | 14 | return new Level1Client( 15 | socketClient, 16 | level1RequestFormatter, 17 | level1MessageHandler, 18 | new Level1Snapshot(socketClient, level1RequestFormatter, level1MessageHandler, snapshotTimeout) 19 | ); 20 | } 21 | 22 | public static Level1Client CreateNew() 23 | { 24 | return CreateNew(IQFeedDefault.Hostname, IQFeedDefault.Level1Port, Level1Default.SnapshotTimeout, new Level1MessageHandler()); 25 | } 26 | 27 | public static Level1Client CreateNew(ILevel1MessageHandler level1MessageHandler) 28 | { 29 | return CreateNew(IQFeedDefault.Hostname, IQFeedDefault.Level1Port, Level1Default.SnapshotTimeout, level1MessageHandler); 30 | } 31 | 32 | public static Level1Client CreateNew(string host, int port) 33 | { 34 | return CreateNew(host, port, Level1Default.SnapshotTimeout, new Level1MessageHandler()); 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Streaming/Level1/Level1Default.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace IQFeed.CSharpApiClient.Streaming.Level1 4 | { 5 | public class Level1Default 6 | { 7 | public static TimeSpan SnapshotTimeout = TimeSpan.FromMinutes(1); 8 | } 9 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Streaming/Level1/Messages/IRegionalUpdateMessage.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace IQFeed.CSharpApiClient.Streaming.Level1.Messages 4 | { 5 | public interface IRegionalUpdateMessage 6 | { 7 | string Symbol { get; } 8 | string Exchange { get; } 9 | double RegionalBid { get; } 10 | int RegionalBidSize { get; } 11 | DateTime RegionalBidTime { get; } 12 | double RegionalAsk { get; } 13 | int RegionalAskSize { get; } 14 | DateTime RegionalAskTime { get; } 15 | int FractionDisplayCode { get; } 16 | int DecimalPrecision { get; } 17 | int MarketCenter { get; } 18 | } 19 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Streaming/Level1/Messages/ITradeCorrectionMessage.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace IQFeed.CSharpApiClient.Streaming.Level1.Messages 8 | { 9 | public interface ITradeCorrectionMessage 10 | { 11 | string Symbol { get; } 12 | string CorrectionType { get; } 13 | DateTime TradeDate { get; } 14 | TimeSpan TradeTime { get; } 15 | double TradePrice { get; } 16 | int TradeSize { get; } 17 | int TickId { get; } 18 | string TradeConditions { get; } 19 | int TradeMarketCentre { get; } 20 | 21 | DateTime TradeDateTime { get; } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Streaming/Level1/Messages/IUpdateSummaryMessage.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace IQFeed.CSharpApiClient.Streaming.Level1.Messages 4 | { 5 | public interface IUpdateSummaryMessage 6 | { 7 | string Symbol { get; } 8 | double MostRecentTrade { get; } 9 | int MostRecentTradeSize { get; } 10 | TimeSpan MostRecentTradeTime { get; } 11 | int MostRecentTradeMarketCenter { get; } 12 | int TotalVolume { get; } 13 | double Bid { get; } 14 | int BidSize { get; } 15 | double Ask { get; } 16 | int AskSize { get; } 17 | double Open { get; } 18 | double High { get; } 19 | double Low { get; } 20 | double Close { get; } 21 | string MessageContents { get; } 22 | string MostRecentTradeConditions { get; } 23 | 24 | [Obsolete("Please use ILevel1DynamicClient instead. This field will be removed soon!")] 25 | Level1DynamicFields DynamicFields { get; } 26 | } 27 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Streaming/Level2/Enums/Level2MessageType.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using IQFeed.CSharpApiClient.Streaming.Level2.Messages; 7 | 8 | namespace IQFeed.CSharpApiClient.Streaming.Level2.Enums 9 | { 10 | public enum Level2MessageType 11 | { 12 | PriceLevelOrder = 0, 13 | OrderAdd = 3, 14 | OrderLevelUpdate = 4, 15 | OrderDelete = 5, 16 | OrderLevelSummary = 6, 17 | PriceLevelSummary = 7, 18 | PriceLevelUpdate = 8, 19 | PriceLevelDelete = 9 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Streaming/Level2/Enums/Level2Side.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace IQFeed.CSharpApiClient.Streaming.Level2 8 | { 9 | public enum Level2Side 10 | { 11 | Sell, 12 | Buy 13 | } 14 | 15 | public static class Level2SideParser 16 | { 17 | public static Level2Side Parse(string text) 18 | { 19 | if (text == "S") 20 | { 21 | return Level2Side.Sell; 22 | } else if(text == "B") 23 | { 24 | return Level2Side.Buy; 25 | } else 26 | { 27 | return (Level2Side)Enum.Parse(typeof(Level2Side), text, true); 28 | } 29 | } 30 | 31 | public static bool TryParse(string text, out Level2Side result) 32 | { 33 | if (text == "S") 34 | { 35 | result = Level2Side.Sell; 36 | return true; 37 | } 38 | 39 | if (text == "B") 40 | { 41 | result = Level2Side.Buy; 42 | return true; 43 | } 44 | 45 | return Enum.TryParse(text, out result); 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Streaming/Level2/ILevel2Client.cs: -------------------------------------------------------------------------------- 1 | using IQFeed.CSharpApiClient.Common.Interfaces; 2 | 3 | namespace IQFeed.CSharpApiClient.Streaming.Level2 4 | { 5 | public interface ILevel2Client : IClient, ILevel2Event, ILevel2Snapshot 6 | { 7 | void ReqWatch(string symbol); 8 | void ReqWatchMarketByPrice(string symbol); 9 | void ReqWatchMarketByOrder(string symbol); 10 | void ReqMarketMakerNameById(string mmid); 11 | void ReqUnwatch(string symbol); 12 | void ReqServerConnect(); 13 | void ReqServerDisconnect(); 14 | } 15 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Streaming/Level2/ILevel2Event.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using IQFeed.CSharpApiClient.Streaming.Common.Messages; 3 | using IQFeed.CSharpApiClient.Streaming.Level2.Messages; 4 | 5 | namespace IQFeed.CSharpApiClient.Streaming.Level2 6 | { 7 | public interface ILevel2Event 8 | { 9 | event Action Summary; 10 | event Action Update; 11 | event Action SymbolNotFound; 12 | event Action Query; 13 | event Action Error; 14 | event Action Timestamp; 15 | event Action System; 16 | 17 | //protocol 6.2 events 18 | event Action OrderAdd; 19 | event Action OrderUpdate; 20 | event Action OrderSummary; 21 | event Action OrderDelete; 22 | event Action PriceLevelOrder; 23 | event Action PriceLevelSummary; 24 | event Action PriceLevelUpdate; 25 | event Action PriceLevelDelete; 26 | } 27 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Streaming/Level2/ILevel2MessageHandler.cs: -------------------------------------------------------------------------------- 1 | namespace IQFeed.CSharpApiClient.Streaming.Level2 2 | { 3 | public interface ILevel2MessageHandler : ILevel2Event 4 | { 5 | void ProcessMessages(byte[] messageBytes, int count); 6 | } 7 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Streaming/Level2/ILevel2Snapshot.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Threading.Tasks; 3 | using IQFeed.CSharpApiClient.Streaming.Level2.Messages; 4 | 5 | namespace IQFeed.CSharpApiClient.Streaming.Level2 6 | { 7 | public interface ILevel2Snapshot 8 | { 9 | Task> GetSummarySnapshotAsync(string symbol); 10 | } 11 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Streaming/Level2/Level2ClientFactory.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using IQFeed.CSharpApiClient.Socket; 3 | 4 | namespace IQFeed.CSharpApiClient.Streaming.Level2 5 | { 6 | public static class Level2ClientFactory 7 | { 8 | public static Level2Client CreateNew(string host, int port, TimeSpan snapshotTimeout, string protocolVersion = IQFeedDefault.ProtocolVersion) 9 | { 10 | var socketClient = new SocketClient(host, port); 11 | var level2RequestFormatter = new Level2RequestFormatter(); 12 | var level2MessageHandler = new Level2MessageHandler(); 13 | 14 | return new Level2Client( 15 | socketClient, 16 | level2RequestFormatter, 17 | level2MessageHandler, 18 | new Level2Snapshot(socketClient, level2RequestFormatter, level2MessageHandler, snapshotTimeout), 19 | protocolVersion 20 | ); 21 | } 22 | 23 | public static Level2Client CreateNew(string protocolVersion = IQFeedDefault.ProtocolVersion) 24 | { 25 | return CreateNew(IQFeedDefault.Hostname, IQFeedDefault.Level2Port, Level2Default.SnapshotTimeout, protocolVersion); 26 | } 27 | 28 | public static Level2Client CreateNew(string host, int port, string protocolVersion = IQFeedDefault.ProtocolVersion) 29 | { 30 | return CreateNew(host, port, Level2Default.SnapshotTimeout, protocolVersion); 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Streaming/Level2/Level2Default.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace IQFeed.CSharpApiClient.Streaming.Level2 4 | { 5 | public class Level2Default 6 | { 7 | public static TimeSpan SnapshotTimeout = TimeSpan.FromMinutes(2); 8 | } 9 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Streaming/Level2/Level2RequestFormatter.cs: -------------------------------------------------------------------------------- 1 | using IQFeed.CSharpApiClient.Common; 2 | 3 | namespace IQFeed.CSharpApiClient.Streaming.Level2 4 | { 5 | public class Level2RequestFormatter : RequestFormatter 6 | { 7 | public string ReqWatch(string symbol) 8 | { 9 | return $"w{symbol.ToUpper()}{IQFeedDefault.ProtocolTerminatingCharacters}"; 10 | } 11 | 12 | public string ReqWatchMarketByPrice(string symbol) 13 | { 14 | return $"WPL,{symbol.ToUpper()}{IQFeedDefault.ProtocolTerminatingCharacters}"; 15 | } 16 | 17 | public string ReqWatchMarketByOrder(string symbol) 18 | { 19 | return $"WOR,{symbol.ToUpper()}{IQFeedDefault.ProtocolTerminatingCharacters}"; 20 | } 21 | 22 | public string ReqMarketMakerNameById(string mmid) 23 | { 24 | return $"m{mmid.ToUpper()}{IQFeedDefault.ProtocolTerminatingCharacters}"; 25 | } 26 | 27 | public string ReqUnwatch(string symbol) 28 | { 29 | return $"r{symbol.ToUpper()}{IQFeedDefault.ProtocolTerminatingCharacters}"; 30 | } 31 | 32 | public string ReqServerConnect() 33 | { 34 | return $"c{IQFeedDefault.ProtocolTerminatingCharacters}"; 35 | } 36 | 37 | public string ReqServerDisconnect() 38 | { 39 | return $"x{IQFeedDefault.ProtocolTerminatingCharacters}"; 40 | } 41 | } 42 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Streaming/Level2/Messages/IOrderAddUpdateSummaryMessage.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using IQFeed.CSharpApiClient.Streaming.Level2.Enums; 3 | 4 | namespace IQFeed.CSharpApiClient.Streaming.Level2.Messages 5 | { 6 | public interface IOrderAddUpdateSummaryMessage 7 | { 8 | /// 9 | /// Level 2 Message Type 10 | /// 11 | Level2MessageType MessageType { get; } 12 | 13 | /// 14 | /// The Security's Stock Symbol 15 | /// 16 | string Symbol { get; } 17 | 18 | /// 19 | /// The unique (per symbol) order identifier for this symbol. 20 | /// Only used in Market By Order messages. 21 | /// Will be blank for Nasdaq Level 2 messages 22 | /// 23 | UInt64 OrderId { get; } 24 | 25 | /// 26 | /// Market Maker ID - Only used for Nasdaq Level 2 messages. 27 | /// Will be blank for Market By Order Messages. 28 | /// 29 | string MMID { get; } 30 | 31 | /// 32 | /// Buy or Sell side 33 | /// 34 | Level2Side Side { get; } 35 | 36 | /// 37 | /// The price value of the price level that was added/updated 38 | /// 39 | double Price { get; } 40 | 41 | /// 42 | /// The size of this order 43 | /// 44 | int Size { get; } 45 | 46 | /// 47 | /// Used to position orders of the same price and side. Priority ranks from lowest to highest. 48 | /// 49 | UInt64 OrderPriority { get; } 50 | 51 | /// 52 | /// Number of places of decimal precision for the price field 53 | /// 54 | int Precision { get; set; } 55 | 56 | /// 57 | /// The time of this order 58 | /// 59 | TimeSpan OrderTime { get; } 60 | 61 | /// 62 | /// The date of this order 63 | /// 64 | DateTime OrderDate { get; } 65 | 66 | DateTime OrderDateTime { get; } 67 | bool Equals(object obj); 68 | int GetHashCode(); 69 | string ToString(); 70 | } 71 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Streaming/Level2/Messages/IOrderDeleteMessage.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using IQFeed.CSharpApiClient.Streaming.Level2.Enums; 3 | 4 | namespace IQFeed.CSharpApiClient.Streaming.Level2.Messages 5 | { 6 | public interface IOrderDeleteMessage 7 | { 8 | /// 9 | /// Level 2 Message Type 10 | /// 11 | Level2MessageType MessageType { get; } 12 | 13 | /// 14 | /// The Security's Stock Symbol 15 | /// 16 | string Symbol { get; } 17 | 18 | /// 19 | /// The unique (per symbol) order identifier for this symbol. 20 | /// Only used in Market By Order messages. 21 | /// Will be blank for Nasdaq Level 2 messages 22 | /// 23 | UInt64 OrderId { get; } 24 | 25 | /// 26 | /// Buy or Sell side 27 | /// 28 | Level2Side Side { get; } 29 | 30 | /// 31 | /// The time of this order 32 | /// 33 | TimeSpan OrderTime { get; } 34 | 35 | /// 36 | /// The date of this order 37 | /// 38 | DateTime OrderDate { get; } 39 | 40 | DateTime OrderDateTime { get; } 41 | bool Equals(object obj); 42 | int GetHashCode(); 43 | string ToString(); 44 | } 45 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Streaming/Level2/Messages/IPriceLevelDeleteMessage.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using IQFeed.CSharpApiClient.Streaming.Level2.Enums; 3 | 4 | namespace IQFeed.CSharpApiClient.Streaming.Level2.Messages 5 | { 6 | public interface IPriceLevelDeleteMessage 7 | { 8 | /// 9 | /// Level 2 Message Type 10 | /// 11 | Level2MessageType MessageType { get; } 12 | 13 | /// 14 | /// The Security's Stock Symbol 15 | /// 16 | string Symbol { get; } 17 | 18 | /// 19 | /// Buy or Sell side 20 | /// 21 | Level2Side Side { get; } 22 | 23 | /// 24 | /// The price value of the price level that was deleted 25 | /// 26 | double Price { get; } 27 | 28 | /// 29 | /// The time of this order 30 | /// 31 | TimeSpan Time { get; } 32 | 33 | /// 34 | /// The date of this order 35 | /// 36 | DateTime Date { get; } 37 | 38 | DateTime DateTime { get; } 39 | bool Equals(object obj); 40 | int GetHashCode(); 41 | string ToString(); 42 | } 43 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Streaming/Level2/Messages/IPriceLevelUpdateSummaryMessage.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using IQFeed.CSharpApiClient.Streaming.Level2.Enums; 3 | 4 | namespace IQFeed.CSharpApiClient.Streaming.Level2.Messages 5 | { 6 | public interface IPriceLevelUpdateSummaryMessage 7 | { 8 | /// 9 | /// Level 2 Message Type 10 | /// 11 | Level2MessageType MessageType { get; } 12 | 13 | /// 14 | /// The Security's Stock Symbol 15 | /// 16 | string Symbol { get; } 17 | 18 | /// 19 | /// Buy or Sell side 20 | /// 21 | Level2Side Side { get; } 22 | 23 | /// 24 | /// The price value of the price level that was added/updated 25 | /// 26 | double Price { get; } 27 | 28 | /// 29 | /// The total size of all orders at this price level 30 | /// 31 | int Size { get; } 32 | 33 | /// 34 | /// The total number of orders at this price level 35 | /// 36 | int OrderCount { get; } 37 | 38 | /// 39 | /// Number of places of decimal precision for the price field 40 | /// 41 | int Precision { get; set; } 42 | 43 | /// 44 | /// The time of the most current order that affected this price level 45 | /// 46 | TimeSpan Time { get; } 47 | 48 | /// 49 | /// The date of the most current order that affected this price level 50 | /// 51 | DateTime Date { get; } 52 | 53 | DateTime OrderDateTime { get; } 54 | bool Equals(object obj); 55 | int GetHashCode(); 56 | string ToString(); 57 | } 58 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Streaming/Level2/Messages/IUpdateSummaryMessage.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace IQFeed.CSharpApiClient.Streaming.Level2.Messages 4 | { 5 | public interface IUpdateSummaryMessage 6 | { 7 | string Symbol { get; } 8 | string MMID { get; } 9 | double Bid { get; } 10 | double Ask { get; } 11 | int BidSize { get; } 12 | int AskSize { get; } 13 | TimeSpan BidTime { get; } 14 | DateTime Date { get; } 15 | string ConditionCode { get; } 16 | TimeSpan AskTime { get; } 17 | char BidInfoValid { get; } 18 | char AskInfoValid { get; } 19 | char EndOfMessageGroup { get; } 20 | } 21 | } -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Streaming/Level2/Messages/MarketMakerNameMessage.cs: -------------------------------------------------------------------------------- 1 | using IQFeed.CSharpApiClient.Extensions; 2 | 3 | namespace IQFeed.CSharpApiClient.Streaming.Level2.Messages 4 | { 5 | public class MarketMakerNameMessage 6 | { 7 | public MarketMakerNameMessage(string mmid, string description) 8 | { 9 | MMID = mmid; 10 | Description = description; 11 | } 12 | 13 | public string MMID { get; private set; } 14 | public string Description { get; private set; } 15 | 16 | public static MarketMakerNameMessage Parse(string message) 17 | { 18 | var values = message.SplitFeedMessage(); 19 | var mmid = values[1]; 20 | var description = values[2]; 21 | 22 | return new MarketMakerNameMessage(mmid, description); 23 | } 24 | 25 | public override bool Equals(object obj) 26 | { 27 | return obj is MarketMakerNameMessage message && 28 | MMID == message.MMID && 29 | Description == message.Description; 30 | } 31 | 32 | public override int GetHashCode() 33 | { 34 | unchecked 35 | { 36 | var hash = 17; 37 | hash = hash * 29 + MMID.GetHashCode(); 38 | hash = hash * 29 + Description.GetHashCode(); 39 | return hash; 40 | } 41 | } 42 | 43 | public override string ToString() 44 | { 45 | return $"{nameof(MMID)}: {MMID}, {nameof(Description)}: {Description}"; 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/IQFeed.CSharpApiClient/Streaming/Level2/Messages/PriceLevelOrderMessage.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | using IQFeed.CSharpApiClient.Streaming.Level2.Enums; 7 | 8 | namespace IQFeed.CSharpApiClient.Streaming.Level2.Messages 9 | { 10 | /// 11 | /// This message is actually the same format as the OrderAddUpdateSummaryMessage 12 | /// 13 | public class PriceLevelOrderMessage : OrderAddUpdateSummaryMessage 14 | { 15 | public PriceLevelOrderMessage( 16 | Level2MessageType messageType, 17 | string symbol, 18 | UInt64 orderId, 19 | string mmid, 20 | Level2Side side, 21 | double price, 22 | int size, 23 | UInt64 orderPriority, 24 | int precision, 25 | TimeSpan orderTime, 26 | DateTime orderDate) : base(messageType, symbol, orderId, mmid, side, price, size, orderPriority, precision, orderTime, orderDate) 27 | { 28 | } 29 | 30 | public new static PriceLevelOrderMessage Parse(string message) 31 | { 32 | var messageParsed = OrderAddUpdateSummaryMessage.Parse(message); 33 | return new PriceLevelOrderMessage( 34 | messageParsed.MessageType, 35 | messageParsed.Symbol, 36 | messageParsed.OrderId, 37 | messageParsed.MMID, 38 | messageParsed.Side, 39 | messageParsed.Price, 40 | messageParsed.Size, 41 | messageParsed.OrderPriority, 42 | messageParsed.Precision, 43 | messageParsed.OrderTime, 44 | messageParsed.OrderDate 45 | ); 46 | } 47 | } 48 | } 49 | --------------------------------------------------------------------------------