• Version 1.15.2
Show / Hide Table of Contents

Throttling Buy Side Sample

Source code


using System;
using OnixS.Fix;
using System.Globalization;
using System.IO;
using OnixS.Fix.Fix44;
using System.Net;
using NLog.Extensions.Logging;
using System.Threading;

namespace ThrottlingBuySide
{
    /// <summary>
    /// Establishes the FIX session as Initiator.
    /// </summary>
    internal static class Initiator
    {
        private const ProtocolVersion fixVersion = ProtocolVersion.Fix44;
        private static string GetLicenseStoreFolder()
        {
            string path = Path.Join(AppContext.BaseDirectory, "../../../../../license");

            if (Directory.Exists(path))
                return path;

            // expecting it run after dotnet publish using default paths
            return Path.Join(AppContext.BaseDirectory, "../../../../../../license");
        }

        private static Message CreateOrderMessage(IMessageInfoDictionary dictionary)
        {
            var order = new Message(MsgType.NewOrderSingle, dictionary);

            order.Set(Tag.HandlInst, HandlInst.AutoExecPub)
                 .Set(Tag.ClOrdID, "Unique identifier for Order")
                 .Set(Tag.Symbol, "TSLA")
                 .Set(Tag.Side, Side.Buy)
                 .Set(Tag.OrderQty, 1000)
                 .Set(Tag.OrdType, OrdType.Market)
                 .Set(Tag.TransactTime, DateTime.UtcNow.ToString("yyyyMMdd-HH:mm:ss", CultureInfo.InvariantCulture));

#if DEBUG
            try
            {
                order.Validate();
            }
            catch (Exception ex)
            {
                Console.WriteLine("Exception on order validation: " + ex);
            }
#endif

            return order;
        }

        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        private static int Main()
        {
            Console.WriteLine("Throttling Buy Side Sample");

            try
            {
                var settings = new EngineSettings()
                {
                    LicenseStore = GetLicenseStoreFolder(),
                    LoggerProvider = new NLogLoggerProvider()
                };

                Engine.Init(settings);

                var dictionary = fixVersion.ToDictionary();

                using (Session session = new("ThrottlingBuySide", "ThrottlingSellSide", dictionary))
                {
                    const int MessagesPerSecondLimitDelta = 3;
                    const int MessagesPerSecondLimit = 10 - MessagesPerSecondLimitDelta;
                    TimeSpan ThrottlingInterval = TimeSpan.FromSeconds(1);
                    AutoResetEvent orderHandlingComplete = new AutoResetEvent(false);
                    int totalOrdersHandled = 0;
                    int totalMessagesRejected = 0;

                    session.ThrottlingLimit(MessagesPerSecondLimit, ThrottlingInterval);

                    session.InboundApplicationMessage += (object sender, InboundMessageEventArgs e) =>
                    {
                        Console.WriteLine("Inbound application-level message:\n" + e.Message);

                        if (e.Message.Type == MsgType.ExecutionReport)
                        {
                            ++totalOrdersHandled;
                            orderHandlingComplete.Set();
                        }
                    };

                    session.InboundSessionMessage += (object sender, InboundMessageEventArgs e) =>
                    {
                        Console.WriteLine("Inbound session-level message:\n" + e.Message);

                        if (e.Message.Type == MsgType.Reject)
                        {
                            ++totalMessagesRejected;
                            Console.WriteLine("Rejection " + totalMessagesRejected + ": message " + e.Message.Get(Tag.RefSeqNum) + " rejected.");
                            orderHandlingComplete.Set();
                        }
                    };

                    session.StateChanged += (object sender, SessionStateChangeEventArgs e) =>
                    {
                        Console.WriteLine("Session state: " + e.NewState);
                    };

                    session.Error += (object sender, SessionErrorEventArgs e) =>
                    {
                        Console.WriteLine("Error: " + e.ToString());
                    };

                    session.Warning += (object sender, SessionWarningEventArgs e) =>
                    {
                        Console.WriteLine("Warning: " + e.ToString());
                    };

                    session.LogonAsInitiator(IPAddress.Loopback, 10450);

                    Console.WriteLine("Press any key to send throttled orders...");

                    Console.ReadKey(true);

                    Message order = CreateOrderMessage(dictionary);

                    const int NumOfMessages = 100;

                    for (int msgCounter = 0; msgCounter < NumOfMessages; ++msgCounter)
                    {
                        session.Throttle();
                        session.Send(order);
                        orderHandlingComplete.WaitOne();
                    }

                    Console.WriteLine("Orders handled: " + totalOrdersHandled + ", messages rejected: " + totalMessagesRejected);
                    Console.WriteLine("Press any key to disconnect the session and terminate the application.");

                    Console.ReadKey(true);

                    session.Logout("The session is disconnected by BuySide");
                }

                Engine.Shutdown();
            }
            catch (Exception ex)
            {
                Console.WriteLine("Exception: " + ex);

                return 1;
            }
            finally
            {
                // From https://github.com/NLog/NLog/wiki/Tutorial:
                // NET Application running on Mono / Linux are required to stop threads / timers before entering application shutdown phase.
                // Failing to do this will cause unhandled exceptions and segmentation faults, and other unpredictable behavior.
                NLog.LogManager.Shutdown(); // Flush and close down internal threads and timers
            }

            return 0;
        }
    }
}

In this article
Back to top Copyright © Onix Solutions.
Generated by DocFX