clj-fix is a toolkit that makes it easy for you to create your own FIX client.
From fixprotocol.org
The Financial Information eXchange ("FIX") Protocol is a series of messaging specifications for the electronic communication of trade-related messages. It has been developed through the collaboration of banks, broker-dealers, exchanges, industry utilities and associations, institutional investors, and information technology providers from around the world.
In addition to sending and receiving order messages, a FIX application must handle a number of other tasks including message parsing, heartbeating, dealing with admin messages, forming FIX messages, and more. clj-fix takes care of the following for you:
See Steps to Create a FIX Client Using clj-fix for more information.
clj-fix was written so that different trading scenarios could be generated to test a market surveillance system my company developed (also in Clojure). clj-fix has been used on live exchanges and is released here under the MIT license.
;Include this in your project.clj:
[clj-fix "0.6.2"]
; Example:
(defproject my-project "1.0"
:dependencies [[clj-fix "0.6.2"]])
; In your ns statement:
(ns my-project.core
(:use clj-fix.core)
(:use clj-fix.connection.protocol))
1.Install and include clj-fix in your project.
2.In your project's root directory, create a directory called config.
You should have four pieces of information about the destination you want to communicate with: the host IP, the port, the sender id, and the target id.
Create a clients.cfg file in the config directory and type in the following information (replacing sample data as needed):
{
"my-fix-client" : {
"venue" : "the-destination", ; This is a label you provide.
"host" : "10.10.10.10",
"port" : 8888,
"sender" : "sender-id",
"target" : "target-id",
"last-logout" : "20130101", ; Enter a date from the past here. clj-fix
"inbound-seq-num" : 0, ; will update it as needed.
"outbound-seq-num" : 0
}
}
You can include multiple client configs in this file.
3.In your project's root directory, create a directory called specs. Place your destination's .spec file here. This is a file you create and is used by fix-translator. Each .spec file should have a name corresponding to the label you gave to "venue" in the config file. So in the example above, the spec directory should contain a file called the-destination.spec. Please refer to fix-translator for information on how to create a .spec file for your destination.
4.Write a callback function for clj-fix, which will use it to send you client-level responses from your destination. As of this writing, clients must handle three types of messages: logon acknowledgment, execution reports, and logout acknowledgment. Here's an example:
; This callback is supplied to an agent.
(defn my-handler [key-id reference last-msg new-msg]
(case (:msg-type new-msg)
:logon (println "Logon accepted by" (:sender-comp-id new-msg))
:execution-report (println "Execution Report: " new-msg)
:logout (println "Logged out from" (:sender-comp-id new-msg))))
5.Load the client:
(def client (load-client :my-fix-client))
6.Logon to your destination
;; The logon params are [client-var, callback, heartbeat-interval,
;; whether-to-reset-sequence-numbers, whether-to-translate-inbound-fix-messages]
(logon client my-handler 60 :no true)
Selecting false for the last parameter will result in your client receiving FIX messages in their raw format (except for logon and logout acknowledgement messages which are always translated). Please see fix-translator for more information.
7.Send an order:
; The new-order params are [the-client-var, side, quantity, symbol, price]
; This sends a buy order for 100 shares of NESNz at 10.0 of the
; symbol's currency
(new-order client :buy 100 "NESNz" 10.0)
Supplying clj-fix's new-order command with minimal parameters results in a simple LIMIT DAY order being sent with the most common default values set. If you want to override a certain default (for example, supply your own client order id) or use a particular order type your destination supports, just include an additional map in the params:
; This sends a buy order for 100 shares of NESNz at 10.0 of the symbol's
; currency with a client specified id and an immediate-or-cancel time-in-force.
(new-order client :buy 100 "NESNz" 10.0 {:client-order-id "my-own-id" :time-in-force :ioc})
Canceling an order requires you to track and maintain orders as they change states. You can either write your own manager or use clj-fix-oms as a light-weight option.
8.Logout of your destination:
; The logout params are [client-var, reason]
(logout client "done")
9.End your session properly so that clj-fix updates the config file.
; The logout param is [client-var]
(end-session client)
cd demo && clj -X:demo
this starts the quote harvester and will print a table of the current quotes to the console.