GF API keeps a collection of cached contracts. In order to send orders, request bars, see current prices, etc., we will need to fetch the relevant contracts from the server using Symbol Lookup.
There are two classes of contracts:
We can check which contracts are already cached like so:
private static void GFClient_OnLoginComplete(GF.Api.IGFClient client, GF.Api.Connection.LoginCompleteEventArgs e) { Console.WriteLine($"{client.Contracts.Get().Count} total contracts"); Console.WriteLine($"{client.Contracts.Base.Get().Count} total base contracts"); Console.WriteLine(); GF.Api.Contracts.IContract esContract = client.Contracts.Base.Get("ES")?.Contracts.First(); if (esContract != null) DisplayContract(esContract); GF.Api.Contracts.IContract esu18Contract = client.Contracts.Get("ESU18"); if (esu18Contract != null) DisplayContract(esu18Contract); } private static void DisplayContract(GF.Api.Contracts.IContract contract) { Console.WriteLine($"Contract: {contract.Symbol} - {contract.BaseSymbol}"); Console.WriteLine($"\tExpiration Date: {contract.ExpirationDate}"); Console.WriteLine($"\tTick Size: {contract.TickSize}"); Console.WriteLine($"\tContract Size: {contract.ContractSize:c}"); Console.WriteLine($"\tHas Options: {contract.HasOptions}"); Console.WriteLine(); }
Note |
---|
The first contract in BaseContracts.Contracts doesn't mean "front month contract". Why? Immediately after login, the Base Contract cache contains futures, futures options, and futures/options spreads, but it doesn't pre-load equity-related BaseContracts or Contracts. This is why we could get information about ES BaseContracts directly in previous example, but should check ESU18 for null in the last one. This rule has an exception: if there is any position or any order, GF API will pre-load involved Contracts. We shouldn't rely on it because, for example, orders may be expired at the end of day. |
Let's say we need to get a IContract instance of some particular symbol. We should send a Symbol Lookup request and handle its response via event:
private static SymbolLookupRequestID _esh18SymbolLookupRequestID; private void RegisterOnSymbolLookupReceived(GF.Api.IGFClient client) { client.Contracts.Lookup.SymbolLookupReceived += GFClient_OnSymbolLookupReceived; } private static void GFClient_OnLoginComplete(GF.Api.IGFClient client, GF.Api.Connection.LoginCompleteEventArgs e) { _esh18SymbolLookupRequestID = client.Contracts.Lookup.BySymbol("ESH18"); } private static void GFClient_OnSymbolLookupReceived(GF.Api.IGFClient client, GF.Api.Contracts.Lookup.SymbolLookupEventArgs e) { if (e.RequestID == _esh18SymbolLookupRequestID) { Console.WriteLine($"Symbol lookup for ESH18 returned {e.Contracts.Count} contracts"); foreach (var contract in e.Contracts) DisplayContract(contract); } }
Besides looking up a contract by its exact symbol, you can also download a group of contracts by filter. For example, let's download 10 electronic contracts that start with ES in symbol or description:
private static SymbolLookupRequestID _esRequestID; private static void GFClient_OnLoginComplete(GF.Api.IGFClient client, GF.Api.Connection.LoginCompleteEventArgs e) { _esRequestID = client.Contracts.Lookup.ByCriteria( new SymbolLookupRequestBuilder() .WithResultCount(10) .WithSymbol("ES", TextSearchMode.AnyInclusion) .WithExpression(new SymbolLookupExpressionBuilder() .Push(new ContractTypeCriterion(ContractType.Electronic)) .Push(new ContractGroupIDCriterion(client.Contracts.Groups.Get().First().ID)) .Push(SymbolLookupExpressionOperator.And) .Build()) .Build()); } private static void GFClient_OnSymbolLookupReceived(GF.Api.IGFClient client, GF.Api.Contracts.Lookup.SymbolLookupEventArgs e) { if (e.RequestID == _esRequestID) { Console.WriteLine($"Symbol lookup for electronic contracts that starts with ES in symbol or description returned {e.Contracts.Count} contracts"); foreach (var contract in e.Contracts) DisplayContract(contract); } }