BL Scripting with JavaScript
- 1 Introduction
- 2 Business Rule scripting with JavaScript
- 2.1 JS FIX functionality
- 2.2 Error handling during script execution
- 2.3 Logging in JavaScript
- 2.3.1 print(<text>)
- 2.4 Operations with session
- 2.4.1 startSession(<sessionName>)
- 2.4.2 startSession(<senderCompId>,<targetCompId>)
- 2.4.3 startSession(<senderCompId>,<targetCompId>,<sessionQualifier>)
- 2.4.4 disconnectSession(<sessionName>,<reason>)
- 2.4.5 disconnectSession(<senderCompId>,<targetCompId>,<reason>)
- 2.4.6 disconnectSession(<senderCompId>,<targetCompId>,<sessionQualifier>,<reason>)
- 2.4.7 terminateSession(<sessionName>,<reason>)
- 2.4.8 terminateSession(<senderCompId>,<targetCompId>,<reason>)
- 2.4.9 terminateSession(<senderCompId>,<targetCompId>,<sessionQualifier>,<reason>)
- 2.5 Operations with messages across BL rules
- 2.5.1 setCtxKV(key,value)
- 2.5.2 getCtxKV(key,[defaultValue])
- 2.5.3 delCtxKV(key)
- 2.6 Operations with group fields
- 2.7 Bulk operations with group fields
- 2.8 Operations with message fields
- 2.8.1 removeField(<fieldTag>)
- 2.8.2 createReject(rejectType [, jAsFallback])
- 2.8.3 isSupportedField(<fieldTag>)
- 2.8.4 isSupportedField( <group handle> , <fieldTag>)
- 2.8.5 getNumField(<fieldTag>)
- 2.8.6 getNumField(<group handle>, <entry>, <fieldTag>)
- 2.8.7 getDateField(<fieldTag>, <format>)
- 2.8.8 getDateField(<group handle>, <entry>, <fieldTag>, <format>)
- 2.8.9 getStringField(<fieldTag>)
- 2.8.10 getStringField(<group handle>, <entry>, <fieldTag>)
- 2.8.11 getMStringField(<fieldTag>)
- 2.8.12 getMStringField(<group handle>, <entry>, <fieldTag>)
- 2.8.13 getRawDataField(<fieldTag>)
- 2.8.14 getRawDataField(<group handle>, <entry>, <fieldTag>)
- 2.8.15 setNumField(<fieldTag>, <new value>)
- 2.8.16 setDateField(<fieldTag>, <format>, <new value>)
- 2.8.17 setStringField(<fieldTag>, <new value>)
- 2.8.18 setMStringField(<fieldTag>, <new value>)
- 2.8.19 setRawDataField(<fieldTag>, <new value>)
- 2.8.20 setNumField(<group handle>, <entry>, <fieldTag>, <new value>)
- 2.8.21 setDateField(<group handle>, <entry>, <fieldTag>, <format>, <new value>)
- 2.8.22 setStringField(<group handle>, <entry>, <fieldTag>, <new value>)
- 2.8.23 setMStringField(<group handle>, <entry>, <fieldTag>, <new value>)
- 2.8.24 setRawDataField(<group handle>, <entry>, <fieldTag>, <new value>)
- 2.8.25 swapFields(<fieldTag1>, <fieldTag2>)
- 2.8.26 swapFields(<group handle field 1>, <entry field 1>, <fieldTag1>, <fieldTag2>)
- 2.8.27 swapFields(<group handle field 1>, <entry field 1>, <fieldTag1>, <group handle field 2>, <entry field 2>, <fieldTag2>)
- 2.9 Additional Date operations
- 2.10 Create date from current date or using passed arguments.
- 2.11 Convert from date to string
- 2.12 Get part of the date - year, month, day, etc.
- 2.12.1 getYear(<date handle>)
- 2.12.2 getMonth(<date handle>)
- 2.12.3 getWeek(<date handle>)
- 2.12.4 getDay(<date handle>)
- 2.12.5 getHour(<date handle>)
- 2.12.6 getMinutes(<date handle>)
- 2.12.7 getSec(<date handle>)
- 2.12.8 getMSec(<date handle>)
- 2.12.9 getNSec(<date handle>)
- 2.13 Set date part - year, month, day, etc.
- 2.13.1 setYear(<date handle>, <new val>)
- 2.13.2 setMonth(<date handle>, <new val>)
- 2.13.3 setWeek(<date handle>, <new val>)
- 2.13.4 setDay(<date handle>, <new val>)
- 2.13.5 setHour(<date handle>, <new val>)
- 2.13.6 setMinutes(<date handle>, <new val>)
- 2.13.7 setSec(<date handle>, <new val>)
- 2.13.8 setMSec(<date handle>, <new val>)
- 2.13.9 setNSec(<date handle>, <new val>)
- 2.14 Change date part with automatic date recalculation
- 2.14.1 changeYear(<date handle>, <new val>)
- 2.14.2 changeMonth(<date handle>, <new val>)
- 2.14.3 changeDay(<date handle>, <new val>)
- 2.14.4 changeHour(<date handle>, <new val>)
- 2.14.5 changeMinutes(<date handle>, <new val>)
- 2.14.6 changeSec(<date handle>, <new val>)
- 2.14.7 changeMSec(<date handle>, <new val>)
- 2.14.8 changeNSec(<date handle>, <new val>)
- 2.15 Routing functions
- 2.15.1 getSourceClientId()
- 2.15.2 getSourceSessionId()
- 2.15.3 getSourceSessionQualifier()
- 2.15.4 getSessionParser(<sessionName>)
- 2.15.5 getSessionParser(<senderCompID>, <targetCompID>)
- 2.15.6 getSessionParser(<senderCompId>, <targetCompId>, <sessionQualifier>)
- 2.15.7 isSessionActive(<Session Name>)
- 2.15.8 convert(<source protocol>, <target protocol>)
- 2.15.9 transform(<target protocol>, <target message type>)
- 2.15.10 getMsgBySeqNum(<SenderCompId>, <TargetCompId> , <SeqNum>)
- 2.15.11 getMsgBySeqNum(<SenderCompId>, <TargetCompId>, <SessionQualifier>, <SeqNum>)
- 2.15.12 send(<SenderCompID>, <TargetCompID>)
- 2.15.13 send(<SenderCompID>, <TargetCompID>,<SessionQualifier>)
- 2.15.14 send(<session source identifier>)
- 2.15.15 handler(<handler name>, <array of additional parameters>)
- 2.15.16 processNetStatusRequest()
- 2.15.17 createNotification (<category>, <reason>)
- 2.15.18 strategySend (<strategyName>)
- 2.15.19 strategyReject (<historyName>, <createBusinessRejectIfFailed>)
- 2.15.20 serializeMessage()
- 2.15.21 serializeMessage(<tagDelimiter>)
- 2.15.22 parseMessage(<msg>)
- 2.15.23 parseMessage(<msg>, <version>)
- 2.16 Error Handling Functions
- 2.16.1 getErrorCode()
- 2.16.2 getErrorText()
- 2.17 History functions
- 2.17.1 saveToHistory (<historyName>, <keyFields>, <commonFields>, <expireDateTime>)
- 2.17.2 updateHistory (<historyName>, <keyFields>, <commonFields>, <expireDateTime>)
- 2.17.3 saveOrUpdate(<historyName>, <keyFields>, <commonFields>, <expireDateTime>)
- 2.17.4 getFromHistory (<historyName>, <keyFields>, <columnName>)
- 2.17.5 getRecordFromHistory (<historyName>, <keyFields>)
- 2.17.6 removeRecordFromHistory (<historyName>, <keyFields>)
- 2.17.7 removeRecordFromHistoryByCompositeKey (<historyName>, <keyFields>)
- 2.18 Direct Database API functions
- 2.18.1 executeSQL(<text>)
- 2.19 Security functions
- 2.19.1 decryptString(<text>)
- 2.19.2 hashString(<text>)
- 2.20 Sequence numbers handling functions
- 2.20.1 setSessionSeqNums(<text>)
- 2.21 Predefined FIX date formats
Introduction
FIXEdge offers a flexible solution for Business Rules purposed to provide routing, transferring, and data manipulations for FIX messages that go through the Business Layer of FIXEdge. In addition to XML Rules, there are two ways to enhance the flexibility of message transferring and data manipulation. Those ways are scripting with JavaScript and XSLT. To use this feature properly, scripts should be written in one of the scripting languages and assigned to the Script instruction of Action section in a Business Rule.
The scripting subsystem gives the user the following advantages:
Saves time spent on business logic implementation
Flexibility and simplicity of modification
Does not bring a significant performance breakdown
FIXEdge uses SpiderMonkey JavaScript engine
Business Rule scripting with JavaScript
It is enough to mention that the script is a JavaScript in the Script tag, in order to run the script and do the proper transformations. This structure facilitates users with all the standard Javascript features and functionality. In addition to this, it enables users to use functions that provide access to the FIX message inside data and allows manipulations with fields and groups as well as whole FIX messages.
JS FIX functionality
A trivial example of a complete JS script for a business rule is shown below:
//take the value the 11th tag from the fix message and get the last 4 characters from it
//assign the new value for the tag 11 with format BBBBSSSSCCYYMMDD
//where
//BBBB - any 4 characters
//SSSS - last 4 characters from the old value of field 11
//CC - century
//YY- year
//MM - month
//DD - day
field_11 = getStringField(11);
if(field_11.length() < 4)
return;
last4 = field_11.slice(field_11.length() - 4);
currDate = getCurrentDateStr(YYYYMMDDUtc);
century = currDate.slice(1, 3);
century++;
result = "bbbb" + last4 + century + currDate.substr(3);
setStringField(11, result);Error handling during script execution
In case of syntax error in script - script execution will be terminated and failed. There is no way to handle syntax errors in script during script execution. User able to stop script execution using throw statement, the result in this case will be the same. User must be able to verify and handle logical errors using verification functions (like isNaN, isMessageValid(), etc) in condition statements.
Logging in JavaScript | |
print(<text>) | |
Example Code print (getCurrentDateStr(DATETIMEUtc)); | Execution of this line results in the following record in the application log: [NOTE] 20131023-08:28:53.651 [4320] [../FixEdge/conf/test.js] - JavaScript '../FixEdge/conf/test.js' output: 20131023-08:28:53 |
Operations with session | |
startSession(<sessionName>)Starts session "sessionName" | |
Example Code
| Starts the "StartByEvent" session |
startSession(<senderCompId>,<targetCompId>)Starts session where SenderCompID = "senderCompID" and TargetCompID = "targetCompID" | |
Example Code
| Starts a session where SenderCompID = "FIXEdge" and TargetCompID = "SimpleClient" |
startSession(<senderCompId>,<targetCompId>,<sessionQualifier>)Starts session where SenderCompID = "senderCompID",TargetCompID = "targetCompID",SessionQualifierValue = "sessionQualifier" | |
Example Code
| Starts a session where SenderCompID = "FIXEdge", TargetCompID = "SimpleClient", SessionQualifierValue = "Q1" |
disconnectSession(<sessionName>,<reason>)Disconnects session "sessionName" with reason "reason" | |
Example Code
| Disconnects the "DisconnectByEvent"session with the "Disconnect by message" reason |
disconnectSession(<senderCompId>,<targetCompId>,<reason>)Disconnects session where SenderCompID = "senderCompId" and TargetCompID = "targetCompId" with reason "reason" | |
Example Code
| Disconnects a session where SenderCompID = "FIXEdge" and TargetCompID = "SimpleClient" with reason "Disconnect by message" |
disconnectSession(<senderCompId>,<targetCompId>,<sessionQualifier>,<reason>)Starts session where SenderCompID = "senderCompID",TargetCompID = "targetCompID",SessionQualifierValue = "sessionQualifier" with reason "reason" | |
Example Code
| Disconnects a session where SenderCompID = "FIXEdge", TargetCompID = "SimpleClient", SessionQualifierValue = "Q1" with reason "Disconnect by message" |
terminateSession(<sessionName>,<reason>)Terminates session "sessionName" with reason "reason" | |
Example Code
| Terminates the "TerminateByEvent" session with the "Terminate by message" reason |
terminateSession(<senderCompId>,<targetCompId>,<reason>)Terminates session where SenderCompID = "senderCompID" and TargetCompID = "targetCompID" with reason "reason" | |
Example Code
| Terminates a session where SenderCompID = "FIXEdge" and TargetCompID = "SimpleClient" with reason "Terminate by message" |
terminateSession(<senderCompId>,<targetCompId>,<sessionQualifier>,<reason>)Terminates session where SenderCompID = "senderCompID",TargetCompID = "targetCompID",SessionQualifierValue = "sessionQualifier" | |
Example Code
| Terminates a session where SenderCompID = "FIXEdge", TargetCompID = "SimpleClient", SessionQualifierValue = "Q1" with reason "Terminate by message" |
Please note:
| |
Operations with messages across BL rules | |
setCtxKV(key,value) | |
Example Code
| The function sets the value to the key to transfer information about the message between different BL rules. If the function argument's type is not a string then the function throws an exception. |
getCtxKV(key,[defaultValue]) | |
Example Code
| The function gets the value of the key from another BL rule. If the function argument's type is not a string then the function throws an exception. If the default value is specified and there is a key stored in the context then the function returns the value stored for the key. If the specified key is not stored in the context:
|
delCtxKV(key) | |
Example Code
| The function deletes the value of the key. If the function's argument type is not a string then the function throws an exception. |
Operations with group fields | |
getGroup(<fieldTag>)Returns group handle for <fieldTag> group field | |
Example Code
| Gets a handle on group 78 and tests whether handle 78 is valid |
getGroup(<parentGroupHandle>, <entry>, <fieldTag>)Returns group handle for <fieldTag> group field from <parentGroupHandle>[<entry>] group Numeration of <entry> starts with 0. | |
Example Code
| Gets a handle on group 552 and tests whether the handle 552 is valid Gets a handle from the first record of 552 group on group 518 and tests whether the handle 518 is valid If the group handles are not identical, then increase the number of group 552 elements up to 4 |
removeField(<group handle>, <entry>, <fieldTag>)Removes field from group field Numeration of <entry> starts with 0. | |
Example Code
| Gets handle on group 78 and tests whether the handle 78 is valid Removes tag 79 from group 78 |
isGroupValid(<handle>)Returns true or false depending on the handle value | |
Example Code
| |
Bulk operations with group fieldsAvailable since FIXEdge 6.12.0 | |
bulkSetStringField(<group handle>, <starting entry>, <fieldTag>, <value>, [<max count>])Populates multiple entries' specific tag with constant value, or copies values from list, depending on value type. Numeration of <starting_entry> starts with 0. | |
Example Code 1
Example Code 2
| Example 1 Resizes group 268 (NoMDEntries) to 200 Gets a handle on group 268 (NoMDEntries) For entries 0 - 99 set tag 269 (MDEntryType) to '0' ('Bid') For entries 100 - 199 set tag 269 (MDEntryType) to '1' ('offer') This is equivalent to code: for (var i = 0; i < 100; i++) { Example 2 Creates a bid_qty_list variable with 5 elements and ask_qty_list with 3 elements Resizes group 268 (NoMDEntries) to 8 (total size of 2 lists) Gets a handle on group 268 (NoMDEntries) For entries 0-4, copy values from bid_qty_list, so that entry[i][271] = bid_qty_list[i] For entries 5-7, copy values from ask_qty_list, so that entry[5+i][271] = ask_qty_list[i] This is equivalent to code:
|
bulkSetStringFieldMapped(<group handle>, <starting entry>, <fieldTag>, <source list>, <key> [, <max count>])Populates multiple entries' specific tag by copying values from nested elements of source Javascript array. Numeration of <starting entry> starts with 0. Numeration of <source list> starts with 0. | |
Example Code
For alternative source structure
| Creates a bids variable with 5 nested pairs of elements, and ask_qty_list with 3 pairs. Resizes group 268 (NoMDEntries) to 8 (total size of 2 lists) Gets a handle on group 268 (NoMDEntries) For entries 0-4, copy Price(270) and Size(271) values from bids; For entries 5-7, copy Price(270) and Size(271) values from asks. This is equivalent to code: for (var i = 0; i < bid_qty_list.length; i++) { For alternative source structure
|
Operations with message fields | |
removeField(<fieldTag>)Removes field from message | |
Example Code removeField(58); | Removes tag 58 from the message |
createReject(rejectType [, jAsFallback])Creating reject | |
Example code: createReject("application", true); | createReject creates FIX Reject messages based on the specified type. It supports session-level rejects ( Note: Created Rejects are not automatically sent. Use send() to transmit the message.
|
isSupportedField(<fieldTag>)Returns true if the field is defined in the dictionary, i.e. it can be presented in the message. False means the tag is not expected in this message type | |
Example Code:
| The example shows how to remove tag 58 from the message if it is defined in the dictionary The script checks if tag 58 is defined for the message |
isSupportedField( <group handle> , <fieldTag>)Returns true if the field is defined in the dictionary for the specific group, i.e. it can be presented in the repeating group of the message. False means the tag is not expected in this specific group for this message type | |
Example Code
| The example shows how to remove non required tag 2376 from the Parties group entry #0. The script gets the repeating group 448 handle. |
getNumField(<fieldTag>)Returns numeric value of the <fieldTag> field | |
Example Code
| Returns a numeric value of field 78 |
getNumField(<group handle>, <entry>, <fieldTag>)Returns number value of the <fieldTag> field from group <group handle>[<entry>] Numeration of <entry> starts with 0. | |
Example Code
| Gets handle on group 552 and tests whether the handle 552 is valid Gets a numeric value of field 581 and assigns it to field 552 |
getDateField(<fieldTag>, <format>)Returns date handle to the <fieldTag> field value | |
Example Code
| Gets a date value of the field 64 in YYYYMMDD format |
getDateField(<group handle>, <entry>, <fieldTag>, <format>)Returns date handle to the <fieldTag> field value from group <group handle>[<entry>] Numeration of <entry> starts with 0. | |
Example Code
| Gets handle on group 778 and tests whether the handle 778 is valid Gets a date value of the field 779 in the YYYYMMDD format from the first element of group 778 |
getStringField(<fieldTag>)Returns string value of the <fieldTag> field | |
Example Code
| Returns a string value of field 78 |
getStringField(<group handle>, <entry>, <fieldTag>)Returns string value of the <fieldTag> field from group <group handle>[<entry>] Numeration of <entry> starts with 0. | |
Example Code
| Gets a handle on group 552 and tests whether handle 552 is valid Gets a string value of field 581 and assigns it to field 552 |
getMStringField(<fieldTag>)Returns array that contains multi string value of the <fieldTag> field | |
Example Code
| Gets a multiple string value of field 18 and assigns it to the tmp variable If the number of strings in the tmp variable equals to 3, then the value of the first string is assigned to field 55 and the value of the second string is assigned to field 65 |
getMStringField(<group handle>, <entry>, <fieldTag>)Returns array that contains multi string value of the <fieldTag> field from group <group handle>[<entry>] Numeration of <entry> starts with 0. | |
Example Code
| Gets a handle on group 552 and tests whether handle 552 is valid Gets a multiple string value of field 18 found in the first entry of group 552 and assigns it to the tmp variable |
getRawDataField(<fieldTag>)returns array that contains raw data value of the <fieldTag> field | |
Example Code
| Gets a raw data value of field 91 and assigns it to the tmp variable |
getRawDataField(<group handle>, <entry>, <fieldTag>)Returns array that contains raw data value of the <fieldTag> field from group <group handle>[<entry>] Numeration of <entry> starts with 0. | |
Example Code
| Gets a handle on group 5521 and tests whether handle 5521 is valid Gets a raw data value of field 91 found in the first entry of group 5521 and assigns it to the tmp variable |
setNumField(<fieldTag>, <new value>)assigns value <new value> to the <fieldTag> field as a NUMBER | |