/// <summary> /// The CreateMessage method creates a new instance of /// a specific FIX message in accordance with the message /// definition in the dictionaries associated with the /// specified FIX application layer version. The message /// that is created by this implementation of the method /// will also include a populated header and trailer that /// conforms to the header and trailer definition found in /// the specified session layer FIX version. /// </summary> /// <param name="sxVersion"> /// The session layer version of the FIX protocol that will /// be used to locate message definitions for the message that /// is to be created. /// </param> /// <param name="axVersion"> /// The application layer version of the FIX protocol that /// will be used to locate the message definition for the /// message that is to be created. /// </param> /// <param name="msgType"> /// The FIX message type of the message to create. /// </param> /// <returns> /// The resulting instance of a FIX message. /// </returns> public FixMessage CreateMessage(string sxVersion, string axVersion, string msgType) { FixMessage result = new FixMessage(); // REC: Determine if the MsgType field has already // been defined and maintain a reference so that it // can be restored after this is done: FixField fldMsgType = GetField(35); // REC: Assign the specified MsgType to the internal // field map so that it gets substituted: SetField(new FixField(35, msgType)); PopulateHdrElements(sxVersion, result); PopulateMsgElements(axVersion, msgType, result); PopulateTrlElements(sxVersion, result); // REC: Restore the previous value for the // message type, if one was present: if (fldMsgType != null) { SetField(fldMsgType); } else { // REC: The MsgType field was not present before // this call was made, so remove it: RemoveField(35); } return(result); }
/// <summary> /// The HandleSession_TestRequest method is invoked to /// handle a test request that has been received from the /// peer that the session is interacting with. /// </summary> /// <param name="msg"> /// The FIX test request received from the peer. /// </param> private void HandleSession_TestRequest(FixMessage msg) { if (_currentState == SessionStates.Session_Opened) { // REC: Dispatch the administrative message to the // session's callback handler: _handler.OnSessionRxAdmMessage(this, msg); // REC: Construct a response message to the test // request and dispatch it to the peer: FixMessage msgResponse = _fixAssembler.CreateMessage(_sxVersion, _axVersion, "0"); if (msgResponse != null) { // REC: Retrieve the test request token from // the incoming request and assign it to the // outbound response message: FixField fldTestReqID = msg.GetField(112); if (fldTestReqID != null) { if (!string.IsNullOrEmpty(fldTestReqID.Content)) { msgResponse.AddField(new FixField(112, fldTestReqID.Content)); } } Dispatch_AdmMessage(msgResponse); } } else { } }
public void OnSessionLogout(IVfxFixAppSession session, FixMessage msg) { FixField fixSCID = msg.Header.GetField(49); FixField fixTCID = msg.Header.GetField(56); Console.WriteLine(string.Format("FIX SERVER: {0} - LOGOUT.", fixSCID.Content)); }
public void OnSessionLogon(IVfxFixAppSession session, FixMessage msg) { FixField fixSCID = msg.Header.GetField(49); FixField fixTCID = msg.Header.GetField(56); Console.WriteLine(string.Format("FIX CLIENT: {0} - LOGON", fixSCID.Content)); System.Threading.ThreadPool.QueueUserWorkItem(HandleWork_SendMessages, session); }
/// <summary> /// The GetField method retrieves an instance of a field that /// has been configured in the assembler instance. /// </summary> /// <param name="tag"> /// The FIX tag of the field to retrieve. /// </param> /// <returns> /// The instance of the FIX field that corresponds to the /// supplied tag, or null if there is no match. /// </returns> public FixField GetField(int tag) { FixField result = null; if (_mapFields.ContainsKey(tag)) { result = _mapFields[tag]; } return(result); }
// REC: The PopulateQueue method is a recursive function // that loads all of the elements in a FixCollection into // an instance of a SrcField queue so that the validator // can then process all the elements sequentially: private void PopulateQueue(Queue <SrcField> queue, FixCollection elements) { foreach (IFixElement element in elements) { if (element is FixField) { FixField msgField = element as FixField; if (msgField != null) { // REC: Attempt to resolve the field's name // by retrieving it using it's tag: string fieldName = ResolveFieldName(msgField.Tag.ToString()); if (fieldName == null) { fieldName = "Unresolved"; } // REC: Create a new instance of SrcField that // represents the contents of this field: SrcField srcField = new SrcField(); srcField.Tag = msgField.Tag.ToString(); srcField.Name = fieldName; srcField.Value = msgField.Content; queue.Enqueue(srcField); } } else if (element is FixGroup) { FixGroup msgGroup = element as FixGroup; if (msgGroup != null) { string groupName = ResolveFieldName(msgGroup.Tag.ToString()); if (groupName == null) { groupName = "Unresolved"; } // REC: Create a new instance of SrcField that // represents the contents of the group: SrcField srcField = new SrcField(); srcField.Tag = msgGroup.Tag.ToString(); srcField.Name = groupName; srcField.Value = msgGroup.Content; queue.Enqueue(srcField); foreach (FixCollection instance in msgGroup.Instances) { PopulateQueue(queue, instance); } } } } }
/// <summary> /// The SetField method registers an instance of a field with /// the assembler. The assembler will use this field whenever /// it constructs a message that contains the field's tag. /// </summary> /// <param name="field"> /// The FIX field to register with the assembler. /// </param> public void SetField(FixField field) { if (!_mapFields.ContainsKey(field.Tag)) { _mapFields.Add(field.Tag, field); } else { _mapFields[field.Tag] = field; } }
/// <summary> /// Updates the FIX value within the input FIX fields for the currently selected strategy. /// </summary> /// <param name="fixTag">FIX tag whose value is to be updated.</param> /// <param name="value">New value for the FIX tag being updated.</param> /// <remarks>This method is used to update FIX tag values that are used within StrategyEdits using the FIX_ /// mechanism. Controls that are initialized using the FIX_ mechanism and parameter values within strategies /// are unaffected when invoking this method.</remarks> public void UpdateFixValue(FixField fixTag, string value) { if (InputFixValues == null) { return; } InputFixValues[fixTag] = value; if (ViewModel != null) { ViewModel.EvaluateAffectedStrategyEdits(this, fixTag); } }
/// <summary> /// Evaluates all the underlying <see cref="StrategyEdit_t"/>s and notifies any interested parties of change /// of state. /// </summary> /// <param name="inputValueProvider">Provider that providers access to any additional FIX field values that may /// be required in the Edit evaluation.</param> /// <returns>Summary state of all StrategyEdits after the evaluation.</returns> public bool EvaluateAffected(FixFieldValueProvider inputValueProvider, FixField fixField) { bool overallState = true; foreach (StrategyEditViewModel strategyEdit in this) { if (strategyEdit.Sources.Contains(Enum.GetName(typeof(FixField), fixField))) { overallState &= strategyEdit.Evaluate(inputValueProvider); } } return(overallState); }
/// <summary> /// The HandleSession_Logon method is invoked to handle /// a logon message that has been received from the peer /// session that this session is communicating with. /// </summary> /// <param name="msg"> /// The FIX logon message received from the peer. /// </param> private void HandleSession_Logon(FixMessage msg) { // REC: Ensure that we're in the appropriate state // to handle a logon message: if (_currentState == SessionStates.Session_Pending || _currentState == SessionStates.Session_Closed) { // REC: Retrieve the FIX SenderCompID of the peer // from the logon message: FixField fldSenderCompID = msg.Header.GetField(49); if (fldSenderCompID != null) { string rxSenderCompID = fldSenderCompID.Content; if (string.IsNullOrEmpty(rxSenderCompID)) { // HELP: Should the session send a reject message // in this case, given that the peer didn't send // its FIX SenderCompID, or should this throw an // argument exception? } // REC: Transition to the opened state: _currentState = SessionStates.Session_Opened; // REC: Notify the session's owner that the session // has received the logon response from the server: _handler.OnSessionLogon(this, msg); } else { // REC: Throw an exception since the session has not // yet been established and there will be no handler // at the application level that can deal with this: throw new ArgumentException("Logon message missing required field - SenderCompID."); } } else { // REC: Notify the session handler that an // administrative message has been received // from the peer session: _handler.OnSessionRxAdmMessage(this, msg); // REC: Throw an exception that indicates the // session is not in the appropriate state to // handle the received message: throw new InvalidOperationException("Session state invalid for received message."); } }
/// <summary> /// The AddMessage_Entrypoint method is the asynchronous /// entrypoint for processing add message requests that have /// been enqueued to the .NET thread pool through the instance /// of the sequencer that is associated with the database. /// </summary> /// <param name="state"> /// The instance of TaskDetails_Add that is associated with /// the asynchronous add message request being processed. /// </param> private void AddMessage_Entrypoint(object state) { TaskDetails_Add taskDetails = state as TaskDetails_Add; if (taskDetails != null) { FixField fldSequence = taskDetails.SessionMsg.Header.GetField(34); if (fldSequence != null) { // REC: Retrieve the message's text so that its // length can be assigned to its index entry: string msgText = taskDetails.SessionMsg.ToString(); // REC: Create an entry for the message in the // index file associated with the session: if (_mapSessions.ContainsKey(taskDetails.SessionId)) { SessionDetails details = _mapSessions[taskDetails.SessionId]; IndexEntry idxEntry = new IndexEntry(); idxEntry.msgOffset = details.MsgWriter.BaseStream.Position; idxEntry.msgLength = msgText.Length; idxEntry.msgSequence = int.Parse(fldSequence.Content); details.Index.Add(idxEntry); details.MsgWriter.Write(msgText.ToCharArray()); details.MsgWriter.Flush(); string idxLine = string.Format("{0}:{1}:{2}", idxEntry.msgSequence, idxEntry.msgOffset, idxEntry.msgLength); details.IdxWriter.WriteLine(idxLine.ToCharArray()); details.IdxWriter.Flush(); } } } }
/// <summary> /// Evaluates all strategy edits within the currently selected strategy. /// </summary> /// <param name="inputValueProvider">Provider that providers access to any additional FIX field values that may /// be required in the Edit evaluation.</param> /// <returns>Summary state of all StrategyEdits after the evaluation.</returns> public bool EvaluateAffectedStrategyEdits(IInitialFixValueProvider inputValueProvider, FixField updatedField) { FixFieldValueProvider additionalValues = inputValueProvider == null ? FixFieldValueProvider.Empty : new FixFieldValueProvider(inputValueProvider, _underlyingStrategy.Parameters); bool result = StrategyEdits.EvaluateAffected(additionalValues, updatedField); foreach (ControlViewModel control in Controls) { control.OnValueChangeCompleted(); } return(result); }
/// <summary> /// The HandleRxMessage method is invoked by the owner of an /// instance of a session to inform it that data has arrived /// from the peer system. /// </summary> /// <param name="mb"> /// The message block that contains the data received from /// the peer system the session is communicating with. /// </param> public void HandleRxMessage(VfxEngine.Ipc.VfxMsgBlock mb) { string content = Encoding.ASCII.GetString(mb.Buffer, 0, mb.Length()); VfxFixParserResult fpr = _fixParser.Parse(content, null, null, null); while (fpr.Status == VfxFixParserStatus.MsgComplete) { // REC: Adjust the read index in the message block // to compensate for the number of bytes parsed from // the incoming data stream: mb.RdIndex += fpr.Consumed; // REC: Crunch the message block to remove the data // that has already been parsed: mb.Crunch(); // REC: Reset the timestamp that is used to determine // when the last message was received from the peer: this._lastRxTicks = DateTime.Now.Ticks; // REC: Determine if the message is a session layer // message and process it accordingly: FixField fldMsgType = fpr.Message.Header.GetField(35); if (fldMsgType != null) { string strMsgType = fldMsgType.Content; if (!string.IsNullOrEmpty(strMsgType)) { switch (strMsgType) { case "A": // Received a FIX logon message: HandleSession_Logon(fpr.Message); break; case "0": // Received a FIX heartbeat message: HandleSession_Heartbeat(fpr.Message); break; case "1": // Received a FIX test request: HandleSession_TestRequest(fpr.Message); break; case "2": // Received a FIX resend request: HandleSession_Resend(fpr.Message); break; case "5": // Received a FIX logout message: HandleSession_Logout(fpr.Message); break; default: // Received a message that should be // routed to the session's owner: HandleSession_Message(fpr.Message); break; } } else { // REC: If the session's identity hasn't been // established yet, just throw an exception and // let the session's owner shut it down: if (_currentState == SessionStates.Session_Pending) { throw new ArgumentException("Initial message missing required field - FIX MsgType."); } else { // REC: The session has been established, so the // session can send a reject message: } } } else { } // REC: Attempt to parse another message from // the buffer of data that has been received: content = Encoding.ASCII.GetString(mb.Buffer, 0, mb.Length()); fpr = _fixParser.Parse(content, null, null, null); } // REC: If the parser couldn't extract a complete message // from the supplied buffer, determine what to do next: if (fpr.Status != VfxFixParserStatus.MsgComplete) { } }
/// <summary> /// The HandleSession_Logon method is invoked to handle /// a logon message that has been received from the peer /// session that this session is communicating with. /// </summary> /// <param name="msg"> /// The FIX logon message received from the peer. /// </param> private void HandleSession_Logon(FixMessage msg) { // REC: Ensure that we're in the appropriate state // to handle a logon message: if (_currentState == SessionStates.Session_Pending || _currentState == SessionStates.Session_Closed) { // REC: Retrieve the FIX SenderCompID of the peer // from the logon message: FixField fldSenderCompID = msg.Header.GetField(49); if (fldSenderCompID != null) { // REC: The SenderCompID from the peer becomes the // session's TargetCompID for outgoing messages: _fixTargetCompID = fldSenderCompID.Content; // REC: Now that the FIX SenderCompID of the peer // session is known, it is used to construct the // identifier for the session - used to retrieve // the session's details from the database: _sessionId = string.Format("{0}-{1}", _fixSenderCompID, _fixTargetCompID); // REC: Attempt to retrieve the session details // from the session database: if (_fixDatabase != null) { // REC: Note that once a session record is acquired // from the database, it must be released when it is // no longer needed by the session instance... _sessionRecord = _fixDatabase.AcquireSession(_sessionId); if (this._resetSequence == true) { _sessionRecord.RxSequence = 1; _sessionRecord.TxSequence = 1; } } // REC: Register the peer session's SenderCompID as // the TargetCompID for outgoing messages: _fixAssembler.SetField(new FixField(56, _fixTargetCompID)); // REC: Assemble the response message: FixMessage response = _fixAssembler.CreateMessage(_sxVersion, _axVersion, "A"); // REC: Handle the sequence number reset flag // if it is present in the logon message: FixField fieldReset = msg.GetField(141); if (fieldReset != null) { response.AddField(new FixField(141, "Y")); } // REC: Transition to the opened state: _currentState = SessionStates.Session_Opened; // REC: Notify the session's owner that the peer // session has sent the logon request: _handler.OnSessionLogon(this, msg); // REC: Dispatch the administrative message out // to the session's owner: Dispatch_AdmMessage(response); } else { // REC: Throw an exception since the session has not // yet been established and there will be no handler // at the application level that can deal with this: throw new ArgumentException("Logon message missing required field - SenderCompID."); } } else { // REC: Notify the session handler that an // administrative message has been received // from the peer session: _handler.OnSessionRxAdmMessage(this, msg); // REC: Throw an exception that indicates the // session is not in the appropriate state to // handle the received message: //throw new InvalidOperationException("Session state invalid for received message."); } }
// REC: Validate an instance of the FixMessage class against // the header/message/trailer definition in the dictionaries: public List <FixValidationResult> Validate(FixMessage msg) { List <FixValidationResult> result = new List <FixValidationResult>(); // REC: Build a queue of all of the FIX elements that // are contained in the message: Queue <SrcField> srcFields = new Queue <SrcField>(); // REC: Add the elements that are in the message's // header to the queue of source fields: PopulateQueue(srcFields, msg.Header); // REC: Add the elements that are in the message's // body to the queue of source fields: PopulateQueue(srcFields, msg.Content); // REC: Add the elements that are in the message's // trailer to the queue of source fields: PopulateQueue(srcFields, msg.Trailer); // REC: Create the MsgLayout structure that defines // the layout of a message as it is defined in the // configured FIX dictionaries: MsgLayout msgLayout = new MsgLayout(); // REC: The message layout's header entries are // copied from the cached list of entries that is // created when the validator is configured: foreach (FixValidationResult hdrEntry in _cachedHeader) { msgLayout.Header.Add(hdrEntry.Clone() as FixValidationResult); } // REC: The message layout's content entries are // only configured if the corresponding message // type can be found in the dictionaries: FixField fldMsgType = msg.Header.GetField(35); if (fldMsgType != null) { string strMsgType = fldMsgType.Content; foreach (FixDictionary dx in _settings.Dictionaries) { FixDxMessage dxMessage = dx.GetMessageByType(strMsgType); if (dxMessage != null) { // REC: Expand the list of elements contained // in the message's definition and populate the // message layout element list with them: FixDxCollection msgElements = dx.Resolve(dxMessage.Elements); foreach (IFixDxElement msgElement in msgElements) { msgLayout.Message.Add(CreateResult(msgElement)); } break; } } } // REC: the message layout's trailer entries are // copied from the cached list of entries that is // created when the validator is configured: foreach (FixValidationResult trlEntry in _cachedTrailer) { msgLayout.Trailer.Add(trlEntry.Clone() as FixValidationResult); } // REC: After the message layout has been defined // the validator can compare the content of the // source message to the layout definition: return(ProcessElements(srcFields, msgLayout)); }
public void OnSessionRxAppMessage(IVfxFixAppSession session, FixMessage msg) { FixField fixSCID = msg.Header.GetField(49); Console.WriteLine(string.Format("FIX SERVER: {0} SENT: {1}", fixSCID.Content, msg.ToString())); }