Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?
17.04.2025, 18:56:13
Начало Помощь Поиск Войти Регистрация
Новости: ООО «Скрин маркет системз», правообладатель программы «Система брокерского обслуживания «TRANSAQ» официально заявляет, что не ведет никакой деятельности в мессенджерах или социальных сетях. 
Подробности на нашем сайте  WWW.TRANSAQ.RU.

Transaq  |  СБО "Transaq"  |  TRANSAQ Connector  |  Topic: Получение исторических данных gethistorydata « предыдущая тема следующая тема »
Страниц: [1] 2 Печать
Автор Тема: Получение исторических данных gethistorydata  (Прочитано 9349 раз)
Atrem
Guest


Email
« : 29.02.2020, 17:05:43 »

Здравствуйте.
Подскажите никак не могу разобраться. Как обрабатывать ответ от функций и где искать данные.

Скачал с сайта Финам пример на C#  в нем и пытаюсь разобраться с принципом работы коннектора.
Вот составил я запрос 

string cmd = "<command id=\"gethistorydata\">" +
                  "<security>" +
                        "<board>FUT</board>" +
                        "<seccode>RIH0</seccode>" +
                  "</security>" +
                  "<period>1</period>" +
                  "<count>1000</count>" +
                  "<reset>false</reset>" +
                  "</command>";
Отправил запрос:
string res = TXmlConnector.ConnectorSendCommand(cmd);

В переменной res находится только результат операции true, а где данные не могу понять. Подскажите, пожалуйста как их получить?
Вижу данные в лог файле а как они туда попали не пойму.

Записан
Atrem
Guest


Email
« Ответ #1 : 01.03.2020, 03:44:41 »

Уважаемые разработчики TRANSAQ!

По моему представлению, чем больше человек пользуются Вашей программой, тем для Вас лучше. Ситуация следующая, QUIK полетел всерьез и похоже надолго. Возможно Вы в курсе. В двух словах примерно после 17 часов перестает поступать биржевая информация. Могу сказать про двух брокеров ВТБ и Финам. В ВТБ данная проблема существует уже пару месяцев все сервера кроме резервного не работают. С 26.02.2020 такие же проблемы начались и в Финам, но у них еще хуже вообще все сервера не работаю, в том числе и резервные. Поскольку ВТБ уже пару месяцев не могут разобраться с этой проблемой, Финам тоже врятли быстро с ней разберется. Для меня эта проблема стала очень серьезной по той причине, что у меня торгуют роботы в QUIK на QLua, а поскольку данные в QUIK стоят, то и торговать невозможно. Встал вопрос, нужно отказываться от QUIK и на что-то переходить. В тех поддержке Финам мне посоветовали TRANSAQ connector. Слышал про него и ранее, но необходимости не было, поскольку вполне устраивал QUIK и QLau. Думаю ага хорошо сейчас скачаю документацию по TRANSAQ connector и перенесу на него своих роботов используя C#. Открыв документацию понял, что ничерта не понимаю или не знаю.
Открываю Visual Studion, первым делом думаю, добавлю библиотеку txmlconnector.dll, Reference> Add Reference, не добавляется ошибка, значит это не библиотека .NET, проблема 1.
Я понимаю, что Вы в TRANSAQ "лютые" программисты и для Вас это вообще не проблема, но вот для Ваших пользователей это проблема, может ошибаюсь, а может и нет процентов 90 людей пишущих торговых роботов вообще не программисты а самоучки.

Ладно, на сайте Финам есть пример C#  TRANSAQ connector, скачиваю, открываю, Solution. Пару тысяч строк кода и штук двадцать срок комментариев – не густо.
Вроде как нашел, как подключить библиотеку

[DllImport("txmlconnector.dll", CallingConvention = CallingConvention.StdCall)]
private static extern IntPtr SendCommand(IntPtr pData);

Но вот почему-то нужно для каждой функции прописывать данные строки

[DllImport("txmlconnector.dll", CallingConvention = CallingConvention.StdCall)]
private static extern bool FreeMemory(IntPtr pData);

Думаю, ладно попробую здесь же хотя бы получить цену закрытия последней свечи.
В мануале написано

Функция SendCommand Служит для передачи команд Коннектору. Возвращаемое значение Указатель на XML-сообщение, содержащее данные об успешности или неуспешности выполнения команды.

В мануале написано. Чтобы получить данные за последние N свечей передаем
<command id="gethistorydata"><security><board> идентификатор режима торгов </board><seccode> код инструмента </seccode></security><period>идентификатор периода</period><count>количество свечей</count><reset>true/false</reset></command>
Результатом работы является структура вида candles. Исторические данные
<candles secid=".." period="идентификатор периода" status=".."board="идентификатор режима торгов" seccode="код инструмента"><candle date="дата" open="…" high="…" low="..." close="…"volume="…" oi="open_interest"/></candles>
Вроде все просто.
Что? Какая еще структура candles? Где ее искать? Функция SendCommand возвращает только true или false.
Ладно идем в Яндекс, запрос C# структуры. На сайте https://docs.microsoft.com/ находим

public struct Coords
{
   public Coords (double x, double y)
{
        X = x;
        Y = y;
    }
    public double X { get; }
    public double Y { get; }
    public override string ToString() => $"({X}, {Y})";
}

Это ничего мне не дало.

Дальше опять в Яндекс, запрос пример TRANSAQ connector, вот теперь находится Ваш форум и один единственный пример http://www.transaq.ru/forum/index.php?topic=804.0 вообще без комментариев к коду и на C++.
Есть еще один пример https://farique.livejournal.com/91066.html , цитата " Вот, допустим, в нашей программе мы получили данные string data. Это данные от сервера в формате строки в виде xml " – отлично, Где эти данные? Как их получить? Если данные есть, то уже не составит труда с ними разобраться.
Код из примера с сайта Финам

public static String ConnectorSendCommand(String command)
{
IntPtr pData = MarshalUTF8.StringToHGlobalUTF8(command);         
IntPtr pResult = SendCommand(pData);
String result = MarshalUTF8.PtrToStringUTF8(pResult);
Marshal.FreeHGlobal(pData);
FreeMemory(pResult);
return result;
}

В этом примере функция используется для отправки команд в connect изходя из кода не понятно а данные то где?
В этом же примере есть функция
public static string Transaq_HandleData(string data)
Вот в нее поступают данные в переменной data находятся запрашиваемые свечки
В этой функции есть строка log.WriteLog("ServerData: " + data); и в логе данные отображаются.
Функция Transaq_HandleData в свою очередь вызывается из функции

static bool myCallBack(IntPtr pData)
{
 string res;
String data = MarshalUTF8.PtrToStringUTF8(pData);
FreeMemory(pData);
res = Transaq_HandleData(data);
 if (res == "server_status") New_Status();
 return true;
}

А функция myCallBack неизвестно откуда вызывается. Так я и не нашел откуда берется data.
Вобщем тупик конкретный.


Учитывая, что на просторах Интернета можно найти лишь несколько примеров и то очень кратеньких складывается ощущение, что "вообще никто" не знает, как он там работает TRANSAQ connector.
Уважаемые разработчики, пожалуйста, напишите для таких недопрограммистов как я,  примеры или инструкции как работать с TRANSAQ connector.
1.   Как правильно подключить библиотеку.
2.   Как правильно отправлять запросы.
3.   Как правильно получать ответ, данные  и самое главное, где их получать.
4.   Несколько примеров от и до, как запросить и получить данные с графика, стакана, таблицы.
5.   Как работать с функциями колбека.

У QLua и TSLaba такие примеры есть, изучить их и использовать становится гораздо проще.

С уважением, Артем.
Записан
klimov
Разработчики
Hero Member
*****
Сообщений: 815


Просмотр профиля Email
« Ответ #2 : 11.03.2020, 09:41:59 »

Артем,
возможно вам будет проще использовать ATF
http://www.transaq.ru/mts

С ним, правда, есть тоже "нюанс"
http://www.transaq.ru/forum/index.php?topic=2820.0.

Записан
Atrem
Guest


Email
« Ответ #3 : 11.03.2020, 11:02:15 »

Уже разобрался, почти, во всех премудростях TRANSAQ Connector. Просто потратил на это кучу времени, была бы подробная инструкция, потратил бы в 2 раза меньше. Вот не пойму почему ее до сих пор нет.
ATF посмотрел, пока не совсем понял глубину ее возможностей.  С учетом того, что ее более не поддерживают считаю что использовать ее нет смысла.
Klimov, скажите Вы знакомы с TRANSAQ Connector, используете его в торговли?
Записан
klimov
Разработчики
Hero Member
*****
Сообщений: 815


Просмотр профиля Email
« Ответ #4 : 11.03.2020, 13:05:42 »

Коннектор в торговле не использую, но более-менее с ним знаком
Записан
Atrem
Guest


Email
« Ответ #5 : 11.03.2020, 13:13:15 »

Скажите, не используете коннектор, потому что не торгуете роботами или пользуетесь другими средствами автоматизации торговли?
Спрашиваю потому, что с января месяца мучаюсь с QUIK у них похоже большие проблемы толи с нагрузкой на сервера, толи они намудрили что-то в очередном обновлении. Причем проблемы наблюдаются у разных брокеров, в моем случае ВТБ и Финам. 
На протяжении 5 лет торгую роботами на Lua. И вот встал вопрос про смену платформы, поскольку к QUIK доверия больше нет.
Записан
Atrem
Guest


Email
« Ответ #6 : 11.03.2020, 13:49:06 »

У меня сложности в понимании коннектора возникли по сути не по самому коннектору, а его реализации на C#. Единственный пример, который можно найти в Интернете, пример от Финама (https://www.finam.ru/howtotrade/tconnector00001/), похоже писал не один человек, а команда и пользователю не очень глубоко знакомому с C# достаточно сложно в нем разобраться, хотя по факту там ничего сверх сложного вроде нет, но достаточно все запутано. Не все удалось понять на 100%, например алгоритм подключения самой библиотеки:

        [DllImport("txmlconnector.dll", CallingConvention = CallingConvention.StdCall)]
        private static extern bool SetCallback(CallBackDelegate pCallback); // тут понятно, делегируем функцию Колбек из библиотеки в свою функцию
     
        [DllImport("txmlconnector.dll", CallingConvention = CallingConvention.StdCall)]
   private static extern IntPtr SendCommand(IntPtr pData); // тут не понятно что же такое IntPtr, поискал почитал понятнее не стало использую как есть без понимания
Возможно есть какой-то другой более простой способ, ведь насколько я понимаю обмен XML сообщениями там все просто отправил форматированную строку, получил форматированную строку. Может кто подскажет.

        [DllImport("txmlconnector.dll", CallingConvention = CallingConvention.StdCall)]
   private static extern bool FreeMemory(IntPtr pData);

        [DllImport("TXmlConnector.dll", CallingConvention = CallingConvention.Winapi)]
        private static extern IntPtr Initialize(IntPtr pPath, Int32 logLevel);

        [DllImport("TXmlConnector.dll", CallingConvention = CallingConvention.Winapi)]
        private static extern IntPtr UnInitialize();

        [DllImport("TXmlConnector.dll", CallingConvention = CallingConvention.Winapi)]
        private static extern IntPtr SetLogLevel(Int32 logLevel);

Вопрос к разработчикам.
Скажите нет ли возможности добавить в запрос к коннектору и в ответ коннектора пользовательский атрибут или узел идентификатор?
Т.е.  отправляю запрос и присваиваю ему уникальный идентификатор, далее отлавливаю в функции обратного вызова ответ, уже по своему идентификатору. По моему мнению это сильно упростит логику обработки ответов. Колбек же, вызывается постоянно, при получении любой информации, при наличии своего идентификатора пользователю будет необходимо, в ответе, всего лишь сравнить один параметр, а не писать кучу условий чтобы идентифицировать ответ.
Записан
klimov
Разработчики
Hero Member
*****
Сообщений: 815


Просмотр профиля Email
« Ответ #7 : 11.03.2020, 13:56:08 »

У меня есть простенький робот на ATF
Думаю, на коннекторе его написать было бы сложнее
Записан
Сорвачев Сергей
Разработчики
Jr. Member
*****
Сообщений: 54


Просмотр профиля Email
« Ответ #8 : 11.03.2020, 14:23:56 »

У меня сложности в понимании коннектора возникли по сути не по самому коннектору, а его реализации на C#.
Эти сложности связаны с тем что библиотека txmlconnector написана на C++, у нее плюсовый интерфейсы и типы, которые при использовании в C# необходимо мэтчить ("маршаллить") с шарповыми.

[DllImport("txmlconnector.dll", CallingConvention = CallingConvention.StdCall)]
private static extern bool SetCallback(CallBackDelegate pCallback);
Это всего лишь декларация (описание) функции в языке C#, которая экспортируется из библиотеки txmlconnector. Вам ее особо понимать не надо, надо использовать саму функцию с указанным набором аргументов.

// тут понятно, делегируем функцию Колбек из библиотеки в свою функцию
Callback-функция - как можно догадаться, есть функция обратного вызова. То есть мы указываем библиотеке txmlconnector (см функцию SetCallback) что хотим получать данные от нее в нашу функцию, которую пишем в своем приложении. Данные, приходящие в колбек - это результаты выполнения запросов, которые пораждаются функцией SendCommand. Как callback-функция будет вызываться и откуда в ней берутся данные вас волновать не должно. Будем считать библиотеку черным ящиком, который что-то генерирует и оповещает нас об этом. Главное что нужно знать и это указано в документации - callback функцию нельзя блокировать на длительное время и делать в ней сложную обработку данных. То есть ее назначение принять данные и положить, например, в очередь для дальнейшей обработки.
Из документации:
"В callback функции не должны выполняться операции, которые могут заблокировать поток на длительное время. Также из callback функции не следует вызывать управляющие функции библиотеки: Initialize, UnInitialize, SetCallback, SetCallbackEx, SendCommand, так как это может привести к взаимной блокировке потоков библиотеки."

// тут не понятно что же такое IntPtr, поискал почитал понятнее не стало использую как есть без понимания
Это шарповый тип, который представляет из себя указатель. Так как в C# нет указателей, как в C++, их надо мэппить на шарповые типы.
Их MSDN: "Тип IntPtr может использоваться языками, поддерживающими указатели, и как распространенный способ обращения к данным между языками, которые не поддерживают указатели."
Пример маршаллинга класса: https://www.codeproject.com/Articles/18032/How-to-Marshal-a-C-Class

Возможно есть какой-то другой более простой способ
Пишите на C++. Как минимум потребность в маршаллинге исчезнет.

Вопрос к разработчикам.
Такой возможности нет. Есть возможность (см. функцию SetCallback) задать глобальный идентификатор на каждый callback (это сделано для проектов, в которых несколько библиотек пишут в одну callback-функцию).
« Последнее редактирование: 11.03.2020, 14:31:56 от Сорвачев Сергей » Записан
Atrem
Guest


Email
« Ответ #9 : 11.03.2020, 14:31:18 »

Спасибо за ответы!
Буду разбираться дальше.
По поводу "глобальный идентификатор на каждый callback" отдельное спасибо.
Писать на C++ для меня ну вообще крайне сложно, с этим языком я пытаюсь разобраться очень давно и вообще никак не догоняю.
Записан
Сорвачев Сергей
Разработчики
Jr. Member
*****
Сообщений: 54


Просмотр профиля Email
« Ответ #10 : 11.03.2020, 14:37:31 »

Спасибо за ответы!
Буду разбираться дальше.
По поводу "глобальный идентификатор на каждый callback" отдельное спасибо.
Писать на C++ для меня ну вообще крайне сложно, с этим языком я пытаюсь разобраться очень давно и вообще никак не догоняю.

Можно, например, Python адаптировать под работу с txmlconnector`ом. Но в данном случае также придется мэтчить сишные типы с питоновскими.
Записан
dimkin
Newbie
*
Сообщений: 1


Просмотр профиля Email
« Ответ #11 : 03.04.2021, 10:40:50 »

Подскажите кто разбирается в Delphi. Вот программа, успешно подключается к серверу Финам. Но почему-то в функцию колбэк приходят кракозябры.
В логах видно, что данные приходят успешно. Значит что-то не верно с функцией CallBack.

type
  Tcallback=function(pData:PAnsiChar):boolean;

type
  TForm1 = class(TForm)
    SpeedButton1: TSpeedButton;
    Memo1: TMemo;
    SpeedButton2: TSpeedButton;
    DisconnectButton3: TSpeedButton;
    SpeedButton4: TSpeedButton;
    memo2: TMemo;
    TestButton3: TSpeedButton;
    procedure SpeedButton1Click(Sender: TObject);
    procedure SpeedButton2Click(Sender: TObject);
    procedure DisconnectButton3Click(Sender: TObject);
    procedure SpeedButton4Click(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure TestButton3Click(Sender: TObject);
  private
    { Private declarations }

  public
    { Public declarations }

  end;

var
  Form1: TForm1;


implementation

    function Initialize(logPath:PAnsiChar;loglevel:integer):PAnsiChar; stdcall;    external 'txmlconnector.dll';
    function UnInitialize:PAnsiChar;                      stdcall;    external 'txmlconnector.dll';
    function SendCommand(pData: PAnsiChar): PAnsiChar;    stdcall;    external 'txmlconnector.dll';
    function SetCallback(pCallback: Tcallback): boolean;  stdcall;    external 'txmlconnector.dll';
    function FreeMemory(pData: PAnsiChar): boolean;       stdcall;    external 'txmlconnector.dll';


{$R *.dfm}

{ TForm1 }

// Описываем функцию для отправки команды и получения результата:
function sendCmd(command: string): string;
var
    cmd, ans: PAnsiChar;
begin
    cmd := PAnsiChar(AnsiToUtf8(command));
    ans := SendCommand(cmd);
    Result := Utf8ToAnsi(ans);
    FreeMemory(ans);
end;

// Описываем колбэк функцию:
function funcCallBack(pData: PAnsiChar): boolean;
var
    str: string;
begin
    str := Utf8ToAnsi(pData);
    FreeMemory(pData);
    //Делаем что угодно с str
    form1.memo2.Lines.Add(str);
    if form1.memo2.Lines.Count>100 then form1.memo2.Clear;

end;


procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  DisconnectButton3Click(Sender);
  UnInitialize;
  sleep(1000);
end;

procedure TForm1.SpeedButton1Click(Sender: TObject);
var
    cmd, ans: string;
    pData,pRes: PAnsiChar;
    Res:string;
begin
// Перед отправкой команд устанавливаем колбэк функцию:
    pData:= PAnsiChar('D:\delphi\2021\CnnectorTest\log\');
    pRes:= Initialize(pData,2);
    Res:=Utf8ToAnsi(pRes);
    SetCallback(@funcCallBack);

// Отправляем команды
   cmd := Sconnect;
   ans := sendCmd(cmd);
   memo1.Clear;
   memo1.Lines.Add(ans);
end;
« Последнее редактирование: 03.04.2021, 11:02:55 от dimkin » Записан
rom_hm
Newbie
*
Сообщений: 7


Просмотр профиля Email
« Ответ #12 : 16.05.2022, 17:19:08 »

Добрый день! Прочитал всю ветку, но так и не нашел ответа на первоначальный вопрос: Как с помощью gethistorydata получать исторические данные через TXmlConnector на C#? Если у кого получилось, поделитесь, пож.
Записан
Сорвачев Сергей
Разработчики
Jr. Member
*****
Сообщений: 54


Просмотр профиля Email
« Ответ #13 : 16.05.2022, 18:40:32 »

Добрый день! Прочитал всю ветку, но так и не нашел ответа на первоначальный вопрос: Как с помощью gethistorydata получать исторические данные через TXmlConnector на C#? Если у кого получилось, поделитесь, пож.

Добрый! Проблема в понимании логики работы или написании кода? Остальные команды удалось реализовать?

Скачиваем ТУТ пример коннектора на C#.
Файл MainForm.cs:
Code: (C#) [Select]
void Get_Transaq_History(int SecurityID, int TimeframeID, int HistoryLength, bool ResetFlag)формирование и отправка команды в коннектор

Файл connector.cs:
Code: (C#) [Select]
public static string Transaq_HandleData(string data)обработчик входящих данных от коннектора.
Вас интересует две секции из этого кода:
1. Значения period для передачи коннектору в gethistorydata
Code: [Select]
// данные для таймфреймов
if (section == "candlekinds")

2. Сами свечи, то есть результат вызова gethistorydata
Code: [Select]
// данные по свечам
if (section == "candles")
{
   if (ename == "candles")
   {
      // ваша обработка
    }
    if (ename == "candle")
    {
      // ваша обработка
    }
}
« Последнее редактирование: 16.05.2022, 18:52:59 от Сорвачев Сергей » Записан
rom_hm
Newbie
*
Сообщений: 7


Просмотр профиля Email
« Ответ #14 : 17.05.2022, 16:17:51 »

Сергей, спасибо за пояснение.
Моя задача на основании предоставленного примера получить исторические данные по свечам. Для этого добавил в MainForm.cs вызов Get_Transaq_History:
      void btn_Connect_Click(object sender, EventArgs e)
      {
         // если подключен или подключается
            if (bConnected || bConnecting)
         {
            Transaq_Disconnect();
         }
         else
         {
                if (!bConnecting) Transaq_Connect();
         }

            // получаем исторические данные   
            Get_Transaq_History(1544, 5, 10, true); // (GAZP, сутки, 10 свечей, true)

        }
И в connector.cs примитивную обработку свечных данных:
                // данные по свечам
                if (section == "candles")  //Get_Transaq_History?
                {
                    log.WriteLog("candles111");

                    if (ename == "candles")
                    {

                    }
                    if (ename == "candle")
                    {

                    }
                }
Но "candles111" в журнале нет. В чем может быть причина?
Записан
Страниц: [1] 2 Печать 
Transaq  |  СБО "Transaq"  |  TRANSAQ Connector  |  Topic: Получение исторических данных gethistorydata « предыдущая тема следующая тема »
Перейти в:  


Войти

Powered by MySQL Powered by PHP Powered by SMF 2.0.10 | SMF © 2006-2008, Simple Machines LLC Valid XHTML 1.0! Valid CSS!