Agent framework designed for FIX applications using quickfix-jruby.
Usage
Agent Types
Initiator
- Connects to an address hosting a fix session (FIX Client)
Acceptor
- Binds on an address to host a fix session (FIX Server)
Agent Definition
Inside your project, declare agents and connection information inside config/fix_agents.rb
like so:
PORT=5000
AgentFIX.session_defaults.merge! BeginString: "FIX.4.2", SocketAcceptPort: PORT, SocketConnectPort: PORT, SocketConnectHost: "localhost"
AgentFIX.define_acceptor :my_acceptor do |a|
a.default ={SenderCompID: "TW"}
a.session ={TargetCompID: "ARCA"}
end
AgentFIX.define_initiator :my_initiator do |i|
i.default ={SenderCompID: "ARCA"}
i.session ={TargetCompID: "TW"}
end
Usage
Configuration
In order to use Agent FIX, you must:
require 'agent_fix'
To use with cucumber, you must:
# env.rb
require 'agent_fix/cucumber'
require 'agent_fix/cucumber/report'
You can define a data dictionary using FIX spec:
FIXSpec.data_dictionary= quickfix.DataDictionary.new "path/to/FIX42.xml"
Configure inspection behavior to use combined admin & app messages (default is app-only):
AgentFIX.include_session_level = true
Getting Started
Start the FIX agents:
AgentFIX.start
at_exit {AgentFIX.stop}
When using cucumber, to clear message caches before each scenario:
Before do
sleep(0.5)
AgentFIX.reset
end
Scoping in cucumber steps
Agent FIX comes with a few features to assist in organizing larger tests, including the ability to scope incoming messages. As an example, taken from features/scope.feature
, first define your scope size with the expectation to receive a certain number of messages:
Then I should receive 3 messages on FIX with agent "my_initiator"
Your scope is now defined to 3 messages. Whenever you attempt to inspect a message by index, the locally defined scope will be used:
And the 2nd message should have the following:
| ClOrdID | "hello" |
| OrderID | "abc" |
| Symbol | "IBM" |
| OrdStatus | "PENDING_NEW" |
This will attempt to inspect the second message in the local scope. If you then said:
Then I should receive 4 messages on FIX with agent "my_initiator"
And the 2nd message should have the following:
| ClOrdID | "hello" |
| OrderID | "abc" |
| Symbol | "IBM" |
| OrdStatus | "PENDING_CANCEL" |
The inspection step, And the 2nd message should have the following
will be looking at the 5th message the agent has received since the scenario was started, or the 2nd message in the last defined scope. The first scope was defined to have 3 messages, the second defined to have 4, which means the second scope is defined as messages #4-7.
Scope inclusion
Scope inclusion is scope inspection without regard to order. Say the agent received the following FIX messages:
8=FIX.4.2|35=8|11=hello|17=123|37=abc|39=A|150=A|151=0|20=0|6=0|14=0|21=1|55=IBM|54=1|40=2|60=20090101-17:13:06.684|
8=FIX.4.2|35=8|11=hello|17=123|37=abc|39=0|150=0|151=0|20=0|6=0|14=0|21=1|55=IBM|54=1|40=2|60=20090101-17:13:06.684|
8=FIX.4.2|35=8|11=hello|17=123|37=abc|39=4|150=A|151=0|20=0|6=0|14=0|21=1|55=IBM|54=1|40=2|60=20090101-17:13:06.684|
8=FIX.4.2|35=8|11=hello|17=123|37=abc|39=2|150=A|151=0|20=0|6=0|14=0|21=1|55=IBM|54=1|40=2|60=20090101-17:13:06.684|
Define your scope:
Then I should receive 3 messages on FIX with agent "my_initiator"
Check for inclusion:
And the FIX messages should include a message with the following:
| ClOrdID | "hello" |
| OrderID | "abc" |
| Symbol | "IBM" |
| OrdStatus | "NEW" |
Message #2 has OrdStatus=NEW
, and matches the cucumber step, so this step will pass. If the message was first or third in the scope, the step would still pass. If, however, another scope was then defined:
Then I should receive a message on FIX with agent "my_initiator"
And an inclusion check was performed:
And the FIX messages should include a message with the following:
| ClOrdID | "hello" |
| OrderID | "abc" |
| Symbol | "IBM" |
| OrdStatus | "NEW" |
The new scope, containing one message, will contain the last FIX message OrdStatus=CANCELED
, and not OrdStatus=NEW
since that was consumed by the previous scope. The second inclusion check for OrdStatus=NEW
would then fail, since the received message was defined in a previous inspection scope.
Identifying scoped FIX messages in failed scenarios
In a failed Agent FIX scenario, if a scope & agent were ever defined, the last defined scope & agent will print their sent & received messages, colored according to the last defined scope. All sent messages will be colored in green, received messages prior to the current scope will be colored in green, and the current scope when the scenario failed will have its messages colored in red.
More
Check out features to see all the ways you can use agent_fix.
Install
gem install agent_fix
or add the following to Gemfile:
gem 'agent_fix'
and run bundle install
from your shell.
More Information
Contributing
Please see the contribution guidelines.
Credits
Contributors:
- Chris Busbey
- Matt Lane
- Mike Gatny
agent_fix is maintained and funded by Connamara Systems, llc.
The names and logos for Connamara Systems are trademarks of Connamara Systems, llc.
Licensing
agent_fix is Copyright © 2016 Connamara Systems, llc.
This software is available under the GPL and a commercial license. Please see the LICENSE file for the terms specified by the GPL license. The commercial license offers more flexible licensing terms compared to the GPL, and includes support services. Contact us for more information on the Connamara commercial license, what it enables, and how you can start commercial development with it.
This product includes software developed by quickfixengine.org (http://www.quickfixengine.org/). Please see the QuickFIX Software LICENSE for the terms specified by the QuickFIX Software License.