HFT: откуда берутся тормоза, и как их мониторить

   Вот диаграмма того откуда берутся тормоза в наших роботах.


первоисточник: https://www.cisco.com/application/pdf/en/us/guest/netsol/ns407/c654/ccmigration_09186a008091d542.pdf

Автозапуск экспорта всех таблиц по DDE в Quik на C#

     Достаточно часто при написании привода или полностью автоматизированной системы работающей в тандеме с Quik необходимо не только уметь отправлять сделки в торговую систему, но и получать из нее различную торговую информацию. К сожалению trans2quik.dll не предоставляет возможности получения какой либо информации о котировках. Поэтому большинство пользователей делают это через квиковские DDE или ODBC. Первый мне кажется более простым в и понятным в реализации. Необходимо создать свой собственный DDE сервер для приема информации(об этом будет рассказано в следующих постах), после чего в Quik настраиваются таблицы которые будут выводиться. Но вот незадача, получается что при каждом запуска нашей программы придется заходить в Quik и запускать экспорт таблиц. Мне кажется это не очень удобно, но никакой возможности это сделать через trans2quik.dll нет.
     Ниже представлен небольшой код, который находит все запущенные терминалы Quik и запускает экспорт всех таблиц путем нажатия пункта меню 'Экспорт Данных -> Начать экспорт таблиц по DDE'.
     Код не требует никаких дополнительных библиотек, вам просто достаточно добавить этот код в свой проект.

using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Text;

namespace QuikIntegration.dde
{
    public class QuikUtil
    {
        private static string _exportMenuKey = "Экспорт данных";
        private static string _stopExportMenuItem = "Остановить экспорт таблиц по &DDE";
        private static string _startExportByDDEMenuItem = "Начать экспорт таблиц по &DDE";

        // ReSharper disable InconsistentNaming
        [DllImport("user32.dll")]
        static extern IntPtr GetMenu(IntPtr hWnd);

        [DllImport("user32.dll")]
        static extern IntPtr GetSubMenu(IntPtr hMenu, int nPos);

        [DllImport("user32.dll")]
        static extern int GetMenuItemCount(IntPtr hMenu);

        [DllImport("user32.dll")]
        static extern int GetMenuString(IntPtr hMenu, uint uIDItem, StringBuilder lpString, int nMaxCount, uint uFlag);

        [DllImport("user32.dll")]
        static extern uint GetMenuItemID(IntPtr hMenu, int nPos);

        [return: MarshalAs(UnmanagedType.Bool)]
        [DllImport("user32.dll", SetLastError = true)]
        static extern bool PostMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);

        private const UInt32 MF_BYPOSITION = 0x00000400;

        public static bool StartDDE()
        {
            IntPtr[] quikWindows = FindQuikWindow();
            if (quikWindows.Length == 0)
            {
                return false;
            }
            foreach (var quikWindow in quikWindows)
            {
                IntPtr mainMenu = GetMenu(quikWindow);
                int exportMenuIndex = (int)FindMenuItemByPart(mainMenu, _exportMenuKey);
                IntPtr exportMenu = GetSubMenu(mainMenu, exportMenuIndex);

                uint exportIndex = 6; // FindMenuItemByPart(exportMenu, _startExportByDDEMenuItem);
                uint menuItem = GetMenuItemID(exportMenu, (int)exportIndex);
                PostMessage(quikWindow, 0x111, (IntPtr)menuItem, (IntPtr)0);
            }

            return true;
        }

        public static bool StopDDE()
        {
            IntPtr[] quikWindows = FindQuikWindow();
            if (quikWindows.Length == 0)
            {
                return false;
            }

            foreach (var quikWindow in quikWindows)
            {
                IntPtr mainMenu = GetMenu(quikWindow);
                int exportMenuIndex = (int)FindMenuItemByPart(mainMenu, _exportMenuKey);
                IntPtr exportMenu = GetSubMenu(mainMenu, exportMenuIndex);

                uint exportIndex = 7; // FindMenuItemByPart(exportMenu, _stopExportMenuItem);
                uint menuItem = GetMenuItemID(exportMenu, (int)exportIndex);
                PostMessage(quikWindow, 0x111, (IntPtr)menuItem, (IntPtr)0);
            }
            return true;
        }

        private static IntPtr[] FindQuikWindow()
        {
            Process[] processes = Process.GetProcessesByName("info");
            IntPtr[] result = new IntPtr[processes.Length];
            for (int i = 0; i < processes.Length; i++)
            {
                result[i] = processes[i].MainWindowHandle;
            }
            return result;
        }

        private static uint FindMenuItemByPart(IntPtr menu, string name)
        {
            int menuItemsCount = GetMenuItemCount(menu);
            for (uint menuIndex = 0; menuIndex < menuItemsCount; menuIndex++)
            {
                StringBuilder result = new StringBuilder();
                GetMenuString(menu, menuIndex, result, 1024, MF_BYPOSITION);
                string buffer = result.ToString();
                if (buffer.Contains(name))
                {
                    return menuIndex;
                }
            }
            return 0;
        }
    }
    // ReSharper restore InconsistentNaming
}


Для того, чтобы запустить экспорт всех таблиц нужно выполнить комманду:
QuikUtil.StartDDE();
остановить
QuikUtil.StopDDE();

Зачем мне нужен этот блог

     Этот блог призван помочь мне структурировать свои знания о трейдинге, а в частности такой его разновидности как алгоритмический или автотрейдинг. А если мои записки когда нибудь кому-то помогут, то это будет замечательно.
сотрудничество