Общие вопросы по разработке > Доступ к объектам терминала из стратегий

Общие вопросы по разработке в Альфа-Директ 4. Обсуждение разработки пользовательских индикаторов, стратегий.
ensh
Сообщения: 218
Зарегистрирован: 28 июн 2017, 13:56
Благодарил (а): 4 раза
Поблагодарили: 39 раз

Доступ к объектам терминала из стратегий

Непрочитанное сообщение ensh » 21 янв 2019, 01:12

Продолжим, щаззз научу, надеюсь, не очень плохому...

Несколько раз уже поднимался вопрос, а как получить, а как узнать... нужную циферку
Можно, конечно, слезно написать разработчикам и они что-то когда-то напишут в толстый талмуд описания стратегий и выпустят в новой версии... а может и нет...

А можно обратиться к объектам сборки Core.dll, где лежат все первичные данные терминала, пошарить и ... найти что-нибудь нужное, разумеется ооочень осторожно, не забывать про наличие блокировок и ничего там не менять :)))))

Итак, пара строчек кода и пояснения

1. Воспользуемся методом динамической загрузки сборки в контекст приложения, здесь нет ничего страшного, так-как сборка уже загружена самим терминалом, вызов метода просто убеждается в ее наличии и дает ссылку на ее метаданные

Код: Выделить всё

 var CoreAssembly = System.Reflection.Assembly.LoadFrom("Core.dll");


2. Теперь получим класс объекта и статический экземпляр. Все данные и работа\обновление с сервера разделены по интересам в различных менеджерах: OrdersManager, PositionManager, BalanceManager, OperationsManager, QuotesManager, QueueManager, ConnectionManager, OrderSendManager, SubscriptionManager, ChatManager, NewsManager, MarketTradesManager, Notifications наверно все... у каждого объекта есть статическое свойство Instance, в котором хранится единственный экземпляр соответствующего менеджера на всю систему.
Имя объекта начинаем с приставки Core, получение статического значения - GetValue с пустым указателем

Код: Выделить всё

var opManagerType = CoreAssembly.GetType("Core.OperationsManager");
var opManagerInstance = opManagerType.GetProperty("Instance").GetValue(null);


3. С помощью рефлексии, хвала Микрософту, получаем нужный нам метод или свойство.

Код: Выделить всё

var opManagerGetOperations = opManagerType.GetMethod("GetOperations", new Type[0]);


4. пользуемся (вызываем) методом или свойством, предварительно разбирая доку по языку C#, относительно всяких правил приведения типов, ибо полученные рефлексией объекты не дружественны к компилятору скрипта, нужно также пошарить по базовым типам, как там все:

Код: Выделить всё

var opList = (((IEnumerable<object>)opManagerGetOperations.Invoke(opManagerInstance, null))
   .OfType<ClientOperationEntity>()
   .ToList());


Осмелюсь напомнить, что работа с рефлексией вещь достаточно затратная, поэтому, ее нужно выполнять при инициализации скрипта, записывать все явки в глобальные переменные (пункты 1...3).
Пункт 4 на усмотрение, если данные не будут меняться в ходе выполнения скрипта, можно их также запрашивать при инициализации, если же нужны именно свежие данные, каждый раз, пункт 4 выполняем в методе индикатора или стратегии.


надеюсь, профит

ensh
Сообщения: 218
Зарегистрирован: 28 июн 2017, 13:56
Благодарил (а): 4 раза
Поблагодарили: 39 раз

Re: Доступ к объектам терминала из стратегий

Непрочитанное сообщение ensh » 22 янв 2019, 00:40

А теперь новый уровень дабы избавиться от рефлексии в индикаторах и стратегиях и пользоваться dynamic переменными.

1. Создаем новый пользовательский индикатор
2. В процедуру инициализации индикатора записываем (в старых версиях пишем "NetProtocol.dll")

Код: Выделить всё

function Initialize()
{
   IndicatorName = "Dynamic";   // Задайте название индикатора и сохраните с данным именем
   
   AddInput("Input", Inputs.Price);   // Input - входной ряд (Inputs.Price) или свечи (Inputs.Candle)
    AddSeries("Dynamic", DrawAs.Line, Color.Red);   // Задаем вид линии индикатора A
 
    var ReferencedLibraries = typeof(TA.Script.ScriptCompiler).GetField("ReferencedLibraries",
       System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static );
    if (ReferencedLibraries != null)
    {
       var ReferencedLibrariesArray = ReferencedLibraries.GetValue(null) as string[];
        for (int i = 0; i < ReferencedLibrariesArray.Length; i++)
           ReferencedLibrariesArray[i] = ReferencedLibrariesArray[i].Replace("ADir.NetProtocol.dll", "Microsoft.CSharp.dll");
     }
}

function Evaluate()
{
// Область расчета значения индикатора

 Dynamic = 0.0;   // Присваиваем значение = 0.0
 
 dynamic a = 6; // проверим, что все взлетело
}



3. Жмем на кнопку компиляции в верху окна, индикатор не только скомпилится, НО и процедура инициализации выполнится (!!!!!) и мы заинжектим в список сборок используемых при выполнении (компиляции) стратегий очень полезную сборку Microsoft.CSharp.dll вместо NetProtocol.dll, уж не знаю, что от этой сборки хотели разработчики... сохраним индикатор как Dynamic

4. теперь становится доступным тип dynamic и можем использовать в индикаторах позднее связывание.

зы. индикатор для подмены сборки можно заюзать на одном из графиков, а можно загружать по мере необходимости, скомпилированные стратегии будут автоматом подгружать Microsoft.CSharp.dll, а вот перед редактированием кода стратегий содержащих dynamic нужно однократно скомпилировать (запустить) индикатор

ensh
Сообщения: 218
Зарегистрирован: 28 июн 2017, 13:56
Благодарил (а): 4 раза
Поблагодарили: 39 раз

Re: Доступ к объектам терминала из стратегий

Непрочитанное сообщение ensh » 25 янв 2019, 13:00

Вот еще один простейший способ получить данные из незнакомого объекта в Альфа Директе

Код: Выделить всё

var opList = (IEnumerable<object>)opManagerGetOperations.Invoke(opManagerInstance, null);

foreach(var op in opList)
{
   var opDataString = op.ToString();
   // в строке список значений XXXX=YYYY, парсим ручками, то что нужно
}


AP_Bor
Сообщения: 170
Зарегистрирован: 18 дек 2017, 08:18
Благодарил (а): 12 раз
Поблагодарили: 8 раз

Re: Доступ к объектам терминала из стратегий

Непрочитанное сообщение AP_Bor » 25 янв 2019, 18:30

Доброго времени суток, ensh
ensh » 25.01.2019, 13:00 писал(а):Вот еще один простейший способ получить данные из незнакомого объекта
Во еще осталось дождаться первого плагина для роботов AD, чтоб спрятать служебный код, например, используя "Managed Extensibility Framework" или "Managed Add-in Framework".
Жду с нетерпением.
► Показать
С наилучшими пожеланиями

ensh
Сообщения: 218
Зарегистрирован: 28 июн 2017, 13:56
Благодарил (а): 4 раза
Поблагодарили: 39 раз

Re: Доступ к объектам терминала из стратегий

Непрочитанное сообщение ensh » 25 янв 2019, 19:24

Я вообще считаю работу с роботами тупиком, но вроде как что-то простое написать...

AP_Bor
Сообщения: 170
Зарегистрирован: 18 дек 2017, 08:18
Благодарил (а): 12 раз
Поблагодарили: 8 раз

Re: Доступ к объектам терминала из стратегий

Непрочитанное сообщение AP_Bor » 25 янв 2019, 20:34

Доброго времени суток, ensh
ensh писал(а):Я вообще считаю работу с роботами тупиком, но вроде как что-то простое написать...
Для вас все так просто, спасибо, рассчитывал на ваше великодушие, ждем с нетерпением.
► Показать
С наилучшими пожеланиями

ensh
Сообщения: 218
Зарегистрирован: 28 июн 2017, 13:56
Благодарил (а): 4 раза
Поблагодарили: 39 раз

Re: Доступ к объектам терминала из стратегий

Непрочитанное сообщение ensh » 27 янв 2019, 23:03

ну и продублирую, оптимальный на мой взгляд, шаблон с примерами доступа к PositonManager, так сказать по результатам коллективного творчества

как оказалось, dynamic не так хорош и проще подключить нормальные типы Альфа Директ

Код: Выделить всё

function Initialize()
{
   IndicatorName = "CorePositionTest";   // Задайте название индикатора и сохраните с данным именем
   
   AddInput("Input", Inputs.Price);   // Input - входной ряд (Inputs.Price) или свечи (Inputs.Candle)
    AddSeries("CorePositionTest", DrawAs.Line, Color.Red);   // Задаем вид линии индикатора A
 
    // регистрация библиотек (как только ввели блок, жмем компиляцию и пишем дальше)
   var ReferencedLibraries = typeof(TA.Script.ScriptCompiler).GetField("ReferencedLibraries",
       System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static );

    if (ReferencedLibraries != null)
    {
       var ReferencedLibrariesArray = ReferencedLibraries.GetValue(null) as string[];
        if (!ReferencedLibrariesArray.Contains("Core.dll"))
        {
           // инжектим базовую библиотеку с данными альфа-директа
           ReferencedLibrariesArray = ReferencedLibrariesArray.Concat(new[] { "Core.dll" }).ToArray();
            ReferencedLibraries.SetValue(null, ReferencedLibrariesArray); // спасибо AP_Bor
        }
       
        if (!ReferencedLibrariesArray.Contains("DataStorageShared.dll"))
        {
           // инжектим базовую библиотеку с информационными справочниками альфа-директа
           ReferencedLibrariesArray = ReferencedLibrariesArray.Concat(new[] { "DataStorageShared.dll" }).ToArray();
            ReferencedLibraries.SetValue(null, ReferencedLibrariesArray); // спасибо AP_Bor
        }

        if (!ReferencedLibrariesArray.Contains("ADir.DataCollections.dll"))
        {
           // инжектим базовую библиотеку с "новыми" коллекциями альфа-директа
           // старые коллекции в "DataCollections.dll"
           ReferencedLibrariesArray = ReferencedLibrariesArray.Concat(new[] { "ADir.DataCollections.dll" }).ToArray();
            ReferencedLibraries.SetValue(null, ReferencedLibrariesArray); // спасибо AP_Bor
        }
   }
   
   // конец - регистрация библиотек
   
   // пишем блок после инжекта!!!! иначе не скомпилируется   
   // регистрация своего индекса (если  ОЧЕНЬ нужно) после инжекта библиотек
   
   // в старых версиях Core.PositionManager 
   var positionManager = Core.Managers.PositionManager.Instance;
   var positionStorage = positionManager.Positions;

    var positionIndexNumber = -1;

    Func<string, int> getIndexNumberByName = (name) =>
    {
       for (int i = 0; i < int.MaxValue; i++)
       {
          var positionIndex = positionStorage[i];

          if (positionIndex == null)
             return -1;

          if (positionIndex.Name == name)
          return i;
       }

       return -1; // дошли досюда... ну ну
    };

   // нужно быть осторожным, индексы никак не проверяются на уникальность и если наплодить индексов
   // все может затормозиться... ну это нужно постараться конечно, но зачем
   if ((positionIndexNumber = getIndexNumberByName("index by idfi")) == -1)
    {
       var index = new IndexedList<int, AD.Common.DataStructures.ClientTradePosition>("index by idfi",
          (AD.Common.DataStructures.ClientTradePosition pos) => pos.IdFiBalance);

       positionStorage.AddIndex(index);

       positionIndexNumber = getIndexNumberByName("index by idfi");
    }
   
    AddGlobalVariable("IndexByIdFi", Types.Int, positionIndexNumber);
   // конец - регистрация своего индекса
}

function Evaluate()
{
   // Область расчета значения индикатора

   CorePositionTest = 0.0;   // Присваиваем значение = 0.0

   // пишем блок после инжекта!!!! иначе не скомпилируется
    // в старых версиях Core.PositionManager 
   var positionManager = Core.Managers.PositionManager.Instance;
   var positionStorage = positionManager.Positions;

   //получить список позиций - пример
    IEnumerable<AD.Common.DataStructures.ClientTradePosition> positions;
    lock (positionStorage.Locker)
    {
       positions = positionStorage.Values.OfType<AD.Common.DataStructures.ClientTradePosition>().ToList();
    }

    foreach (var position in positions)
    {
       // здесь все позиции
       var objectEntity = Core.DataStorageShared.GetObjectsByIdObject(position.IdObject);
       var finInfoExt = position.finInfoExt;                               
    }
    // конец - получить список позиций   
      
              
    // использование стандартного индекса - позицию по idObject-у - пример
    var position123456 = positionStorage.GetSingle(123456, (int)Core.Managers.PositionManager.PositionsIndexNumber.IdObject);

   // использование своего индекса - пример
    var position789 = positionStorage.GetSingle(789, IndexByIdFi);   
}

High Profit Trader
Сообщения: 77
Зарегистрирован: 23 мар 2018, 10:54
Поблагодарили: 2 раза

Re: Доступ к объектам терминала из стратегий

Непрочитанное сообщение High Profit Trader » 06 авг 2019, 18:50

Прикольно!

ifinch
Сообщения: 14
Зарегистрирован: 14 янв 2021, 14:47
Благодарил (а): 1 раз
Поблагодарили: 1 раз

Re: Доступ к объектам терминала из стратегий

Непрочитанное сообщение ifinch » 14 янв 2021, 16:07

Можно ли залинковать стороннюю dll, в которой описаны те или иные расчеты, как это позвонляет MT4/5 например (кусок кода ниже)?

#import "Indicators64.dll"
string _IndicatorError(int id);
int _IndicatorInit(uchar &tpe[], uchar &ind[], uchar &sym[]);
int _IndicatorSetBar(int id,int barno,int edate,int etime ,double O,double H,double L,double C,double pV,double nV);
double _IndicatorValue(int id, int valid);
int _IndicatorSetParameter(int id, int parm, double val);
#import

ensh
Сообщения: 218
Зарегистрирован: 28 июн 2017, 13:56
Благодарил (а): 4 раза
Поблагодарили: 39 раз

Re: Доступ к объектам терминала из стратегий

Непрочитанное сообщение ensh » 16 янв 2021, 01:14



Вернуться в «Общие вопросы по разработке»

Кто сейчас на конференции

Сейчас этот форум просматривают: Google [Bot] и 11 гостей