TargetID
is the NAME of the box
to where you sending message, if
you need to distinguish sessions
for multiple clients (I assume into
one server) just give each client
different SenderCompID
.
On your server you have to setup one session for each client.
Example for one server-client session:
On your server (INCA):
[SESSION]
BeginString=FIX.4.0
SenderCompID=INCA
TargetCompID=CLIENT1
On your client (CLIENT1):
[SESSION]
BeginString=FIX.4.0
SenderCompID=CLIENT1
TargetCompID=INCA
quickfixengine distinguishes session
(server-client connection) based on
those 3 values: (BeginString,
TargetCompID, SenderCompID)
When you send message you put your
comp id as sendercompid
and the
target to where you sending message
as targetcompid
. You specify
beginstring
based on the fix
version you wish to use to
communicate (FIX4.0
/FIX4.2
....).
Custom fields depends on what
exactly is required. FIX protocol
specifies custom fields those with
FieldID bigger than the reserved
range, so your custom fields can
start with FieldID 5000.
There are couple of options about
how to go about it. The simplest one
is to just use the numerical value
of message and add it to message (I
assume you use c++ but it's similar
with other languages).
Something like:
msg.setField(5000,"SomeValue");
This custom field will not be
validated automatically because FIX
does not know about it. FIX uses xml
files where each message and field
is specified.
There is a proper procedure to add a
new message to xml specs and then
regenerate quickfixengine code to
generate new field structures but so
far I did not need to do it.
message cracker is just a method
that takes pointer to generic
message and then it looks at the
message id (if I remember) and calls
appropriate handler.
It is one big if statement with lots
of string operations so sometimes
it's better to do the checking
yourself, but you should be okay to
use it.
This is how the method looks like, you'll get the idea:
void crack( const Message& message,
const FIX::SessionID& sessionID )
{
const std::string& msgTypeValue
= message.getHeader().getField( FIX::FIELD::MsgType );
if( msgTypeValue == "0" )
onMessage( (const Heartbeat&)message, sessionID );
else
if( msgTypeValue == "A" )
onMessage( (const Logon&)message, sessionID );
else
if( msgTypeValue == "1" )
onMessage( (const TestRequest&)message, sessionID );
else
You then generally implement the
appropriate method like for example
if you only care about
ExecutionReport
s you implement in
your code:
virtual void onMessage( ExecutionReport&, const FIX::SessionID& );
Then your application will get the
ExecutionReport
so that you can
process it. The onMessage
methods
for messages that you don't
implement simply do nothing and
return so message will never get to
your application.