http://www.cnblogs.com/jinglelin/archive/2012/04/26/2470978.html
QuickFix/N简介
FIX是Financial Information eXchange的简称。FIX是一种专门为实时电子证券交易设计的标准消息协议。该协议由FIX protocol, Ltd(FPL)所有并维护。FIX协议的官方网址为http://www.fixprotocol.org/
QuickFix引擎( http://www.quickfixengine.org/ )一个开源的FIX引擎,其中它有JAVA、C++、C#三个版本的实现。
QuickFix/N是实现了FIX协议4.0-5.0版本及其功能的开源软件,100%使用.NET(C#)实现。
QuickFix/N官网下载 http://www.quickfixn.org/
QuickFix/N源码下载 https://github.com/connamara/quickfixn
使用QuickFIX/N创建一个Fix应用程序
使用QuickFIX/N创建一个FIX应用程序很容易,实现它的接口Application即可,例如创建一个简单应用程序如下
:
{
public void FromApp(Message msg, SessionID sessionID) { }
public void OnCreate(SessionID sessionID) { }
public void OnLogout(SessionID sessionID) { }
public void OnLogon(SessionID sessionID) { }
public void FromAdmin(Message msg, SessionID sessionID) { }
public void ToAdmin(Message msg, SessionID sessionID) { }
public void ToApp(Message msg, SessionID sessionID) { }
}
这些实现方法将被QuickFIX/N的事件调用。
下面我们来看看每个回调事件的说明。
应用回调
客户端(对手方)发送登录请求或其它请求消息,当QuickFIX/N应用程序收到消息。QuickFIX/N应用程序会发送一个回调事件的通知。
FromApp -每个应用级别的消息将通过该方法处理,如委托指令,执行报告,证券信息以及市场数据。
FromAdmin -每个管理级别的消息将通过该方法处理,如心跳,登录以及注销。
OnCreate中 - 每当一个新的会话被创建,该方法被调用。
OnLogon - 当登录操作成功完成时,该方法被调用。
OnLogout - 当会话断开时触发,包括对方主动请求logout或者网络连接断开都会引发该事件。
ToApp -所有应用级别的消息在发送出去之前,都会调用该方法。如果需要在每个发出的消息当中添加一个标签(Tag),在该方法是实现该需求最好的位置。
ToAdmin -所有发出的管理级别消息在发送出去之前,都会调用该方法。
Acceptor 和 Initiator
QuickFIX/N 实现了的acceptor 和 initiator两种模式。
Initiator:作为客户端,当我们要连接到对方的应用时,使用Initiator。
Acceptor :作为服务端,当我们要提供应用服务供对方连接时,使用Acceptor。
创建我们的应用程序
以下示例代码,我们实现Application 接口
,然后实例化一个Acceptor
:
public class MyQuickFixApp : Application
{
public void FromApp(Message msg, SessionID sessionID) { }
public void OnCreate(SessionID sessionID) { }
public void OnLogout(SessionID sessionID) { }
public void OnLogon(SessionID sessionID) { }
public void FromAdmin(Message msg, SessionID sessionID) { }
public void ToAdmin(Message msg, SessionID sessionID) { }
public void ToApp(Message msg, SessionID sessionID) { }
}
public class MyApp
{
static void Main(string[] args)
{
SessionSettings settings = new SessionSettings(args[0]);
Application myApp = new MyQuickFixApp();
MessageStoreFactory storeFactory = new FileStoreFactory(settings);
LogFactory logFactory = new FileLogFactory(settings);
ThreadedSocketAcceptor acceptor = new ThreadedSocketAcceptor(
myApp,
storeFactory,
settings,
logFactory);
acceptor.Start();
while (true)
{
System.Console.WriteLine("Waiting!");
System.Threading.Thread.Sleep(1000);
}
acceptor.Stop();
}
}
如果要更改应用角色,改为Initiator,
只要简单地用SocketInitiator替换ThreadedSocketAcceptor即可
。
其它扩展
1)消息存储扩展
MessageStore会存储
FIX会话级别消息的消息传出记录。我们可以通过实现MessageStoreFactory接口,来自定义或扩展我们的消息存储。
2)日志存储扩展
日志记录已经有了两个的实现:FileLog、ScreenLog,其中文件存储的日志记录器已经可以满足一般的要求。当然,我们也可以通过实现LogFactory接口,来自定义实现或扩展我们的日志存储。
一、 发送消息
QuickFIX/N的发送FIX消息的简单示例:
FIX44.NewOrderSingle order = new FIX44.NewOrderSingle(
new ClOrdID("1234"),
new Symbol("000001
"),
new Side(Side.BUY),
new TransactTime(DateTime.Now),
new OrdType(OrdType.MARKET));
Session.SendToTaget(order, sessionID);
首先,我们需要学习如何使用会话发送指令消息。
1) QuickFIX会话
发送消息时,我们必须指定QuickFIX会话,QuickFIX根据会话信息判定消息发送目的地。
所有QuickFIX会话的标识是在消息头定义的,通常包括SenderCompID
,TargetCompID
,BeginString
等字段
,这些都是在配置文件中指定。
SenderCompID=CONNAMARA
TargetCompID=CBOE
BeginString=FIX4.4
有几个获得会话的方式。一是当会话被创建并缓存它时,我们可以获得SessionID:
private SessionID MySessionID { get; set; }
public void OnCreate(SessionID sessionID)
{
MySessionID = sessionID;
}
另外,我们可以在响应传入消息时,得到SessionID:
public void OnMessage(FIX42.ExecutionReport execution, SessionID sessionID)
{
ProcessExecution(execution, sessionID);
}
或者,先在配置文件当中配置好所有的会话,我们可以从配置文件找到匹配的SessionID:
var mySessionID = new SessionID("FIX4.2", "senderCompID", "targetCompID");
2) 创建和发送消息
创建消息时,我们首选使用指定Fix版本和消息类型的构造函数,填写必选字段:
using QuickFix;
using QuickFix.Fields;
var order = new QuickFix.FIX44.NewOrderSingle(
new ClOrdID("1234"),
new Symbol("000001"),
new Side(Side.BUY),
new TransactTime(DateTime.Now),
new OrdType(OrdType.LIMIT));
使用信息的字段属性设置字段值:
order.Price = new Price(new decimal(22.4));
order.Account = new Account("18861112");
把上面的内容合并在一起:创建消息,设置其必需的字段,并设置两个附加字段,使用获得的SessionID,我们发送消息示意如下:
var order = new QuickFix.FIX44.NewOrderSingle(
new ClOrdID("1234"),
new Symbol("000001"),
new Side(Side.BUY),
new TransactTime(DateTime.Now),
new OrdType(OrdType.LIMIT));
order.Price = new Price(new decimal(22.4));
order.Account = new Account("18861112");
Session.SendToTarget(order, sessionID);
3) 创建消息及字段的其他实现方式
类型安全的方式 ,已经被证明它是最好的方式了,但我们也可以用其他创建消息及字段的方法。
1) 每个消息类型都有一个默认的构造函数:
var order = new QuickFix.FIX44.NewOrderSingle();
order.ClOrdID = new ClOrdID("1234");
order.Symbol = new Symbol("000001");
order.Side = new Side(Side.BUY);
2) 我们也可以用QuickFIX C ++及QuickFIX/J风格的get / set方法,也是类型安全的:
order.Set(new TransactTime(DateTime.Now));
order.Set(new OrdType(OrdType.LIMIT));
如果不是一个消息属性,可以用SetField设置一个字段的值:
order.SetField(new Account("18861112"));
3) 另外,也可以这么做,先创建一个Message基类的实例,它没有属性,因此都必须使用SetField 方法,但不建议使用这种风格:
var order = new QuickFix.Message();
order.Header.SetField(new MsgType("D"));
order.SetField(new ClOrdID("1234"));
order.SetField(new Symbol("AAPL"));
order.SetField(new Side(Side.BUY));
order.SetField(new TransactTime(DateTime.Now));
order.SetField(new OrdType(OrdType.LIMIT));
二、 接收消息
在QuickFIX/N接收类型安全和简单类型的消息:
public void OnMessage( QuickFix.FIX44.NewOrderSingle order,SessionID sessionID)
{
ProcessOrder(order.Price, order.OrderQty, order.Account);
}
1) 接收类型安全的消息
MessageCracker
是一个抽象类,一个助手类,一般在类型安全的各个OnMessage方法中调用,用于解析各个FIX版本的委托消息类型。处理FIX消息时,
Crack方法会根据消息类型,判断其类型类型是否已定义消息类型,如果已定义的消息,将调用其已注册的处理方法来处理消息。
写
QuickFIX/N应用时,应用类将继承MessageCracker,对于消息的处理,我们使用的都是指定的、强类型的Message和Field类,对于不同的消息类型,我们分别不同的处理方法实现处理逻辑。当消息到达时, FromApp方法里面调用Crack,根据不同的消息类型,调用相应类型的消息处理方法 :
using QuickFix;
public class MyApplication : MessageCracker, Application
{
public void FromApp(Message msg, SessionID sessionID)
{
Crack(msg, sessionID);
}
//...
}
在重载的onMessage回调方法当中调用Crack 。以下例子演示接收委托及证券信息:
public void OnMessage( QuickFix.FIX44.NewOrderSingle ord, SessionID sessionID)
{
ProcessOrder(ord.Price, ord.OrderQty, ord.Account);
}
public void OnMessage( QuickFix.FIX44.SecurityDefinition secDef, SessionID sessionID)
{
GotSecDef(secDef);
}
2) 消息解析器示例
整合一下,一个类型安全的订单处理的应用是这样的:
public class MyApplication : MessageCracker, Application
{
public void OnMessage(
QuickFix.FIX42.NewOrderSingle ord,
SessionID sessionID)
{
ProcessOrder(ord.Price, ord.OrderQty, ord.Account);
}
protected void ProcessOrder(
Price price,
OrderQty quantity,
Account account)
{
//...
}
#region Application Methods
public void FromApp(Message msg, SessionID sessionID)
{
Crack(msg, sessionID);
}
public void OnCreate(SessionID sessionID) { }
public void OnLogout(SessionID sessionID) { }
public void OnLogon(SessionID sessionID) { }
public void FromAdmin(Message msg, SessionID sessionID)
{ }
public void ToAdmin(Message msg, SessionID sessionID)
{ }
public void ToApp(Message msg, SessionID sessionID)
{ }
#endregion
}
3) 非类型安全的应用实现
直接对接收到的Message基类消息进行处理,没有了类型安全的类及字段,需要很多额外的逻辑。一般不建议这样做。
//
不推荐
public class MyApplication : Application
{
public void FromApp(Message msg, SessionID sessionID)
{
string msgType = msg.Header.GetString(Tags.MsgType);
if (msgType.Equals(MsgType.EXECUTION_REPORT))
{
string account = msg.GetString(Tags.Account);
decimal price = msg.GetDecimal(Tags.Price);
}
}
// ...same Application callbacks as above
}