1

I am developing a Quickfix/n initiator to be used with several counterparties, in the same instance, all using the same version of FIX (4.2 in this instance) but utilizing a unique messaging specification and I would like to use Intellisense/ReSharper to develop said initiator.

Previously I have used the generate.rb script to create source code from a modified FIX##.xml file but would like to use something like FIX42.DeutcheBank.xml, FIX42.CME.xml, FIX42.Whatever, to generate the source with the generate.rb ruby script or a modified version thereof so they can be parsed by IntelliSense/ReSharper and I am having issues because they all use "FIX.4.2" as begin strings and thus causes a compile error.

I know that I can just refer to a field/group via a key like Tags["BidForwardPointsCME"] or something similar with a DataDictionary but, as stated, I would like to be able to use IntelliSense/ReSharper and reference the message fields/groups with something like Quickfix.CounterParty.WhateverField and using the same dll.

I've banged my head against the internet for answers for 3-4 days with no luck - Is what I would like to do possible? If so, how would one go about it?

Hi in advance to Grant Birchmeier <:-]

Junkiebev
  • 143
  • 9
  • 1
    Who's Gary? And sorry, but I have zero experience with ReSharper. And I'm not fully sure I understand the question. How does a common "FIX.4.2" begin string cause a problem? (I assume you're talking about the `8=FIX.4.2` begin string.) – Grant Birchmeier Feb 05 '16 at 15:32
  • Sorry Grant - I wrote this on very little sleep! – Junkiebev Feb 05 '16 at 18:25
  • The problem is that two counterparties use the same FIX tag number but the data type is different. I'm wanting to use something like 'using QuickFix.SomeCounterParty;' rather than 'using QuickFix.FIX42;' Rather than editing the XML definition file and generating the FIX dll. Thanks and happy Friday. – Junkiebev Feb 05 '16 at 18:30

2 Answers2

1

For anyone that ever is trying to do this, the answer is pretty simple - probably not the most efficient but it works as far as I know.

the trick is to edit two ruby generation scripts (messages_gen.rb and generate.rb) and place the additional FIX specification XML file(s) in the spec/fix directory.

Assuming that you have a custom FIX xml file for Foo Exchange and that the Foo Exchange uses FIX 4.2, you need to name it FIX.xml (Example: FIXFooExchange.xml)

Next, you will have to override the FIX version in messages_gen.rb like so:

def self.gen_basemsg fixver, destdir
  beginstring = fixver
  if beginstring.match(/^FIX50/)
    beginstring = "FIXT11"
  end

  if beginstring.match(/^FIXFooExchange/)
    beginstring = "FIX42"
  end

Next you need to add your custom fix version to 6 method definitions in the generate.rb file.

Those methods are:

initialize

agg_fields

get_field_def

generate_messages

generate_csproj

generate_message_factories

Here are a few examples:

def initialize
  @fix40 = FIXDictionary.load spec('FIX40')
  @fix41 = FIXDictionary.load spec('FIX41')
  @fix42 = FIXDictionary.load spec('FIX42')
  @fix43 = FIXDictionary.load spec('FIX43')
  @fix44 = FIXDictionary.load spec('FIX44')
  @fix50 = FIXDictionary.load spec('FIX50')
  @fix50sp1 = FIXDictionary.load spec('FIX50SP1')
  @fix50sp2 = FIXDictionary.load spec('FIX50SP2')
  @fixFooExchange = FIXDictionary.load spec('FIXFooExchange')
  @src_path = File.join File.dirname(__FILE__), '..', 'QuickFIXn'
end

def get_field_def fld_name
# we give priority to latest fix version
  fld = merge_field_defs(
  @fix50sp2.fields[fld_name],
  @fix50sp1.fields[fld_name],
  @fix50.fields[fld_name],
  @fix44.fields[fld_name],
  @fixFooExchange.fields[fld_name],
  @fix43.fields[fld_name],
  @fix42.fields[fld_name],
  @fix41.fields[fld_name],
  @fix40.fields[fld_name]
)
End

Basically you just copy one line and replace the fix version with the customized exchange xml data dictionary name.

The class BeginString in FixValues.cs should be modified to look like this:

public class BeginString
{
    public const string FIXT11 = "FIXT.1.1";
    public const string FIX50  = "FIX.5.0";
    public const string FIX44  = "FIX.4.4";
    public const string FIX43  = "FIX.4.3";
    public const string FIXFooExchange = "FIX.4.2";
    public const string FIX42  = "FIX.4.2";
    public const string FIX41  = "FIX.4.1";
    public const string FIX40  = "FIX.4.0";
}

The Values.cs file contains a single class which should be changed to look like this:

public class Values
{
    public const string BeginString_FIXT11 = "FIXT.1.1";
    public const string BeginString_FIX50  = "FIX.5.0";
    public const string BeginString_FIX44  = "FIX.4.4";
    public const string BeginString_FIX43  = "FIX.4.3";
    public const string BeginString_FIXFooExchange = "FIX.4.2";
    public const string BeginString_FIX42  = "FIX.4.2";
    public const string BeginString_FIX41  = "FIX.4.1";
    public const string BeginString_FIX40  = "FIX.4.0";
}

Do those things and then run the generate.bat file and you should be able to reference namespaces via '.' rather than using the base FIX version. Here are some examples: using QuickFix.FIXFooExchange; using Message = QuickFix.Message;

QuickFix.FIXFooExchange.MessageFactory mF = new QuickFix.FIXFooExchange.MessageFactory();

and reference message properties like:

string customField = message.yourCustomFieldName.getValue().ToUpper();

instead of by

string customField = message["yourCustomFieldName"].getValue().ToUpper();

Lastly, you need to edit 2 .cs files: FixValues.cs and Values.cs

I've tested this pretty extensively and it seems to work but I would advise that you do testing before you put anything in production.

Junkiebev
  • 143
  • 9
  • 1
    I found that I had to specify the specific message factory when creating my initiator/acceptor like so: `initiator = new SocketInitiator(this, storeFactory, settings, logFactory, new QuickFix.FIXFooExchange.MessageFactory())` – Feem Aug 28 '17 at 16:20
0

So the problem is you want 1 QF initiator process to connect to several different counterparties where each session uses a separate data dictionary?

Don't you do this using DataDictionary=somewhere/FIX42.xml in the configuration file?

See also http://quickfixn.org/tutorial/configuration.html AppDataDictionary: This setting supports the possibility of a custom application data dictionary for each session.

rupweb
  • 3,052
  • 1
  • 30
  • 57
  • Yes - That would work but it would break IntelliSense. What I would like to do is generate, in addition to the FIX42/FIX43/FIX44/etc. references/types/etc, something like 'FIXDeutscheBank42' which intellisense would be able to parse in order to do things like autocompletion and type-guessing. I suspect that the only thing which would be a problem is that all of the various *special* fix data dictionaries use "FIX.4.2" (in this instance) as a begin string and this might be breaking an enum of some sort... Additional Namespaces/Classes might be a better way of saying it. – Junkiebev Feb 08 '16 at 04:17
  • Like Grant above I also have no IntelliSense / ReSharper experience, so I don't quite get it. When you say "FIXDeutscheBank42 which intellisense would be able to parse" do you mean pick up a particular data dictionary and parse the message formats within? Isn't there a way to configure QF to use a different data dictionary per session and that solves this problem? I mean, whatever you use, I can't see a way around not using tag `8=FIX.4.2` because, well, that's how FIX works, innit :) – rupweb Feb 08 '16 at 18:16