Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

Table of Contents

Preface

FIXEdge offers solution for Business Rules purposed to provide routing, transferring, and data manipulations for FIX messages that go through the Business Layer of FIXEdge. See BL Scripting with JavaScript for more information.

Changing field values in repeating groups using JavaScript

This example describes how to change the Party Role (452) 's value from '1' (Executing Firm) to '17' (Contra Firm) in Execution Report (35=8).

...

The rule on the call of the JavaScript. Condition section sets up the condition for filtering messages by field MsgType (35) = 8. 

Code Block
languagexml
titleBL_Config.xml
<Rule Description="Save Parties for every incoming Execution Report (35=8)">
	<Source Name=".*" />
		<Condition>
		    	<MsgType>
       				<Val>8</Val>
		    	</MsgType>
		</Condition>
		<Action>
			<Script Language="JavaScript" FileName ="updatePartyRole.js"/>
			<!-- Do other necessary transformations and actions-->
			<!-- ... -->
		</Action>
</Rule>
Info

See Rule element for more information

JavaScript

Further, use JavaScript "updatePartyRole.js" on repeating group transformation:

...

Storing repeating groups in Database

This example describes how to write the values from the Parties repeating group in Trade Capture Report (35=AE) to specific DB columns.

Image Modified

History Configuration

It is necessary to create the History definition in the Business Layer Configuration file and to register all the fields that are in the database table and in the order in which they are registered in the database.

...

Code Block
languagexml
titleBL_Config.xml
<Rule Description="Save Parties for every incoming AE message">
	<Source Name=".*" />
	<Condition>
		<EqualField Field="35" Value="AE" />
	</Condition>
	<Action>
		<Script Language="JavaScript" FileName="TrdCapt.js" />
	</Action>
</Rule>
Info

See Rule element for more information

JavaScript

JavaScript "TrdCapt.js" for storing in a DB

Code Block
languagejs
titleTrdCapt.js
tags = new Array(447, 452); 		//In this array, we assign non-key tag numbers, below which the loop will go through this array with getStringField.
partyKey = new Array(); 		    //An array in which the key fields 571 and 448 will be stored
partyKey.push(getStringField(571)); //We write down the first part of the key. In this example, this is TradeReportID

hndl = getGroup(453);
groupSize = getNumField(453);
if (null != groupSize  and  isGroupValid(hndl)) 
{
	for (i = 0; i < groupSize; ++i) 
	{
		partyData = new Array(); 		// An array for data to be stored in db. the values of the 447 and 452 tags
		entry = i;
		partyKey.push(getStringField(hndl, i, 448)); 			//Record the second part of the key, PartyID
		if (null == getRecordFromHistory("Parties", partyKey))  //Check if there is already such an entry in the database
		{ 												
			for (j = 0; j < tags.length; ++j)                   // go through all fields to be stored.
			{ 													// 
				val = getStringField(hndl, i, tags[j]); 
				if (undefined == val) val = ""; 				// missing tag = "", In the database for non-key fields it is desirable to enable write NULL
				partyData.push(val); 
			}				       
			saveToHistory("Parties", partyKey, partyData, ""); 		// Save records to the database
		} 
		else
		{ 												
			//If such a record already exists in the database, then we write a notification and do nothing.
			print("Do nothing. Party duplicate has found in DB for " + partyKey); 
		}
	}
}
Info

Messages with the same TradeReportID (571) and PartyID (448) tags are considered as duplicates and are filtered.

For changing this behavior, KeyFields in History configuration should be modified/extended

Removing block from a repeating groups

For removing repeating group block we recommend the following steps:

  1. Clear all fields from a group entry.
  2. Copy all fields from the last group entry.
  3. Resize group, i.e. set a new group size value to a specific tag.

Please note that this approach has certain limitations:

  • Validation for repeating groups checks should be enabled. Messages with undefined tags and unexpected structure should be rejected or skipped.
  • All possible fields should be handled in JavaScript. Unexpected tags should be restricted in fix dictionaries. Otherwise, JavaScript would make a mess with tags.

BL_Config.xml

The rule on the call of the JavaScript for removing a block from a repeating group.

Code Block
languagexml
titleBL_Config.xml
<?xml version="1.0" encoding="UTF-8"?>
<FIXEdge>
 <BusinessLayer>
  <Rule>
   <Source>
    <FixSession SenderCompID=".*" TargetCompID="FIXEDGE"/>
   </Source>
   <Action>
    <Script Language="JavaScript" FileName="FIXEdge1/conf/removePartyRole17.js"/>
    <Send Name="RECIPIENT" />
   </Action>
  </Rule>
  
  <DefaultRule>
   <Action>
    <DoNothing/>
   </Action>
  </DefaultRule>
 </BusinessLayer>
</FIXEdge>

JavaScript 

Further, use JavaScript "removePartyRole17.js" for removing a block from a repeating group:

Code Block
languagejs
titleremovePartyRole17.js
partiesGroupTags = new Array( 448, 447, 452, 2376 ); 
 
partiesNoCount = getNumField(453);
partiesGrp = getGroup(453);
partiesNewSize = partiesNoCount;
print("[DEBUG] Initial message has " + partiesNoCount.toString() + " parties"); // for debugging
if (0 < partiesNoCount && isGroupValid(partiesGrp))
{
 var i = 0;
 while (i < partiesNoCount && partiesNewSize > 0)
 {
  var partyRole = getNumField(partiesGrp, i, 452);
  if (partyRole == 17)
  {
   // Copy the last block to this position field by field if it exist
   for (var n=0; n < partiesGroupTags.length; ++n) 
   {
    if( i == partiesNewSize-1) // is this is the last block
    {
     removeField(partiesGrp, i, partiesGroupTags[n]);
    }
    else 
    {
     // partiesNewSize-1 - reference to the last block.
     lastBlockField = getStringField(partiesGrp, partiesNewSize-1, partiesGroupTags[n])
     currentBlockField = getStringField(partiesGrp, i, partiesGroupTags[n])
     print("[DEBUG] Current value of Field " + partiesGroupTags[n].toString() + " :" + currentBlockField + "   Last Field: " + lastBlockField ); // for debugging
     if ( lastBlockField != null && currentBlockField != null) // swap values with last group and clean it.
     {
      swapFields(partiesGrp, partiesNewSize-1, partiesGroupTags[n], partiesGrp, i, partiesGroupTags[n]); 
      removeField(partiesGrp, partiesNewSize-1, partiesGroupTags[n]);
     }
     else if ( lastBlockField != null) 
     {
      setStringField(partiesGrp, i, partiesGroupTags[n], lastBlockField ); // assumed only field that can be converted to string can be absent
     }
     else //  currentBlockField != null and should be removed.
     {
      removeField(partiesGrp, i, partiesGroupTags[n]);
     }
    }
   }
   --partiesNewSize;
   print("[DEBUG] Removed party block #" + i.toString() + " New parties size = " + partiesNewSize.toString() ); // for debugging
   // Do not increment i because copied block could have partyRole = 17 and should be rechecked. 
  }
  else
  {
   ++i;
  }
 }
 if (partiesNewSize > 0)
 {
  setNumField(453, partiesNewSize);
 }
 else // remove parties if there are no entries;
 {
  removeField(453);
 } 
 print("[DEBUG] New parties size = " + partiesNewSize.toString()); // for debugging
}
Info

Messages with the same TradeReportID (571) and PartyID (448) tags are considered as duplicates and are filtered.

For changing this behavior, KeyFields in History configuration should be modified/extended


Example of transformation

Code Block
languagebash
Sent message:
8=FIX.4.4|9=230|35=D|49=FIXEdge|56=FIXCLIENT|34=2|52=20180409-09:43:06.927|11=E2017000000000000000001|453=3|448=TestValue1|447=D|452=11|448=TestValue2|447=D|452=122|448=XYZT|447=D|452=17|1=EPAM-TEST|55=USD/CNH|54=1|15=USD|58=Remove block #3 of 3|10=045|

Processed message:
8=FIX.4.4|9=208|35=D|49=FIXCLIENT|56=FIXEdge|34=2|52=20180409-09:43:06.930|11=E2017000000000000000001|453=2|448=TestValue1|447=D|452=11|448=TestValue2|447=D|452=122|1=EPAM-TEST|55=USD/CNH|54=1|15=USD|58=Remove block #3 of 3|10=140|