Unit RegionalsProxyUnit; { This is a minimum job to handle the alerts that were working in the pure TAL/ Delphi alert server. We could try to make this more general. But there doesn't seem to be much interest in this type of data. We are only tracking the bid and ask prices, only tracking them on the NYSE, and only tracking them for specific stocks. There is a seperate way to request this data vs NBBO, last print, etc. Presumably we'll only be watching this for stocks listed on the NYSE. } Interface Uses DataNodes, ProxyListenerBaseUnit, TalRegionals, MessageQueues, Classes; Type TRegionalsProxy = Class(TProxyListenerBase) Private FSymbol : String; RegionalsData : TTalRegionalBidAsk; FLastBid, FLastAsk : Double; Procedure Send(AlwaysSend : Boolean); Procedure NewRegionalsData; Constructor Create(Const Symbol : String; MessageQueue : TMessageQueue); Protected Procedure OnRestartOutput; Override; Class Function CreateNew(Data : String) : TDataNodeWithStringKey; Override; Public Class Procedure Find(Symbol : String; MessageQueue : TMessageQueue; OnChange : TThreadMethod; Out Node : TProxyListenerBase; Out Link : TDataNodeLink); End; Implementation Uses DataFormats, TalkWithServer, DebugOutput, StrUtils, SysUtils; Constructor TRegionalsProxy.Create(Const Symbol : String; MessageQueue : TMessageQueue); Var Link : TDataNodeLink; Begin Try FSymbol := Symbol; FMessageQueue := MessageQueue; Inherited Create; TTalRegionalBidAsk.Find(Symbol, NewRegionalsData, RegionalsData, Link); AddAutoLink(Link); If OutputStarted Then // If someone was already listening to this data node then we will have // data already, and we should push that to the user. Note that noone // is listening our NotifyListeners yet, so anyone who creates one of // these should immediately check their queue. OnRestartOutput Except On Ex : Exception Do Begin DebugOutputWindow.AddMessage(Ex, 'TL1Proxy.Create') End End End; Procedure TRegionalsProxy.Send(AlwaysSend : Boolean); Var SomethingSent : Boolean; Procedure SendField(Const NameOnWire : String; Current : Double; Var Last : Double); Var Encoded : String; Msg : TMessageToServer; Begin { SendField } If AlwaysSend Or (Current <> Last) Then Begin Last := Current; SetLength(Encoded, SizeOf(Double)); PDouble(PChar(Encoded))^ := Current; SetLength(Msg, 3); Msg[0].Name := WireCommand; Msg[0].Value := NameOnWire; Msg[1].Name := WireSymbol; Msg[1].Value := FSymbol; Msg[2].Name := WireBody; Msg[2].Value := Encoded; FMessageQueue.AddToQueue(Msg); SomethingSent := True End End; { SendField } Begin { TRegionalsProxy.Send } SomethingSent := False; If RegionalsData.Valid Then Begin SendField(WireNyseBidData, RegionalsData.Bid, FLastBid); SendField(WireNyseAskData, RegionalsData.Ask, FLastAsk) End Else Begin SendField(WireNyseBidData, 0.0, FLastBid); SendField(WireNyseAskData, 0.0, FLastAsk) End; If SomethingSent Then NotifyListeners End; { TRegionalsProxy.Send } Procedure TRegionalsProxy.NewRegionalsData; Begin If OutputStarted Then Send(False) End; Procedure TRegionalsProxy.OnRestartOutput; Begin Send(True) End; Class Function TRegionalsProxy.CreateNew(Data : String) : TDataNodeWithStringKey; Var Symbol : String; MessageQueue : TMessageQueue; Begin MessageQueue := TObject(PInteger(PChar(Data))^) As TMessageQueue; Symbol := MidBStr(Data, 5, MaxInt); //DebugOutputWindow.AddMessage('About to create: ' + Symbol); Result := Create(Symbol, MessageQueue) //DebugOutputWindow.AddMessage('Created: ' + Symbol); End; Class Procedure TRegionalsProxy.Find(Symbol : String; MessageQueue : TMessageQueue; OnChange : TThreadMethod; Out Node : TProxyListenerBase; Out Link : TDataNodeLink); Var Encoded : String; TempNode : TDataNodeWithStringKey; Begin //DebugOutputWindow.AddMessage('About to find: ' + Symbol); Encoded := 'XXXX' + Symbol; PInteger(PChar(Encoded))^ := Integer(MessageQueue); FindCommon(TRegionalsProxy, Encoded, OnChange, TempNode, Link); Node := TempNode As TProxyListenerBase //DebugOutputWindow.AddMessage('Found: ' + Symbol); End; End.