using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Web;
using QuickFix;
using QuickFix.Fields;
// http://quickfixn.org/
// https://www.nuget.org/packages/QuickFix.Net.NETCore.FIX42/
// http://quickfixn.org/tutorial/creating-an-application
// http://quickfixn.org/tutorial/example-applications
namespace TopNugetPackages
{
public class HttpServer : IDisposable
{
private readonly HttpListener _httpListener;
private Thread _connectionThread;
private Boolean _running, _disposed;
private readonly SessionSettings _sessionSettings;
private StringBuilder _sbHtmlHeader;
public HttpServer(string prefix, SessionSettings settings)
{
if (!HttpListener.IsSupported)
{
// Requires at least a Windows XP with Service Pack 2
throw new NotSupportedException(
"The Http Server cannot run on this operating system.");
}
_httpListener = new HttpListener();
_httpListener.Prefixes.Add(prefix);
_sessionSettings = settings;
}
public void Start()
{
if (!_httpListener.IsListening)
{
_httpListener.Start();
_running = true;
// Use a thread to listen to the Http requests
_connectionThread = new Thread(ConnectionThreadStart);
_connectionThread.Start();
}
}
public void Stop()
{
if (_httpListener.IsListening)
{
_running = false;
_httpListener.Stop();
}
}
private void ConnectionThreadStart()
{
try
{
while (_running)
{
// Grab the context and pass it to the processor methods to handle it
HttpListenerContext context = _httpListener.GetContext();
HttpListenerRequest request = context.Request;
HttpListenerResponse response = context.Response;
string responseString;
_sbHtmlHeader = new StringBuilder(@"<HEAD><CENTER><TITLE>QuickFIX Engine Web Interface</TITLE><H1>QuickFIX Engine Web Interface</H1></CENTER>");
_sbHtmlHeader.AppendFormat(@"<CENTER>[<A HREF='/'>HOME</A>] [<A HREF='{0}'>RELOAD</A>]</CENTER><HR/></HEADER><BODY>", request.Url.OriginalString);
switch (request.Url.AbsolutePath)
{
case "/":
responseString = ProcessRoot(request);
break;
case "/session":
responseString = SessionDetails(request);
break;
case "/resetSession":
responseString = ResetSession(request);
break;
case "/resetSessions":
responseString = ResetSessions(request);
break;
case "/refreshSession":
responseString = RefreshSession(request);
break;
case "/refreshSessions":
responseString = RefreshSessions(request);
break;
case "/enableSessions":
responseString = EnableSessions(request);
break;
case "/disableSessions":
responseString = DisableSessions(request);
break;
default:
responseString = ProcessRoot(request);
break;
}
byte[] buffer = Encoding.UTF8.GetBytes(responseString);
response.ContentLength64 = buffer.Length;
Stream output = response.OutputStream;
output.Write(buffer, 0, buffer.Length);
output.Close();
}
}
catch (HttpListenerException)
{
Console.WriteLine("HTTP server was shut down.");
}
}
private string DisableSessions(HttpListenerRequest request)
{
bool confirm = false;
StringBuilder sbHtmlPageBody = _sbHtmlHeader;
if (request.QueryString["confirm"] != null)
{
if (Convert.ToInt16(request.QueryString["confirm"]) != 0)
{
confirm = true;
foreach (SessionID session in _sessionSettings.GetSessions())
{
Session sessionDetails = Session.LookupSession(session);
sessionDetails.Logout();
}
}
}
if (confirm)
{
sbHtmlPageBody = new StringBuilder();
sbHtmlPageBody.AppendFormat(@"<HEAD><META http-equiv='refresh' content=2;URL={0} /><CENTER><TITLE>QuickFIX Engine Web Interface</TITLE><H1>QuickFIX Engine Web Interface</H1></CENTER>", "/");
sbHtmlPageBody.AppendFormat("<CENTER><h2><A HREF='{0}'>Sessions</A> have been disabled</h2></CENTER>", "/");
}
else
{
sbHtmlPageBody.Append("<CENTER><h2>Are you sure you want to disable all sessions ?</h2></CENTER>");
sbHtmlPageBody.AppendFormat("<CENTER>[<A HREF='{0}?confirm=1'>YES, disable sessions</A>] [<A HREF='/'>NO, do not disable sessions</A>]</CENTER>", request.Url.OriginalString);
}
return sbHtmlPageBody.ToString();
}
private string EnableSessions(HttpListenerRequest request)
{
bool confirm = false;
string urlOriginalString = request.Url.OriginalString;
StringBuilder sbHtmlPageBody = _sbHtmlHeader;
if (request.QueryString["confirm"] != null)
{
if (Convert.ToInt16(request.QueryString["confirm"]) != 0)
{
confirm = true;
foreach (SessionID session in _sessionSettings.GetSessions())
{
Session sessionDetails = Session.LookupSession(session);
sessionDetails.Logon();
}
}
}
if (confirm)
{
sbHtmlPageBody = new StringBuilder();
sbHtmlPageBody.AppendFormat(@"<HEAD><META http-equiv='refresh' content=2;URL={0} /><CENTER><TITLE>QuickFIX Engine Web Interface</TITLE><H1>QuickFIX Engine Web Interface</H1></CENTER>", "/");
sbHtmlPageBody.AppendFormat("<CENTER><h2><A HREF='{0}'>Sessions</A> have been enabled</h2></CENTER>", "/");
}
else
{
sbHtmlPageBody.Append("<CENTER><h2>Are you sure you want to enable all sessions ?</h2></CENTER>");
sbHtmlPageBody.AppendFormat("<CENTER>[<A HREF='{0}?confirm=1'>YES, enable sessions</A>] [<A HREF='/'>NO, do not enable sessions</A>]</CENTER>", urlOriginalString);
}
return sbHtmlPageBody.ToString();
}
private string RefreshSession(HttpListenerRequest request)
{
SessionID sessionId = new SessionID(request.QueryString["beginstring"], request.QueryString["sendercompid"], request.QueryString["targetcompid"]);
Session sessionDetails = Session.LookupSession(sessionId);
if (sessionDetails == null) throw new Exception("Session not found");
StringBuilder sbHtmlPageBody = _sbHtmlHeader;
bool confirm = false;
string urlOriginalString = request.Url.OriginalString;
string url = "/session?" + GetParameterList(urlOriginalString);
if (request.QueryString["confirm"] != null)
{
if (Convert.ToInt16(request.QueryString["confirm"]) != 0)
{
confirm = true;
sessionDetails.Refresh();
url = RemoveQueryStringByKey(urlOriginalString, "confirm");
}
}
if (confirm)
{
sbHtmlPageBody = new StringBuilder();
sbHtmlPageBody.AppendFormat(@"<HEAD><META http-equiv='refresh' content=2;URL=/session?{0} /><CENTER><TITLE>QuickFIX Engine Web Interface</TITLE><H1>QuickFIX Engine Web Interface</H1></CENTER>", GetParameterList(urlOriginalString));
sbHtmlPageBody.AppendFormat(@"<CENTER>[<A HREF='/'>HOME</A>] [<A HREF='{0}'>RELOAD</A>]</CENTER><HR/></HEAD><BODY>", urlOriginalString);
sbHtmlPageBody.AppendFormat("<CENTER><h2><A HREF='/session?{0}'>{1}</A> has been refreshed</h2></CENTER>", GetParameterList(url), sessionId);
}
else
{
sbHtmlPageBody.AppendFormat("<CENTER><h2>Are you sure you want to refresh session <A HREF='{0}'>{1}</A>?</h2></CENTER>", url, sessionId);
sbHtmlPageBody.AppendFormat("<CENTER>[<A HREF='{0}&confirm=1'>YES, refresh session</A>] [<A HREF='{0}'>NO, do not refresh session</A>]</CENTER>", url);
}
return sbHtmlPageBody.ToString();
}
private string RefreshSessions(HttpListenerRequest request)
{
bool confirm = false;
string urlOriginalString = request.Url.OriginalString;
StringBuilder sbHtmlPageBody = _sbHtmlHeader;
if (request.QueryString["confirm"] != null)
{
if (Convert.ToInt16(request.QueryString["confirm"]) != 0)
{
confirm = true;
foreach (SessionID session in _sessionSettings.GetSessions())
{
Session sessionDetails = Session.LookupSession(session);
sessionDetails.Refresh();
}
}
}
if (confirm)
{
sbHtmlPageBody = new StringBuilder();
sbHtmlPageBody.AppendFormat(@"<HEAD><META http-equiv='refresh' content=2;URL={0} /><CENTER><TITLE>QuickFIX Engine Web Interface</TITLE><H1>QuickFIX Engine Web Interface</H1></CENTER>", "/");
sbHtmlPageBody.AppendFormat("<CENTER><h2><A HREF='{0}'>Sessions</A> have been refreshed</h2></CENTER>", "/");
}
else
{
sbHtmlPageBody.Append("<CENTER><h2>Are you sure you want to refresh all sessions ?</h2></CENTER>");
sbHtmlPageBody.AppendFormat("<CENTER>[<A HREF='{0}?confirm=1'>YES, refresh sessions</A>] [<A HREF='/'>NO, do not refresh sessions</A>]</CENTER>", urlOriginalString);
}
return sbHtmlPageBody.ToString();
}
private string ResetSessions(HttpListenerRequest request)
{
bool confirm = false;
string urlOriginalString = request.Url.OriginalString;
StringBuilder sbHtmlPageBody = _sbHtmlHeader;
if (request.QueryString["confirm"] != null)
{
if (Convert.ToInt16(request.QueryString["confirm"]) != 0)
{
confirm = true;
foreach (SessionID session in _sessionSettings.GetSessions())
{
Session sessionDetails = Session.LookupSession(session);
sessionDetails.Reset("Reset from WebInterface");
}
}
}
if (confirm)
{
sbHtmlPageBody = new StringBuilder();
sbHtmlPageBody.AppendFormat(@"<HEAD><META http-equiv='refresh' content=2;URL={0} /><CENTER><TITLE>QuickFIX Engine Web Interface</TITLE><H1>QuickFIX Engine Web Interface</H1></CENTER>", "/");
sbHtmlPageBody.AppendFormat("<CENTER><h2><A HREF='{0}'>Sessions</A> have been reset</h2></CENTER>", "/");
}
else
{
sbHtmlPageBody.Append("<CENTER><h2>Are you sure you want to reset all sessions ?</h2></CENTER>");
sbHtmlPageBody.AppendFormat("<CENTER>[<A HREF='{0}?confirm=1'>YES, reset sessions</A>] [<A HREF='/'>NO, do not reset sessions</A>]</CENTER>", urlOriginalString);
}
return sbHtmlPageBody.ToString();
}
private string ResetSession(HttpListenerRequest request)
{
SessionID sessionId = new SessionID(request.QueryString["beginstring"], request.QueryString["sendercompid"], request.QueryString["targetcompid"]);
Session sessionDetails = Session.LookupSession(sessionId);
if (sessionDetails == null) throw new Exception("Session not found");
StringBuilder sbHtmlPageBody = _sbHtmlHeader;
bool confirm = false;
string urlOriginalString = request.Url.OriginalString;
string url = "/session?" + GetParameterList(urlOriginalString);
if (request.QueryString["confirm"] != null)
{
if (Convert.ToInt16(request.QueryString["confirm"]) != 0)
{
confirm = true;
sessionDetails.Reset("Reset from WebInterface");
url = RemoveQueryStringByKey(urlOriginalString, "confirm");
}
}
if (confirm)
{
sbHtmlPageBody = new StringBuilder();
sbHtmlPageBody.AppendFormat(@"<HEAD><META http-equiv='refresh' content=2;URL=/session?{0} /><CENTER><TITLE>QuickFIX Engine Web Interface</TITLE><H1>QuickFIX Engine Web Interface</H1></CENTER>", GetParameterList(urlOriginalString));
sbHtmlPageBody.AppendFormat(@"<CENTER>[<A HREF='/'>HOME</A>] [<A HREF='{0}'>RELOAD</A>]</CENTER><HR/></HEAD><BODY>", urlOriginalString);
sbHtmlPageBody.AppendFormat("<CENTER><h2><A HREF='/session?{0}'>{1}</A> has been reset</h2></CENTER>", GetParameterList(url), sessionId);
}
else
{
sbHtmlPageBody.AppendFormat("<CENTER><h2>Are you sure you want to reset session <A HREF='{0}'>{1}</A>?</h2></CENTER>", url, sessionId);
sbHtmlPageBody.AppendFormat("<CENTER>[<A HREF='{0}&confirm=1'>YES, reset session</A>] [<A HREF='{0}'>NO, do not reset session</A>]</CENTER>", url);
}
return sbHtmlPageBody.ToString();
}
private string ProcessRoot(HttpListenerRequest request)
{
StringBuilder sbHtmlPageBody = _sbHtmlHeader;
//Session count
sbHtmlPageBody.AppendFormat("<CENTER><b><i>{0} Sessions managed by QuickFIX</b></i></CENTER><HR/>", _sessionSettings.GetSessions().Count);
//session management links
sbHtmlPageBody.AppendFormat(@"<CENTER><A HREF='/resetSessions{0}'>RESET</A> <A HREF='/refreshSessions'>REFRESH</A> <A HREF='/enableSessions'>ENABLE</A> <A HREF='/disableSessions'>DISABLE</A></CENTER><HR/></HEADER><BODY>", GetParameterList(request.Url.OriginalString));
//Start the table generation
sbHtmlPageBody.Append("<table id=\"sessionlist\" style=\"border-width:1; padding:2; width:100%\">");
sbHtmlPageBody.Append("<tr>");
sbHtmlPageBody.Append(AddCell("Session", true));
sbHtmlPageBody.Append(AddCell("Type", true));
sbHtmlPageBody.Append(AddCell("Enabled", true));
sbHtmlPageBody.Append(AddCell("Session Time", true));
sbHtmlPageBody.Append(AddCell("Logged On", true));
sbHtmlPageBody.Append(AddCell("Next Incoming", true));
sbHtmlPageBody.Append(AddCell("Next Outgoing", true));
sbHtmlPageBody.Append("</tr>");
foreach (SessionID session in _sessionSettings.GetSessions())
{
Session sessionDetails = Session.LookupSession(session);
sbHtmlPageBody.Append("<tr>");
sbHtmlPageBody.Append(AddCell(String.Format(
"<a href=\"session?BeginString={0}&SenderCompID={1}&TargetCompID={2}\">{0}:{1}->{2}</a>",
session.BeginString, session.SenderCompID, session.TargetCompID)));
sbHtmlPageBody.Append(AddCell(sessionDetails.IsInitiator ? "initiator" : "acceptor"));
sbHtmlPageBody.Append(AddCell(sessionDetails.IsEnabled ? "yes" : "no"));
sbHtmlPageBody.Append(AddCell(sessionDetails.IsSessionTime ? "yes" : "no"));
sbHtmlPageBody.Append(AddCell(sessionDetails.IsLoggedOn ? "yes" : "no"));
sbHtmlPageBody.Append(AddCell(sessionDetails.NextTargetMsgSeqNum.ToString()));
sbHtmlPageBody.Append(AddCell(sessionDetails.NextSenderMsgSeqNum.ToString()));
sbHtmlPageBody.Append("</tr>");
}
sbHtmlPageBody.Append("</table>");
return sbHtmlPageBody.ToString();
}
public string SessionDetails(HttpListenerRequest request)
{
SessionID sessionId = new SessionID(request.QueryString["beginstring"], request.QueryString["sendercompid"], request.QueryString["targetcompid"]);
Session sessionDetails = Session.LookupSession(sessionId);
if (sessionDetails == null) throw new Exception("Session not found");
StringBuilder sbHtmlPageBody = _sbHtmlHeader;
string url = request.Url.OriginalString;
string urlOriginalString = request.Url.OriginalString;
if (request.QueryString["enabled"] != null)
{
if (!Convert.ToBoolean(request.QueryString["enabled"]))
sessionDetails.Logout();
else
sessionDetails.Logon();
url = RemoveQueryStringByKey(urlOriginalString, "Enabled");
}
if (request.QueryString["next incoming"] != null)
{
int value = Convert.ToInt16(request.QueryString["next incoming"]);
sessionDetails.NextTargetMsgSeqNum = value <= 0 ? 1 : value;
url = RemoveQueryStringByKey(urlOriginalString, "next incoming");
}
if (request.QueryString["Next Outgoing"] != null)
{
int value = Convert.ToInt16(request.QueryString["Next Outgoing"]);
sessionDetails.NextSenderMsgSeqNum = value <= 0 ? 1 : value;
url = RemoveQueryStringByKey(urlOriginalString, "Next Outgoing");
}
if (request.QueryString["SendRedundantResendRequests"] != null)
{
sessionDetails.SendRedundantResendRequests = Convert.ToBoolean(request.QueryString["SendRedundantResendRequests"]);
url = RemoveQueryStringByKey(urlOriginalString, "SendRedundantResendRequests");
}
if (request.QueryString["CheckCompId"] != null)
{
sessionDetails.CheckCompID = Convert.ToBoolean(request.QueryString["CheckCompId"]);
url = RemoveQueryStringByKey(urlOriginalString, "CheckCompId");
}
if (request.QueryString["CheckLatency"] != null)
{
sessionDetails.CheckLatency = Convert.ToBoolean(request.QueryString["CheckLatency"]);
url = RemoveQueryStringByKey(urlOriginalString, "CheckLatency");
}
if (request.QueryString["MaxLatency"] != null)
{
int value = Convert.ToInt16(request.QueryString["MaxLatency"]);
sessionDetails.MaxLatency = value <= 0 ? 1 : value;
url = RemoveQueryStringByKey(urlOriginalString, "MaxLatency");
}
if (request.QueryString["LogonTimeout"] != null)
{
int value = Convert.ToInt16(request.QueryString["LogonTimeout"]);
sessionDetails.LogonTimeout = value <= 0 ? 1 : value;
url = RemoveQueryStringByKey(urlOriginalString, "LogonTimeout");
}
if (request.QueryString["LogoutTimeout"] != null)
{
int value = Convert.ToInt16(request.QueryString["LogoutTimeout"]);
sessionDetails.LogoutTimeout = value <= 0 ? 1 : value;
url = RemoveQueryStringByKey(urlOriginalString, "LogoutTimeout");
}
if (request.QueryString["ResetOnLogon"] != null)
{
sessionDetails.ResetOnLogon = Convert.ToBoolean(request.QueryString["ResetOnLogon"]);
url = RemoveQueryStringByKey(urlOriginalString, "ResetOnLogon");
}
if (request.QueryString["ResetOnLogout"] != null)
{
sessionDetails.ResetOnLogout = Convert.ToBoolean(request.QueryString["ResetOnLogout"]);
url = RemoveQueryStringByKey(urlOriginalString, "ResetOnLogout");
}
if (request.QueryString["ResetOnDisconnect"] != null)
{
sessionDetails.ResetOnDisconnect = Convert.ToBoolean(request.QueryString["ResetOnDisconnect"]);
url = RemoveQueryStringByKey(urlOriginalString, "ResetOnDisconnect");
}
if (request.QueryString["RefreshOnLogon"] != null)
{
sessionDetails.RefreshOnLogon = Convert.ToBoolean(request.QueryString["RefreshOnLogon"]);
url = RemoveQueryStringByKey(urlOriginalString, "RefreshOnLogon");
}
if (request.QueryString["MillisecondsInTimestamp"] != null)
{
sessionDetails.MillisecondsInTimeStamp = Convert.ToBoolean(request.QueryString["MillisecondsInTimestamp"]);
url = RemoveQueryStringByKey(urlOriginalString, "MillisecondsInTimestamp");
}
if (request.QueryString["PersistMessages"] != null)
{
sessionDetails.PersistMessages = Convert.ToBoolean(request.QueryString["PersistMessages"]);
url = RemoveQueryStringByKey(urlOriginalString, "PersistMessages");
}
sbHtmlPageBody.AppendFormat(@"<CENTER>{0}</CENTER><HR/>", sessionId);
sbHtmlPageBody.AppendFormat(@"<CENTER>[<A HREF='/resetSession?{0}'>RESET</A>] [<A HREF='/refreshSession?{0}'>REFRESH</A>]</CENTER><HR/></HEADER><BODY>", GetParameterList(urlOriginalString));
sbHtmlPageBody.Append("<table id=\"session_details\" style=\"border-width:1; padding:2; width:100%\">");
sbHtmlPageBody.Append(AddRow("Enabled", sessionDetails.IsEnabled, url));
sbHtmlPageBody.Append(AddRow("ConnectionType", sessionDetails.IsInitiator ? "initiator" : "acceptor"));
sbHtmlPageBody.Append(AddRow("SessionTime", sessionDetails.IsSessionTime));
sbHtmlPageBody.Append(AddRow("LoggedOn", sessionDetails.IsLoggedOn));
sbHtmlPageBody.Append(AddRow("Next Incoming", sessionDetails.NextTargetMsgSeqNum, url));
sbHtmlPageBody.Append(AddRow("Next Outgoing", sessionDetails.NextSenderMsgSeqNum, url));
sbHtmlPageBody.Append(AddRow("SendRedundantResendRequests", sessionDetails.SendRedundantResendRequests, url));
sbHtmlPageBody.Append(AddRow("CheckCompId", sessionDetails.CheckCompID, url));
sbHtmlPageBody.Append(AddRow("CheckLatency", sessionDetails.CheckLatency, url));
sbHtmlPageBody.Append(AddRow("MaxLatency", sessionDetails.MaxLatency, url));
sbHtmlPageBody.Append(AddRow("LogonTimeout", sessionDetails.LogonTimeout, url));
sbHtmlPageBody.Append(AddRow("LogoutTimeout", sessionDetails.LogoutTimeout, url));
sbHtmlPageBody.Append(AddRow("ResetOnLogon", sessionDetails.ResetOnLogon, url));
sbHtmlPageBody.Append(AddRow("ResetOnLogout", sessionDetails.ResetOnLogout, url));
sbHtmlPageBody.Append(AddRow("ResetOnDisconnect", sessionDetails.ResetOnDisconnect, url));
sbHtmlPageBody.Append(AddRow("RefreshOnLogon", sessionDetails.RefreshOnLogon, url));
sbHtmlPageBody.Append(AddRow("MillisecondsInTimestamp", sessionDetails.MillisecondsInTimeStamp, url));
sbHtmlPageBody.Append(AddRow("PersistMessages", sessionDetails.PersistMessages, url));
sbHtmlPageBody.Append("</table>");
return sbHtmlPageBody.ToString();
}
public static string RemoveQueryStringByKey(string url, string key)
{
var uri = new Uri(url);
// this gets all the query string key value pairs as a collection
var newQueryString = HttpUtility.ParseQueryString(uri.Query);
// this removes the key if exists
newQueryString.Remove(key);
// this gets the page path from root without QueryString
string pagePathWithoutQueryString = uri.GetLeftPart(UriPartial.Path);
return newQueryString.Count > 0
? $"{pagePathWithoutQueryString}?{newQueryString}"
: pagePathWithoutQueryString;
}
public static string GetParameterList(string url)
{
return HttpUtility.ParseQueryString((new Uri(url).Query)).ToString();
}
private static string AddRow(string colName, bool value, string url = "")
{
string valueAsStr = value ? "yes" : "no";
string innerHtml = url.Length > 0
? $"<a href=\" {url}&{colName}={!value} \">toggle</a>"
: "";
return AddRow(colName, valueAsStr, innerHtml);
}
private static string AddRow(string colName, int value, string url = "")
{
string innerHtml = $"<a href=\" {url}&{colName}={value - 10} \"> << </a>" +
$"<a href=\" {url}&{colName}={value - 1} \"> < </a>" +
" | " +
$"<a href=\" {url}&{colName}={value + 1} \"> > </a>" +
$"<a href=\" {url}&{colName}={value + 10} \"> >> </a>";
return AddRow(colName, value.ToString(), innerHtml);
}
private static string AddRow(string colName, string value, string innerHtml = "")
{
StringBuilder row = new StringBuilder();
row.Append("<tr>");
row.Append(AddCell(colName));
row.Append(AddCell(value));
row.Append(AddCell(innerHtml));
row.Append("</tr>");
return row.ToString();
}
private static string AddCell(string cellContent, bool header = false)
{
string entryType = header ? "th" : "td";
return "<" + entryType + " align=\"left\">" + cellContent + "</" + entryType + ">";
}
~HttpServer() => Dispose(false);
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (_disposed)
{
return;
}
if (disposing)
{
if (_running)
{
Stop();
}
if (_connectionThread != null)
{
//_connectionThread.Abort();
_connectionThread.Join();
_connectionThread = null;
}
}
_disposed = true;
}
}
/// <summary>
/// Just a simple server that will let you connect to it and ignore any
/// application-level messages you send to it.
/// Note that this app is *NOT* a message cracker.
/// </summary>
public class SimpleAcceptorApp : /*QuickFix.MessageCracker,*/ QuickFix.IApplication
{
#region QuickFix.Application Methods
public void FromApp(Message message, SessionID sessionID)
{
Console.WriteLine("IN: " + message);
//Crack(message, sessionID);
}
public void ToApp(Message message, SessionID sessionID)
{
Console.WriteLine("OUT: " + message);
}
public void FromAdmin(Message message, SessionID sessionID)
{
Console.WriteLine("IN: " + message);
}
public void ToAdmin(Message message, SessionID sessionID)
{
Console.WriteLine("OUT: " + message);
}
public void OnCreate(SessionID sessionID) { }
public void OnLogout(SessionID sessionID) { }
public void OnLogon(SessionID sessionID) { }
#endregion
}
public class TradeClientApp : QuickFix.MessageCracker, QuickFix.IApplication
{
Session _session = null;
// This variable is a kludge for developer test purposes. Don't do this on a production application.
public IInitiator MyInitiator = null;
#region IApplication interface overrides
public void OnCreate(SessionID sessionID)
{
_session = Session.LookupSession(sessionID);
}
public void OnLogon(SessionID sessionID) { Console.WriteLine("Logon - " + sessionID.ToString()); }
public void OnLogout(SessionID sessionID) { Console.WriteLine("Logout - " + sessionID.ToString()); }
public void FromAdmin(Message message, SessionID sessionID) { }
public void ToAdmin(Message message, SessionID sessionID) { }
public void FromApp(Message message, SessionID sessionID)
{
Console.WriteLine("IN: " + message.ToString());
try
{
Crack(message, sessionID);
}
catch (Exception ex)
{
Console.WriteLine("==Cracker exception==");
Console.WriteLine(ex.ToString());
Console.WriteLine(ex.StackTrace);
}
}
public void ToApp(Message message, SessionID sessionID)
{
try
{
bool possDupFlag = false;
if (message.Header.IsSetField(QuickFix.Fields.Tags.PossDupFlag))
{
possDupFlag = QuickFix.Fields.Converters.BoolConverter.Convert(
message.Header.GetString(QuickFix.Fields.Tags.PossDupFlag)); /// FIXME
}
if (possDupFlag)
throw new DoNotSend();
}
catch (FieldNotFoundException)
{ }
Console.WriteLine();
Console.WriteLine("OUT: " + message.ToString());
}
#endregion
#region MessageCracker handlers
public void OnMessage(QuickFix.FIX44.ExecutionReport m, SessionID s)
{
Console.WriteLine("Received execution report");
}
public void OnMessage(QuickFix.FIX44.OrderCancelReject m, SessionID s)
{
Console.WriteLine("Received order cancel reject");
}
#endregion
public void Run()
{
while (true)
{
try
{
char action = QueryAction();
if (action == '1')
QueryEnterOrder();
else if (action == '2')
QueryCancelOrder();
else if (action == '3')
QueryReplaceOrder();
else if (action == '4')
QueryMarketDataRequest();
else if (action == 'g')
{
if (this.MyInitiator.IsStopped)
{
Console.WriteLine("Restarting initiator...");
this.MyInitiator.Start();
}
else
Console.WriteLine("Already started.");
}
else if (action == 'x')
{
if (this.MyInitiator.IsStopped)
Console.WriteLine("Already stopped.");
else
{
Console.WriteLine("Stopping initiator...");
this.MyInitiator.Stop();
}
}
else if (action == 'q' || action == 'Q')
break;
}
catch (System.Exception e)
{
Console.WriteLine("Message Not Sent: " + e.Message);
Console.WriteLine("StackTrace: " + e.StackTrace);
}
}
Console.WriteLine("Program shutdown.");
}
private void SendMessage(Message m)
{
if (_session != null)
_session.Send(m);
else
{
// This probably won't ever happen.
Console.WriteLine("Can't send message: session not created.");
}
}
private char QueryAction()
{
// Commands 'g' and 'x' are intentionally hidden.
Console.Write("\n"
+ "1) Enter Order\n"
+ "2) Cancel Order\n"
+ "3) Replace Order\n"
+ "4) Market data test\n"
+ "Q) Quit\n"
+ "Action: "
);
HashSet<string> validActions = new HashSet<string>("1,2,3,4,q,Q,g,x".Split(','));
string cmd = Console.ReadLine().Trim();
if (cmd.Length != 1 || validActions.Contains(cmd) == false)
throw new System.Exception("Invalid action");
return cmd.ToCharArray()[0];
}
private void QueryEnterOrder()
{
Console.WriteLine("\nNewOrderSingle");
QuickFix.FIX44.NewOrderSingle m = QueryNewOrderSingle44();
if (m != null && QueryConfirm("Send order"))
{
m.Header.GetString(Tags.BeginString);
SendMessage(m);
}
}
private void QueryCancelOrder()
{
Console.WriteLine("\nOrderCancelRequest");
QuickFix.FIX44.OrderCancelRequest m = QueryOrderCancelRequest44();
if (m != null && QueryConfirm("Cancel order"))
SendMessage(m);
}
private void QueryReplaceOrder()
{
Console.WriteLine("\nCancelReplaceRequest");
QuickFix.FIX44.OrderCancelReplaceRequest m = QueryCancelReplaceRequest44();
if (m != null && QueryConfirm("Send replace"))
SendMessage(m);
}
private void QueryMarketDataRequest()
{
Console.WriteLine("\nMarketDataRequest");
QuickFix.FIX44.MarketDataRequest m = QueryMarketDataRequest44();
if (m != null && QueryConfirm("Send market data request"))
SendMessage(m);
}
private bool QueryConfirm(string query)
{
Console.WriteLine();
Console.WriteLine(query + "?: ");
string line = Console.ReadLine().Trim();
return (line[0].Equals('y') || line[0].Equals('Y'));
}
#region Message creation functions
private QuickFix.FIX44.NewOrderSingle QueryNewOrderSingle44()
{
QuickFix.Fields.OrdType ordType = null;
QuickFix.FIX44.NewOrderSingle newOrderSingle = new QuickFix.FIX44.NewOrderSingle(
QueryClOrdID(),
QuerySymbol(),
QuerySide(),
new TransactTime(DateTime.Now),
ordType = QueryOrdType());
newOrderSingle.Set(new HandlInst('1'));
newOrderSingle.Set(QueryOrderQty());
newOrderSingle.Set(QueryTimeInForce());
if (ordType.getValue() == OrdType.LIMIT || ordType.getValue() == OrdType.STOP_LIMIT)
newOrderSingle.Set(QueryPrice());
if (ordType.getValue() == OrdType.STOP || ordType.getValue() == OrdType.STOP_LIMIT)
newOrderSingle.Set(QueryStopPx());
return newOrderSingle;
}
private QuickFix.FIX44.OrderCancelRequest QueryOrderCancelRequest44()
{
QuickFix.FIX44.OrderCancelRequest orderCancelRequest = new QuickFix.FIX44.OrderCancelRequest(
QueryOrigClOrdID(),
QueryClOrdID(),
QuerySymbol(),
QuerySide(),
new TransactTime(DateTime.Now));
orderCancelRequest.Set(QueryOrderQty());
return orderCancelRequest;
}
private QuickFix.FIX44.OrderCancelReplaceRequest QueryCancelReplaceRequest44()
{
QuickFix.FIX44.OrderCancelReplaceRequest ocrr = new QuickFix.FIX44.OrderCancelReplaceRequest(
QueryOrigClOrdID(),
QueryClOrdID(),
QuerySymbol(),
QuerySide(),
new TransactTime(DateTime.Now),
QueryOrdType());
ocrr.Set(new HandlInst('1'));
if (QueryConfirm("New price"))
ocrr.Set(QueryPrice());
if (QueryConfirm("New quantity"))
ocrr.Set(QueryOrderQty());
return ocrr;
}
private QuickFix.FIX44.MarketDataRequest QueryMarketDataRequest44()
{
MDReqID mdReqID = new MDReqID("MARKETDATAID");
SubscriptionRequestType subType = new SubscriptionRequestType(SubscriptionRequestType.SNAPSHOT);
MarketDepth marketDepth = new MarketDepth(0);
QuickFix.FIX44.MarketDataRequest.NoMDEntryTypesGroup marketDataEntryGroup = new QuickFix.FIX44.MarketDataRequest.NoMDEntryTypesGroup();
marketDataEntryGroup.Set(new MDEntryType(MDEntryType.BID));
QuickFix.FIX44.MarketDataRequest.NoRelatedSymGroup symbolGroup = new QuickFix.FIX44.MarketDataRequest.NoRelatedSymGroup();
symbolGroup.Set(new Symbol("LNUX"));
QuickFix.FIX44.MarketDataRequest message = new QuickFix.FIX44.MarketDataRequest(mdReqID, subType, marketDepth);
message.AddGroup(marketDataEntryGroup);
message.AddGroup(symbolGroup);
return message;
}
#endregion
#region field query private methods
private ClOrdID QueryClOrdID()
{
Console.WriteLine();
Console.Write("ClOrdID? ");
return new ClOrdID(Console.ReadLine().Trim());
}
private OrigClOrdID QueryOrigClOrdID()
{
Console.WriteLine();
Console.Write("OrigClOrdID? ");
return new OrigClOrdID(Console.ReadLine().Trim());
}
private Symbol QuerySymbol()
{
Console.WriteLine();
Console.Write("Symbol? ");
return new Symbol(Console.ReadLine().Trim());
}
private Side QuerySide()
{
Console.WriteLine();
Console.WriteLine("1) Buy");
Console.WriteLine("2) Sell");
Console.WriteLine("3) Sell Short");
Console.WriteLine("4) Sell Short Exempt");
Console.WriteLine("5) Cross");
Console.WriteLine("6) Cross Short");
Console.WriteLine("7) Cross Short Exempt");
Console.Write("Side? ");
string s = Console.ReadLine().Trim();
char c = ' ';
switch (s)
{
case "1": c = Side.BUY; break;
case "2": c = Side.SELL; break;
case "3": c = Side.SELL_SHORT; break;
case "4": c = Side.SELL_SHORT_EXEMPT; break;
case "5": c = Side.CROSS; break;
case "6": c = Side.CROSS_SHORT; break;
case "7": c = 'A'; break;
default: throw new Exception("unsupported input");
}
return new Side(c);
}
private OrdType QueryOrdType()
{
Console.WriteLine();
Console.WriteLine("1) Market");
Console.WriteLine("2) Limit");
Console.WriteLine("3) Stop");
Console.WriteLine("4) Stop Limit");
Console.Write("OrdType? ");
string s = Console.ReadLine().Trim();
char c = ' ';
switch (s)
{
case "1": c = OrdType.MARKET; break;
case "2": c = OrdType.LIMIT; break;
case "3": c = OrdType.STOP; break;
case "4": c = OrdType.STOP_LIMIT; break;
default: throw new Exception("unsupported input");
}
return new OrdType(c);
}
private OrderQty QueryOrderQty()
{
Console.WriteLine();
Console.Write("OrderQty? ");
return new OrderQty(Convert.ToDecimal(Console.ReadLine().Trim()));
}
private TimeInForce QueryTimeInForce()
{
Console.WriteLine();
Console.WriteLine("1) Day");
Console.WriteLine("2) IOC");
Console.WriteLine("3) OPG");
Console.WriteLine("4) GTC");
Console.WriteLine("5) GTX");
Console.Write("TimeInForce? ");
string s = Console.ReadLine().Trim();
char c = ' ';
switch (s)
{
case "1": c = TimeInForce.DAY; break;
case "2": c = TimeInForce.IMMEDIATE_OR_CANCEL; break;
case "3": c = TimeInForce.AT_THE_OPENING; break;
case "4": c = TimeInForce.GOOD_TILL_CANCEL; break;
case "5": c = TimeInForce.GOOD_TILL_CROSSING; break;
default: throw new Exception("unsupported input");
}
return new TimeInForce(c);
}
private Price QueryPrice()
{
Console.WriteLine();
Console.Write("Price? ");
return new Price(Convert.ToDecimal(Console.ReadLine().Trim()));
}
private StopPx QueryStopPx()
{
Console.WriteLine();
Console.Write("StopPx? ");
return new StopPx(Convert.ToDecimal(Console.ReadLine().Trim()));
}
#endregion
}
public class Executor : QuickFix.MessageCracker, QuickFix.IApplication
{
static readonly decimal DEFAULT_MARKET_PRICE = 10;
int orderID = 0;
int execID = 0;
private string GenOrderID() { return (++orderID).ToString(); }
private string GenExecID() { return (++execID).ToString(); }
#region QuickFix.Application Methods
public void FromApp(Message message, SessionID sessionID)
{
Console.WriteLine("IN: " + message);
Crack(message, sessionID);
}
public void ToApp(Message message, SessionID sessionID)
{
Console.WriteLine("OUT: " + message);
}
public void FromAdmin(Message message, SessionID sessionID) { }
public void OnCreate(SessionID sessionID) { }
public void OnLogout(SessionID sessionID) { }
public void OnLogon(SessionID sessionID) { }
public void ToAdmin(Message message, SessionID sessionID) { }
#endregion
#region MessageCracker overloads
public void OnMessage(QuickFix.FIX40.NewOrderSingle n, SessionID s)
{
Symbol symbol = n.Symbol;
Side side = n.Side;
OrdType ordType = n.OrdType;
OrderQty orderQty = n.OrderQty;
Price price = new Price(DEFAULT_MARKET_PRICE);
ClOrdID clOrdID = n.ClOrdID;
switch (ordType.getValue())
{
case OrdType.LIMIT:
price = n.Price;
if (price.Obj == 0)
throw new IncorrectTagValue(price.Tag);
break;
case OrdType.MARKET: break;
default: throw new IncorrectTagValue(ordType.Tag);
}
QuickFix.FIX40.ExecutionReport exReport = new QuickFix.FIX40.ExecutionReport(
new OrderID(GenOrderID()),
new ExecID(GenExecID()),
new ExecTransType(ExecTransType.NEW),
new OrdStatus(OrdStatus.FILLED),
symbol,
side,
orderQty,
new LastShares(orderQty.getValue()),
new LastPx(price.getValue()),
new CumQty(orderQty.getValue()),
new AvgPx(price.getValue()));
exReport.Set(clOrdID);
if (n.IsSetAccount())
exReport.SetField(n.Account);
try
{
Session.SendToTarget(exReport, s);
}
catch (SessionNotFound ex)
{
Console.WriteLine("==session not found exception!==");
Console.WriteLine(ex.ToString());
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
public void OnMessage(QuickFix.FIX41.NewOrderSingle n, SessionID s)
{
Symbol symbol = n.Symbol;
Side side = n.Side;
OrdType ordType = n.OrdType;
OrderQty orderQty = n.OrderQty;
Price price = new Price(DEFAULT_MARKET_PRICE);
ClOrdID clOrdID = n.ClOrdID;
switch (ordType.getValue())
{
case OrdType.LIMIT:
price = n.Price;
if (price.Obj == 0)
throw new IncorrectTagValue(price.Tag);
break;
case OrdType.MARKET: break;
default: throw new IncorrectTagValue(ordType.Tag);
}
QuickFix.FIX41.ExecutionReport exReport = new QuickFix.FIX41.ExecutionReport(
new OrderID(GenOrderID()),
new ExecID(GenExecID()),
new ExecTransType(ExecTransType.NEW),
new ExecType(ExecType.FILL),
new OrdStatus(OrdStatus.FILLED),
symbol,
side,
orderQty,
new LastShares(orderQty.getValue()),
new LastPx(price.getValue()),
new LeavesQty(0),
new CumQty(orderQty.getValue()),
new AvgPx(price.getValue()));
exReport.Set(clOrdID);
if (n.IsSetAccount())
exReport.SetField(n.Account);
try
{
Session.SendToTarget(exReport, s);
}
catch (SessionNotFound ex)
{
Console.WriteLine("==session not found exception!==");
Console.WriteLine(ex.ToString());
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
public void OnMessage(QuickFix.FIX42.NewOrderSingle n, SessionID s)
{
Symbol symbol = n.Symbol;
Side side = n.Side;
OrdType ordType = n.OrdType;
OrderQty orderQty = n.OrderQty;
ClOrdID clOrdID = n.ClOrdID;
Price price = new Price(DEFAULT_MARKET_PRICE);
switch (ordType.getValue())
{
case OrdType.LIMIT:
price = n.Price;
if (price.Obj == 0)
throw new IncorrectTagValue(price.Tag);
break;
case OrdType.MARKET: break;
default: throw new IncorrectTagValue(ordType.Tag);
}
QuickFix.FIX42.ExecutionReport exReport = new QuickFix.FIX42.ExecutionReport(
new OrderID(GenOrderID()),
new ExecID(GenExecID()),
new ExecTransType(ExecTransType.NEW),
new ExecType(ExecType.FILL),
new OrdStatus(OrdStatus.FILLED),
symbol,
side,
new LeavesQty(0),
new CumQty(orderQty.getValue()),
new AvgPx(price.getValue()));
exReport.Set(clOrdID);
exReport.Set(orderQty);
exReport.Set(new LastShares(orderQty.getValue()));
exReport.Set(new LastPx(price.getValue()));
if (n.IsSetAccount())
exReport.SetField(n.Account);
try
{
Session.SendToTarget(exReport, s);
}
catch (SessionNotFound ex)
{
Console.WriteLine("==session not found exception!==");
Console.WriteLine(ex.ToString());
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
public void OnMessage(QuickFix.FIX43.NewOrderSingle n, SessionID s)
{
Symbol symbol = n.Symbol;
Side side = n.Side;
OrdType ordType = n.OrdType;
OrderQty orderQty = n.OrderQty;
Price price = new Price(DEFAULT_MARKET_PRICE);
ClOrdID clOrdID = n.ClOrdID;
switch (ordType.getValue())
{
case OrdType.LIMIT:
price = n.Price;
if (price.Obj == 0)
throw new IncorrectTagValue(price.Tag);
break;
case OrdType.MARKET: break;
default: throw new IncorrectTagValue(ordType.Tag);
}
QuickFix.FIX43.ExecutionReport exReport = new QuickFix.FIX43.ExecutionReport(
new OrderID(GenOrderID()),
new ExecID(GenExecID()),
new ExecType(ExecType.FILL),
new OrdStatus(OrdStatus.FILLED),
symbol, // Shouldn't be here?
side,
new LeavesQty(0),
new CumQty(orderQty.getValue()),
new AvgPx(price.getValue()));
exReport.Set(clOrdID);
exReport.Set(symbol);
exReport.Set(orderQty);
exReport.Set(new LastQty(orderQty.getValue()));
exReport.Set(new LastPx(price.getValue()));
if (n.IsSetAccount())
exReport.SetField(n.Account);
try
{
Session.SendToTarget(exReport, s);
}
catch (SessionNotFound ex)
{
Console.WriteLine("==session not found exception!==");
Console.WriteLine(ex.ToString());
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
public void OnMessage(QuickFix.FIX44.NewOrderSingle n, SessionID s)
{
Symbol symbol = n.Symbol;
Side side = n.Side;
OrdType ordType = n.OrdType;
OrderQty orderQty = n.OrderQty;
Price price = new Price(DEFAULT_MARKET_PRICE);
ClOrdID clOrdID = n.ClOrdID;
switch (ordType.getValue())
{
case OrdType.LIMIT:
price = n.Price;
if (price.Obj == 0)
throw new IncorrectTagValue(price.Tag);
break;
case OrdType.MARKET: break;
default: throw new IncorrectTagValue(ordType.Tag);
}
QuickFix.FIX44.ExecutionReport exReport = new QuickFix.FIX44.ExecutionReport(
new OrderID(GenOrderID()),
new ExecID(GenExecID()),
new ExecType(ExecType.FILL),
new OrdStatus(OrdStatus.FILLED),
symbol, //shouldn't be here?
side,
new LeavesQty(0),
new CumQty(orderQty.getValue()),
new AvgPx(price.getValue()));
exReport.Set(clOrdID);
exReport.Set(symbol);
exReport.Set(orderQty);
exReport.Set(new LastQty(orderQty.getValue()));
exReport.Set(new LastPx(price.getValue()));
if (n.IsSetAccount())
exReport.SetField(n.Account);
try
{
Session.SendToTarget(exReport, s);
}
catch (SessionNotFound ex)
{
Console.WriteLine("==session not found exception!==");
Console.WriteLine(ex.ToString());
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
public void OnMessage(QuickFix.FIX50.NewOrderSingle n, SessionID s)
{
Symbol symbol = n.Symbol;
Side side = n.Side;
OrdType ordType = n.OrdType;
OrderQty orderQty = n.OrderQty;
Price price = new Price(DEFAULT_MARKET_PRICE);
ClOrdID clOrdID = n.ClOrdID;
switch (ordType.getValue())
{
case OrdType.LIMIT:
price = n.Price;
if (price.Obj == 0)
throw new IncorrectTagValue(price.Tag);
break;
case OrdType.MARKET: break;
default: throw new IncorrectTagValue(ordType.Tag);
}
QuickFix.FIX50.ExecutionReport exReport = new QuickFix.FIX50.ExecutionReport(
new OrderID(GenOrderID()),
new ExecID(GenExecID()),
new ExecType(ExecType.FILL),
new OrdStatus(OrdStatus.FILLED),
side,
new LeavesQty(0),
new CumQty(orderQty.getValue()));
exReport.Set(clOrdID);
exReport.Set(symbol);
exReport.Set(orderQty);
exReport.Set(new LastQty(orderQty.getValue()));
exReport.Set(new LastPx(price.getValue()));
exReport.Set(new AvgPx(price.getValue()));
if (n.IsSetAccount())
exReport.SetField(n.Account);
try
{
Session.SendToTarget(exReport, s);
}
catch (SessionNotFound ex)
{
Console.WriteLine("==session not found exception!==");
Console.WriteLine(ex.ToString());
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
public void OnMessage(QuickFix.FIX40.News n, SessionID s) { }
public void OnMessage(QuickFix.FIX41.News n, SessionID s) { }
public void OnMessage(QuickFix.FIX42.News n, SessionID s) { }
public void OnMessage(QuickFix.FIX43.News n, SessionID s) { }
public void OnMessage(QuickFix.FIX44.News n, SessionID s) { }
public void OnMessage(QuickFix.FIX50.News n, SessionID s) { }
public void OnMessage(QuickFix.FIX40.OrderCancelRequest msg, SessionID s)
{
string orderid = (msg.IsSetOrderID()) ? msg.OrderID.Obj : "unknown orderID";
QuickFix.FIX40.OrderCancelReject ocj = new QuickFix.FIX40.OrderCancelReject(new OrderID(orderid), msg.ClOrdID);
ocj.CxlRejReason = new CxlRejReason(CxlRejReason.UNKNOWN_ORDER);
ocj.Text = new Text("Executor does not support order cancels");
try
{
Session.SendToTarget(ocj, s);
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
public void OnMessage(QuickFix.FIX41.OrderCancelRequest msg, SessionID s)
{
string orderid = (msg.IsSetOrderID()) ? msg.OrderID.Obj : "unknown orderID";
QuickFix.FIX41.OrderCancelReject ocj = new QuickFix.FIX41.OrderCancelReject(
new OrderID(orderid), msg.ClOrdID, msg.OrigClOrdID, new OrdStatus(OrdStatus.REJECTED));
ocj.CxlRejReason = new CxlRejReason(CxlRejReason.UNKNOWN_ORDER);
ocj.Text = new Text("Executor does not support order cancels");
try
{
Session.SendToTarget(ocj, s);
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
public void OnMessage(QuickFix.FIX42.OrderCancelRequest msg, SessionID s)
{
string orderid = (msg.IsSetOrderID()) ? msg.OrderID.Obj : "unknown orderID";
QuickFix.FIX42.OrderCancelReject ocj = new QuickFix.FIX42.OrderCancelReject(
new OrderID(orderid), msg.ClOrdID, msg.OrigClOrdID, new OrdStatus(OrdStatus.REJECTED), new CxlRejResponseTo(CxlRejResponseTo.ORDER_CANCEL_REQUEST));
ocj.CxlRejReason = new CxlRejReason(CxlRejReason.UNKNOWN_ORDER);
ocj.Text = new Text("Executor does not support order cancels");
try
{
Session.SendToTarget(ocj, s);
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
public void OnMessage(QuickFix.FIX43.OrderCancelRequest msg, SessionID s)
{
string orderid = (msg.IsSetOrderID()) ? msg.OrderID.Obj : "unknown orderID";
QuickFix.FIX43.OrderCancelReject ocj = new QuickFix.FIX43.OrderCancelReject(
new OrderID(orderid), msg.ClOrdID, msg.OrigClOrdID, new OrdStatus(OrdStatus.REJECTED), new CxlRejResponseTo(CxlRejResponseTo.ORDER_CANCEL_REQUEST));
ocj.CxlRejReason = new CxlRejReason(CxlRejReason.UNKNOWN_ORDER);
ocj.Text = new Text("Executor does not support order cancels");
try
{
Session.SendToTarget(ocj, s);
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
public void OnMessage(QuickFix.FIX44.OrderCancelRequest msg, SessionID s)
{
string orderid = (msg.IsSetOrderID()) ? msg.OrderID.Obj : "unknown orderID";
QuickFix.FIX44.OrderCancelReject ocj = new QuickFix.FIX44.OrderCancelReject(
new OrderID(orderid), msg.ClOrdID, msg.OrigClOrdID, new OrdStatus(OrdStatus.REJECTED), new CxlRejResponseTo(CxlRejResponseTo.ORDER_CANCEL_REQUEST));
ocj.CxlRejReason = new CxlRejReason(CxlRejReason.OTHER);
ocj.Text = new Text("Executor does not support order cancels");
try
{
Session.SendToTarget(ocj, s);
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
public void OnMessage(QuickFix.FIX50.OrderCancelRequest msg, SessionID s)
{
string orderid = (msg.IsSetOrderID()) ? msg.OrderID.Obj : "unknown orderID";
QuickFix.FIX50.OrderCancelReject ocj = new QuickFix.FIX50.OrderCancelReject(
new OrderID(orderid), msg.ClOrdID, msg.OrigClOrdID, new OrdStatus(OrdStatus.REJECTED), new CxlRejResponseTo(CxlRejResponseTo.ORDER_CANCEL_REQUEST));
ocj.CxlRejReason = new CxlRejReason(CxlRejReason.OTHER);
ocj.Text = new Text("Executor does not support order cancels");
try
{
Session.SendToTarget(ocj, s);
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
public void OnMessage(QuickFix.FIX40.OrderCancelReplaceRequest msg, SessionID s)
{
string orderid = (msg.IsSetOrderID()) ? msg.OrderID.Obj : "unknown orderID";
QuickFix.FIX40.OrderCancelReject ocj = new QuickFix.FIX40.OrderCancelReject(new OrderID(orderid), msg.ClOrdID);
ocj.CxlRejReason = new CxlRejReason(CxlRejReason.UNKNOWN_ORDER);
ocj.Text = new Text("Executor does not support order cancel/replaces");
try
{
Session.SendToTarget(ocj, s);
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
public void OnMessage(QuickFix.FIX41.OrderCancelReplaceRequest msg, SessionID s)
{
string orderid = (msg.IsSetOrderID()) ? msg.OrderID.Obj : "unknown orderID";
QuickFix.FIX41.OrderCancelReject ocj = new QuickFix.FIX41.OrderCancelReject(
new OrderID(orderid), msg.ClOrdID, msg.OrigClOrdID, new OrdStatus(OrdStatus.REJECTED));
ocj.CxlRejReason = new CxlRejReason(CxlRejReason.UNKNOWN_ORDER);
ocj.Text = new Text("Executor does not support order cancel/replaces");
try
{
Session.SendToTarget(ocj, s);
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
public void OnMessage(QuickFix.FIX42.OrderCancelReplaceRequest msg, SessionID s)
{
string orderid = (msg.IsSetOrderID()) ? msg.OrderID.Obj : "unknown orderID";
QuickFix.FIX42.OrderCancelReject ocj = new QuickFix.FIX42.OrderCancelReject(
new OrderID(orderid), msg.ClOrdID, msg.OrigClOrdID, new OrdStatus(OrdStatus.REJECTED), new CxlRejResponseTo(CxlRejResponseTo.ORDER_CANCEL_REPLACE_REQUEST));
ocj.CxlRejReason = new CxlRejReason(CxlRejReason.UNKNOWN_ORDER);
ocj.Text = new Text("Executor does not support order cancel/replaces");
try
{
Session.SendToTarget(ocj, s);
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
public void OnMessage(QuickFix.FIX43.OrderCancelReplaceRequest msg, SessionID s)
{
string orderid = (msg.IsSetOrderID()) ? msg.OrderID.Obj : "unknown orderID";
QuickFix.FIX43.OrderCancelReject ocj = new QuickFix.FIX43.OrderCancelReject(
new OrderID(orderid), msg.ClOrdID, msg.OrigClOrdID, new OrdStatus(OrdStatus.REJECTED), new CxlRejResponseTo(CxlRejResponseTo.ORDER_CANCEL_REPLACE_REQUEST));
ocj.CxlRejReason = new CxlRejReason(CxlRejReason.UNKNOWN_ORDER);
ocj.Text = new Text("Executor does not support order cancel/replaces");
try
{
Session.SendToTarget(ocj, s);
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
public void OnMessage(QuickFix.FIX44.OrderCancelReplaceRequest msg, SessionID s)
{
string orderid = (msg.IsSetOrderID()) ? msg.OrderID.Obj : "unknown orderID";
QuickFix.FIX44.OrderCancelReject ocj = new QuickFix.FIX44.OrderCancelReject(
new OrderID(orderid), msg.ClOrdID, msg.OrigClOrdID, new OrdStatus(OrdStatus.REJECTED), new CxlRejResponseTo(CxlRejResponseTo.ORDER_CANCEL_REPLACE_REQUEST));
ocj.CxlRejReason = new CxlRejReason(CxlRejReason.OTHER);
ocj.Text = new Text("Executor does not support order cancel/replaces");
try
{
Session.SendToTarget(ocj, s);
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
public void OnMessage(QuickFix.FIX50.OrderCancelReplaceRequest msg, SessionID s)
{
string orderid = (msg.IsSetOrderID()) ? msg.OrderID.Obj : "unknown orderID";
QuickFix.FIX50.OrderCancelReject ocj = new QuickFix.FIX50.OrderCancelReject(
new OrderID(orderid), msg.ClOrdID, msg.OrigClOrdID, new OrdStatus(OrdStatus.REJECTED), new CxlRejResponseTo(CxlRejResponseTo.ORDER_CANCEL_REPLACE_REQUEST));
ocj.CxlRejReason = new CxlRejReason(CxlRejReason.OTHER);
ocj.Text = new Text("Executor does not support order cancel/replaces");
try
{
Session.SendToTarget(ocj, s);
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
}
// FIX40-41 don't have rejects
public void OnMessage(QuickFix.FIX42.BusinessMessageReject n, SessionID s) { }
public void OnMessage(QuickFix.FIX43.BusinessMessageReject n, SessionID s) { }
public void OnMessage(QuickFix.FIX44.BusinessMessageReject n, SessionID s) { }
public void OnMessage(QuickFix.FIX50.BusinessMessageReject n, SessionID s) { }
#endregion //MessageCracker overloads
}
public class QuickFixMainDriver : ITopNugetPackages
{
private const string HttpServerPrefix = "http://127.0.0.1:5080/";
private readonly string cfgPath = Directory.GetCurrentDirectory() + @"\..\..\..\Resources\simpleacc.cfg";
private readonly string exePath = Directory.GetCurrentDirectory() + @"\..\..\..\Resources\executor.cfg";
private readonly string trdPath = Directory.GetCurrentDirectory() + @"\..\..\..\Resources\tradeclient.cfg";
public QuickFixMainDriver()
{
}
/// <summary>
/// SimpleAcceptor
///
/// Server that accepts messages from clients and print them
/// </summary>
public void SimpleAcceptor()
{
Console.WriteLine("=============");
Console.WriteLine("This is only an example program.");
Console.WriteLine("It's a simple server (e.g. Acceptor) app that will let clients (e.g. Initiators)");
Console.WriteLine("connect to it. It will accept and display any application-level messages that it receives.");
Console.WriteLine("Connecting clients should set TargetCompID to 'SIMPLE' and SenderCompID to 'CLIENT1' or 'CLIENT2'.");
Console.WriteLine("Port is 5001.");
Console.WriteLine("(see simpleacc.cfg for configuration details)");
Console.WriteLine("=============");
//if (args.Length != 1)
//{
// Console.WriteLine("usage: SimpleAcceptor CONFIG_FILENAME");
// System.Environment.Exit(2);
//}
try
{
SessionSettings settings = new SessionSettings(cfgPath);
IApplication app = new SimpleAcceptorApp();
IMessageStoreFactory storeFactory = new FileStoreFactory(settings);
ILogFactory logFactory = new FileLogFactory(settings);
IAcceptor acceptor = new ThreadedSocketAcceptor(app, storeFactory, settings, logFactory);
acceptor.Start();
Console.WriteLine("press <enter> to quit");
Console.Read();
acceptor.Stop();
}
catch (System.Exception e)
{
Console.WriteLine("==FATAL ERROR==");
Console.WriteLine(e.ToString());
}
}
/// <summary>
/// Executor
///
/// Performs trade/order execution sent by client
/// </summary>
public void Executor()
{
Console.WriteLine("=============");
Console.WriteLine("This is only an example program, meant to be used with the TradeClient example.");
Console.WriteLine("=============");
//if (args.Length != 1)
//{
// Console.WriteLine("usage: Executor CONFIG_FILENAME");
// System.Environment.Exit(2);
//}
try
{
SessionSettings settings = new SessionSettings(exePath);
IApplication executorApp = new Executor();
IMessageStoreFactory storeFactory = new FileStoreFactory(settings);
ILogFactory logFactory = new FileLogFactory(settings);
ThreadedSocketAcceptor acceptor = new ThreadedSocketAcceptor(executorApp, storeFactory, settings, logFactory);
HttpServer srv = new HttpServer(HttpServerPrefix, settings);
acceptor.Start();
srv.Start();
Console.WriteLine("View Executor status: " + HttpServerPrefix);
Console.WriteLine("press <enter> to quit");
Console.Read();
srv.Stop();
acceptor.Stop();
}
catch (System.Exception e)
{
Console.WriteLine("==FATAL ERROR==");
Console.WriteLine(e.ToString());
}
}
/// <summary>
/// Trade Client
///
/// Client program that sends trade request to Executor/Server for order processing
/// </summary>
public void TradeClient()
{
Console.WriteLine("=============");
Console.WriteLine("This is only an example program, meant to run against the Executor or SimpleAcceptor example programs.");
Console.WriteLine();
Console.WriteLine(" ! ! !");
Console.WriteLine(" DO NOT USE THIS ON A COMMERCIAL FIX INTERFACE! It won't work and it's a bad idea!");
Console.WriteLine(" ! ! !");
Console.WriteLine();
Console.WriteLine("=============");
//if (args.Length != 1)
//{
// System.Console.WriteLine("usage: TradeClient.exe CONFIG_FILENAME");
// System.Environment.Exit(2);
//}
//string file = args[0];
try
{
QuickFix.SessionSettings settings = new QuickFix.SessionSettings(trdPath);
TradeClientApp application = new TradeClientApp();
QuickFix.IMessageStoreFactory storeFactory = new QuickFix.FileStoreFactory(settings);
QuickFix.ILogFactory logFactory = new QuickFix.ScreenLogFactory(settings);
QuickFix.Transport.SocketInitiator initiator = new QuickFix.Transport.SocketInitiator(application, storeFactory, settings, logFactory);
// this is a developer-test kludge. do not emulate.
application.MyInitiator = initiator;
initiator.Start();
application.Run();
initiator.Stop();
}
catch (System.Exception e)
{
Console.WriteLine(e.Message);
Console.WriteLine(e.StackTrace);
}
Environment.Exit(1);
}
// Sample to use QuickFix
// Configure CFG files to use which version, such as 4.2
public void DoIt()
{
Console.WriteLine("Run as Simple Server or Executor Server");
Console.WriteLine("Note: TradeClient CFG must be configured correctly");
Console.WriteLine("1 = Simple");
Console.WriteLine("2 = Executor");
var rd = Console.ReadLine();
if (rd.StartsWith("1"))
{
Console.WriteLine("Starting Simple Server");
Task.Run(() => SimpleAcceptor());
}
else
{
// Executor
Console.WriteLine("Starting Executor");
Task.Run(() => Executor());
}
Thread.Sleep(3000);
//// Trade Client
//Console.WriteLine("Starting Client");
TradeClient();
}
}
}