Indigo Pricing Service
Since investment banks spend a great deal of time (computational) pricing option, futures, bonds etc. We have been looking into using Indigo for a Pricing Service. What follows is some simplistic prototype code to get an idea of how such a service could work. What is not shown is the auto generated code from wsdlgen.exe
Pricing Service
using System;
using System.Collections.Generic;
using System.MessageBus;
using System.MessageBus.Services;
using System.Xml.Serialization;
namespace PricingServer
{
[DialogPortType(Name = "Pricing", Namespace = "http://www.someinvestmentbank.com/pricing")]
public class IndigoService
{
private object locker = new object();
private System.Collections.Generic.List<IPricingClient> clients = new List<PricingServer.IPricingClient>();
private System.Threading.Thread priceThread = null;
public IndigoService()
{
priceThread = new System.Threading.Thread(new System.Threading.ThreadStart(GeneratePrices));
priceThread.IsBackground = true;
priceThread.Start();
}
[ServiceMethod]
public string Greeting (string name)
{
return String.Format ("Hello, {0}!", name);
}
[ServiceMessage]
public void RegisterForPriceChanges(IPricingClient client)
{
lock (locker)
{
this.clients.Add(client);
}
Console.WriteLine("Client Registered");
}
private void GeneratePrices()
{
Random r = new Random((int)DateTime.Now.Ticks);
while (true)
{
lock (locker)
{
foreach (IPricingClient client in clients)
{
client.PriceUpdate(new PriceInfo("MSFT", r.Next(100), r.NextDouble(), r.NextDouble(), r.NextDouble()));
}
}
System.Threading.Thread.Sleep(2000);
}
}
}
public interface IPricingClient: IDialogPortTypeChannel
{
[ServiceMessage]
void PriceUpdate(PriceInfo priceChange);
}
[XmlType(Namespace = "http://www.someinvestmentbank.com/repos")]
public class PriceInfo
{
public string underlying;
public double price;
public double vega;
public double delta;
public double gamma;
public PriceInfo(string under, double price, double v, double d, double g)
{
this.underlying = under;
this.price = price;
this.vega = v;
this.gamma = g;
this.delta = d;
}
}
}
using System;
using System.MessageBus;
using System.MessageBus.Services;
//Note: This project has Indigo security disabled by default
//see the Indigo WindowsAuthRequestReply quickstart for an example
//of adding Indigo security to this application
namespace PricingServer
{
public class Host
{
[STAThread]
public static void Main (string[] args)
{
//The service environment needs to be loaded before it can be used.
//The Load method loads whatever configuration is available in the configuration file.
ServiceEnvironment environs = ServiceEnvironment.Load ();
ServiceManager sm=environs[typeof(ServiceManager)] as ServiceManager;
sm.ActivatableServices.Add (typeof(PricingServer.IndigoService));
//Only once the envrionment is open can connections be established.
environs.Open ();
Console.WriteLine ("Press enter to stop the services...");
Console.ReadLine ();
//Closing the environment forces cleanup of server and should not be forgotten.
environs.Close ();
}
}
}
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.messagebus>
<serviceEnvironments>
<serviceEnvironment name="main">
<port>
<identityRole>soap.tcp://localhost:46002/PricingService/</identityRole>
</port>
<!--
Note: This project has Indigo security disabled by default
see the Indigo WindowsAuthRequestReply quickstart for an example
of adding Indigo security to this application
-->
<remove name="securityManager" />
<policyManager>
<areUntrustedPolicyAttachmentsAccepted>true</areUntrustedPolicyAttachmentsAccepted>
<isPolicyReturned>true</isPolicyReturned>
</policyManager>
</serviceEnvironment>
</serviceEnvironments>
</system.messagebus>
</configuration>
Pricing Client
using System;
using System.MessageBus;
using System.MessageBus.Services;
using PricingServer;
using www_someinvestmentbank_com.pricing;
namespace PricingClient
{
public class Client
{
private ServiceEnvironment environment = null;
private IPricingChannel pricing = null;
[STAThread]
public static void Main(string[] args)
{
new Client().Run();
}
public void Run()
{
environment = ServiceEnvironment.Load();
try
{
environment.Open();
Uri serviceUri = new Uri("soap.tcp://localhost:46002/HelloService/");
System.MessageBus.Services.ServiceManager manager = environment[typeof(System.MessageBus.Services.ServiceManager)] as System.MessageBus.Services.ServiceManager;
pricing = (IPricingChannel)manager.CreateChannel(typeof(IPricingChannel), serviceUri);
Console.WriteLine(pricing.Greeting("Matt"));
pricing.RegisterForPriceChanges();
pricing.PriceUpdate += new Pricing_PriceUpdateEventHandler(eTrade_PriceUpdate);
Console.WriteLine("Waiting for Prices");
Console.ReadLine();
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
finally
{
environment.Close();
}
}
private void eTrade_PriceUpdate(IPricingChannel sender, PricingServer.PriceInfo priceChange)
{
Console.WriteLine(priceChange.underlying + " " + priceChange.price + " " + priceChange.gamma);
}
}
}
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.messagebus>
<serviceEnvironments>
<serviceEnvironment name="main">
<port>
<identityRole>soap.tcp://localhost:46003/HelloClient/</identityRole>
</port>
<remove name="securityManager" />
<policyManager>
<!-- CAUTION: Security disabled for demonstration purposes only. -->
<!-- Permits unsigned policy statements. Default requires signed policy statements -->
<areUntrustedPolicyAttachmentsAccepted>
true
</areUntrustedPolicyAttachmentsAccepted>
<isPolicyReturned>true</isPolicyReturned>
</policyManager>
</serviceEnvironment>
</serviceEnvironments>
</system.messagebus>
</configuration>
Obviously in a real pricing service, the GeneratePrices() function would do a little more than the above code, probably listening to a number of internal message bus feeds to retrieve the appropriate data, and then using something like Black-Scholes or some internally developed analytics