Autospreader
Synthetic spread definitions are treated as instruments. Before you can launch your synthetic spread, you first need to fetch its definition as detailed in Working with Instruments. Specifically, you follow the same steps as you would to fetch an exchange native instrument, except you:
- Set the market name to "ASE".
- Set the product type to "Synthetic".
- Set the product name to "ASE".
- Set the alias to the user-defined name associated with the synthetic spread.
Fetching Autospreader Spread Definitions
The following code snippet demonstrates how to fetch the list of all Autospreader spread definitions.
InstrumentCatalogSubscription spreadCatalog_ = null;
public void SubscribeSpreadDefinitions()
{
if (spreadCatalog_ is null)
{
spreadCatalog_ = new InstrumentCatalogSubscription(Product.Autospreader,
m_callback_disp);
spreadCatalog_.OnData += OnSpreadDefinitionNotification;
spreadCatalog_.Start();
}
}
public void OnSpreadDefinitionNotification(object sender, InstrumentCatalogEventArgs e)
{
Console.WriteLine("OnSpreadDefinitionNotification " + e?.Event + " " + e?.Message);
switch (e.Event)
{
case ProductDataEvent.Found:
Console.WriteLine("Here are all the current spread definitions");
foreach (var sp in e.InstrumentCatalog.InstrumentList)
{
Console.WriteLine("Spread " + sp.Name);
}
break;
case ProductDataEvent.InstrumentDeleted:
foreach (var sp in e.Deleted)
{
Console.WriteLine("Spread " + sp.Name + " was deleted.");
}
break;
case ProductDataEvent.InstrumentUpdated:
foreach (var sp in e.Updated)
{
Console.WriteLine("Spread " + sp.Name + " was updated.");
}
break;
case ProductDataEvent.InstrumentCreated:
foreach (var sp in e.Added)
{
Console.WriteLine("Spread " + sp.Name + " was created.");
}
break;
}
}
Once you have the instrument corresponding to your spread definition, you can subscribe for market data and route orders for these instruments by following the same steps as you would for an exchange native instrument.
Note: As Autospreader orders are filled, you will receive fill messages for each leg order as well as fill messages for the parent order. These parent fill messages will have an ExecType of ‘Trade’ and an OrdStatus of ‘PartiallyFilled’. When the Autospreader order is fully filled, you will receive a deletion event with an ExecType of ‘Canceled’ and an OrdStatus of ‘Filled’. It is done in this manner to account for possible overfill scenarios when quoting more than one leg.
Creating Autospreader Spread Definitions
You can also create new Autospreader spread definitions from scratch as follows.
public void Test_CreateSpread()
{
SubscribeSpreadDefinitions();
Instrument newInst;
var spdetail = new SpreadDetails("my.nettest");
spdetail.Color = System.Drawing.Color.GreenYellow;
spdetail.PricingModel = PricingModel.Implied;
InstrumentLookup leg1Lookup = new InstrumentLookup(tt_net_sdk.Dispatcher.Current, MarketId.CME, ProductType.Future, "GE", "GE Jun23");
InstrumentLookup leg2Lookup = new InstrumentLookup(tt_net_sdk.Dispatcher.Current, MarketId.CME, ProductType.Future, "GE", "GE Sep23");
if ((leg1Lookup.Get() == ProductDataEvent.Found) && (leg2Lookup.Get() == ProductDataEvent.Found))
{
var leg1 = new SpreadLegDetails(leg1Lookup.Instrument, 1, 1.0M);
leg1.ActiveQuoting = true;
leg1.IsLeanIndicative = false;
leg1.MinLeanQty = "ThisLeg.DisclosedRemainingQuantity";
spdetail.AppendLeg(leg1);
var leg2 = new SpreadLegDetails(leg2Lookup.Instrument, -1, -1.0M);
leg2.ActiveQuoting = true;
leg2.IsLeanIndicative = false;
leg2.MinLeanQty = "ThisLeg.DisclosedRemainingQuantity";
spdetail.AppendLeg(leg2);
ASReturnCodes rtnCode;
newInst = AutospreaderManager.AddSpreadDetails(spdetail, out rtnCode);
if (newInst is null)
{
Console.WriteLine("unable to add new spread. " + spdetail.Name);
}
else
{
Console.WriteLine("Created new spread. " + newInst.Name + " key:" + newInst.Key);
}
Console.WriteLine("Add return: " + rtnCode);
}
}
Once you have created the Autospreader spread definition, you can manipulate it as demonstrated in the code snippets below.
// Deleting an Autospreader spread definition
public void Test_DeleteSpread()
{
SubscribeSpreadDefinitions();
InstrumentLookup spreadLookup = new InstrumentLookup(tt_net_sdk.Dispatcher.Current, MarketId.ASE, ProductType.Synthetic, Product.Autospreader.Alias, "my.nettest");
if (spreadLookup.Get() == ProductDataEvent.Found)
{
Console.WriteLine("Attempting to delete spread instrument." + spreadLookup.Alias);
SpreadDetails details = spreadLookup.Instrument.GetSpreadDetails();
ASReturnCodes rtnCode = AutospreaderManager.DeleteSpreadDetails(details);
Console.WriteLine("Delete return: " + rtnCode);
}
else
{
Console.WriteLine("Unable to find spread instrument." + spreadLookup.Alias);
}
}
// Changing the instrument of an existing Autospreader spread definition
public void Test_ModifySpread()
{
InstrumentLookup spreadLookup = new InstrumentLookup(tt_net_sdk.Dispatcher.Current, MarketId.ASE, ProductType.Synthetic, Product.Autospreader.Alias, "my.nettest");
if (spreadLookup.Get() == ProductDataEvent.Found)
{
SpreadDetails sp = spreadLookup.Instrument.GetSpreadDetails();
Console.WriteLine("Found spread instrument." + sp.Name + " (" +
spreadLookup.Instrument.InstrumentDetails.Version + ")");
InstrumentLookup newLegLookup = new InstrumentLookup(tt_net_sdk.Dispatcher.Current,
MarketId.CME, ProductType.Future, "6A", "6A Mar22");
if (newLegLookup.Get() == ProductDataEvent.Found)
{
SpreadLegDetails leg1 = sp.GetLeg(0);
leg1.Instrument = newLegLookup.Instrument;
sp.Updateleg(0, leg1);
ASReturnCodes rtnCode;
Instrument newSpreadInst = AutospreaderManager.UpdateSpreadDetails(sp, out rtnCode);
sp = newSpreadInst.GetSpreadDetails();
Console.WriteLine("Update to find spread instrument." + sp.Name + " (" +
newSpreadInst.InstrumentDetails.Version + ")");
}
}
else
{
Console.WriteLine("Unable to find spread instrument." + spreadLookup.Alias);
}
}
There are methods to get/set the leg accounts. # To set the leg account by using the Account Object, use SetLegAccount(index, Account object)
Assigning Rules to a Spread
Retrieve a list of available spread rules using AutospreaderManager.GetSpreadRules(). A rule can be located in this global collection of available rules and assigned to a spread. Then the rule can be configured on a leg by leg basis.
Use the following sample code as a guide.
InstrumentLookup spreadLookup = new InstrumentLookup(tt_net_sdk.Dispatcher.Current, MarketId.ASE, ProductType.Synthetic,
Product.Autospreader.Alias, spreadName);
if (spreadLookup.Get() == ProductDataEvent.Found)
{
SpreadDetails details = spreadLookup.Instrument.GetSpreadDetails();
var rules = AutospreaderManager.GetSpreadRules();
SpreadRule ttRule;
if (rules.TryGetValue("(TT) Minimum Increment Quote", out ttRule))
{
// rule exists so it can be use but make sure it is not aleady assigned
// since a rule can only be attached once to a spread
var existingRule = details.GetRule(ttRule.Name);
if (existingRule is null)
details.AppendRule(ttRule);
// change the rule default values on second leg
var leg1 = details.GetLeg(1);
// enable using the rule name
leg1.EnableRule(ttRule.Name, true);
leg1.SetRuleCustomVariable(ttRule.Name, "minIncrement", 6);
// disable the default values on first leg
var leg0 = details.GetLeg(0);
// enable using the rule index
leg0.EnableRule(0, false);
// save the changes
ASReturnCodes retCode = ASReturnCodes.FailToSave;
AutospreaderManager.UpdateSpreadDetails(details, out retCode);
if (retCode == ASReturnCodes.Success)
Console.WriteLine("Successfull updated " + spreadLookup.Instrument.InstrumentDetails.Name);
else
Console.WriteLine("FAILED to updated " + spreadLookup.Instrument.InstrumentDetails.Name);
}
}
Setting the Account on Different Legs of the Spread
There are three (3) methods to get/set the account on the different legs of the spread:
- To set the leg account by using the Account Object, use SetLegAccount (index, Account Object),
- To set the leg account by using the Account Name, use SetLegAccountName (index, accountname) .
- To get the account for the Leg, you can use the method LegAccount (index).
Note: When setting the value for index, remember that the value begins with 0. So to set the account on the first leg, set index equal to 0, the second leg, index equals 1 and so on.