~Russian Bear’Z Blog~



Руководство по использованию GA4TS

GA4TS Dynamic Link Library (version 1.1) имеет стандартный интерфейс, поэтому использовать библиотеку можно в любой программе, поддерживающей вызовы через API. Библиотека защищена современными криптографическими методами и может быть использована только на компьютере зарегистрированного пользователя. Поддерживается совместимость только в ОС: Windows 2000 и более поздние версии.

Продолжение:

УСТАНОВКА БИБЛИОТЕКИ

Библиотека состоит из одного файла GA4TS.dll, зарегистрированную версию которого достаточно скопировать на компьютер. Для регистрации надо скачать программу CreateId4GA.exe, и с её помощью определить трёхзначный идентификатор компьютера, на котором будет использоваться библиотека. И если Вы приобретаете библиотеку, ты Вы приобретаете зарегистрированную версию, которая может быть использована только на этом компьютере, одним пользователем. При существенном изменении конфигурации компьютера библиотека может не пройти этап верификации, для чего необходимо воспользоватся обратной связью.

void __stdcall ga_create(
    int multiobjective, // Количество критериев.
    int gene_length, // Количество генов(параметров).
    int total_count, // Количество итераций.
    LPSTR log); // Имя файла для записи логов, или NULL.

Проверяет соответствие встроенных ключей, после чего создаёт в памяти объект ГА.

Значения для multiobjective от 1 до 10. Значения для gene_length от 1 до 100. Используется один раз.


void __stdcall ga_setadvancedoptions(
    int sel, // Метод выбора родителей.
    int choice, // Метод выбора пар.
    int child, // Метод определения количества детей.
    int next, // Метод отбора для следующей популяции
    double prob); // Вероятность мутации.

Задаёт параметры работы ГА. Вызов не обязателен. Вызывается в любой момент.

  1. sel - Метод выбора родителей. Может принимать два значения: 0 – выбор осуществляется равномерно по всей популяции, 1– происходит выбор методом «рулетки» (по умолчанию).
  2. choice – Метод выбора пар. Принимает следующие значения: 0 – панимексия, 1 – комплексная панимексия, 2 – аутбридинг по генотипу, 3 – инбридинг по генотипу, 4 – аутбридинг по фенотипу, 5 – инбридинг по фенотипу, 6 – случайный метод выбранный из набора(0, 0, 0, 1, 2, 3, 4, 5) (по умолчанию), 7 – случайный метод из набора (0, 1, 2, 3, 3, 3, 4, 5). В случайных методах, предотвращаён прямой переход от инбридинга к аутбридингу, и наоборот.
  3. child – Метод, по которому определяется количество детей в следующей популяции. Принимает следующие значения: 0 – эквивалентно предыдущей популяции, 1 – приближённо к количеству базовой популяции (по умолчанию).
  4. next – Метод отбора для следующей популяции. Принимает три значения: 0 – метод Парето (по умолчанию), 1 – турнирный отбор, 2 – элитный отбор. Все методы работают независимо от количества критериев.
  5. prob – Вероятность мутации. По умолчанию значение равно 0.002.


void __stdcall ga_setcodelength(
    int gene_pos, // Порядковый номер гена, нумерация с 0.
    int code_length); // Длина кода.

Задаёт точность вычислений для данного параметра. Точность задаётся длиной кода, который соответствует количеству бит, представляющий этот параметр. Например, кодом длиной 10, можно закодировать 210 значений, или целое число из 0, …,1023, или дробное, число меньшее 1, с точностью до 3 знака после запятой. Этот параметр, а точнее длина хромосомы (сумма по всем генам) существенно влияет на объём вычислений и на скорость сходимости. Вызывается пред ga_generate, для каждого гена. Максимальное значение 63.


int __stdcall ga_generate(
    int population); // Размер базовой популяции.

Создаёт базовую популяцию, и возвращает 0 в случае успеха и -1 в случае ошибки. Ошибка может возникнуть, в результате проверки идентификационных ключей, или установки длины кода.


int __stdcall ga_loadbasepopulation(
    LPSTR fn, // CSV – файл, с базовой популяцией.
    int population); // Размер базовой популяции.

Создаёт базовую популяцию, и возвращает 0 в случае успеха и -1 в случае ошибки. Файл, полученный с помощью ga_writechain, может использоваться для дальнейших вычислений. Заменяет вызов ga_generate.


int __stdcall ga_getinitialized(void);

Проверка состояния инициализации: 0 – завершена, -1 – не завершена. Используется в TS Omega для избежания повторной процедуры инициализации.


double __stdcall ga_getcurrentgene(
    int gene_pos); // Номер гена, нумерация с 0.

Возвращает число из интервала [0,1] с плавающей запятой, соответствующее значению гена, для текущей хромосомы.


__int64 __stdcall ga_getcurrentgeneint64(
    int gene_pos); // Номер гена, нумерация с 0.

Возвращает целое число из интервала [0, 2code_length-1], соответствующее значению гена, для текущей хромосомы.


int __stdcall ga_getcurrentgeneint(
    int gene_pos); // Номер гена, нумерация с 0.

Версия для TS Omega. Функция корректно работает с длиной кода не более 31.


void __stdcall ga_setcurrentvalue(
    int objective, // Номер критерия, нумерация с 0.
    double value); // Значение.

Передаёт значение, полученное целевой функции, для текущей хромосомы.


int __stdcall ga_calculated(
    int count); // Номер итерации.

Вызывается для формирования новой хромосомы, после вычисления значений для всех критериев. Возвращает: -1 – в случае ошибки, 0 – после завершении работы Генетического Алгоритма, при достижении значения count, близкой к заданному максимальному количеству итераций, 1 – перед началом вычисления детей, 2 – после окончания.


int __stdcall ga_writechain(
    int grid, // Параметр фильтрации
    LPSTR fn); // Имя файла для вывода результата.

Записывает в заданный файл результат работы ГА. Возвращает 0 в случае успеха и -1 в случае ошибки. Параметр фильтрации отражает плотность расположения в пространстве критериев, и сказывается на количестве результирующих данных: их будет примерно netmultiobjective/multiobjective.


int __stdcall ga_addelitechain(
    LPSTR str, // Строка 1.
    LPSTR str, // Строка 2.
    LPSTR str, // Строка 3.
    LPSTR str); // Строка 4.

Добавляет заведомо хорошее решение, для ускорения сходимости популяции. Возвращает 0 в случае успеха и -1 в случае ошибки. Строки содержат информацию о коде каждого гена, в том же виде что и параметры функций ga_getcurrentgene и ga_getcurrentgeneint. Формат строк следующий: через точку с запятой записываются значения всех генов: для дробного значения “F=дробное число;” а для целочисленного “I=целое число;”. В библиотеке все строки объединяются в одну, потому что TS Omega не распознаёт строки, длиннее 64 символов.

ПРИМЕР ИСПОЛЬЗОВАНИЯ В TS OMEGA

Для оптимизации параметров стратегии в TS при помощи библиотеки, надо произвести некую модификацию кода самой стратегии. Но сначала о самом запуске оптимизации. TS Omega, каждый раз загружает, и заново выгружает динамическую библиотеку, во время оптимизации, при наличии к ней обращений в стратегии. Чтоб такого не происходило, надо эту стратегию использовать на другом графике, и когда TS проверяет, используется библиотека, где-либо ещё, то не выгружает её из памяти. Такая процедура необходима, так как указать TS, как ей поступать c DLL нельзя программным образом, а иметь общий доступ к памяти, необходимо на время всех итераций. Далее приводится пример код, для оптимизации 6 переменных, который надо будет вставить в стратегию.


Inputs:
    count(0);
var:
    str(“”),
    saucer(0),
    period(5),
    AVO16(1),
    AVO32(1),
    AVO64(1),
    AVO128(1);

Параметр count счётчик итераций, по которому будет идти перебор в TS, строчная переменная и 6 переменных для оптимизации.

Затем для версий TS Omega 3.0 – 5.0, необходимо перед первым вызовом, в коде стратегии прописать:


DefineDLLFunc: “C:\GA\GA4TS.dll”, void, “ga_create”, int, int, int, LPSTR;
DefineDLLFunc: “C:\GA\GA4TS.dll”, void, “ga_setadvancedoptions”, int, int, int, int, double;
DefineDLLFunc: “C:\GA\GA4TS.dll”, void, “ga_setcodelength”, int, int;
DefineDLLFunc: “C:\GA\GA4TS.dll”, int, “ga_generate”, int;
DefineDLLFunc: “C:\GA\GA4TS.dll”, int, “ga_loadbasepopulation”, LPSTR, int;
DefineDLLFunc: “C:\GA\GA4TS.dll”, int, “ga_getinitialized”;
DefineDLLFunc: “C:\GA\GA4TS.dll”, double, “ga_getcurrentgene”, int;
DefineDLLFunc: “C:\GA\GA4TS.dll”, int, “ga_getcurrentgeneint”, int;
DefineDLLFunc: “C:\GA\GA4TS.dll”, void, “ga_setcurrentvalue”, int, double;
DefineDLLFunc: “C:\GA\GA4TS.dll”, int, “ga_calculated”, int;
DefineDLLFunc: “C:\GA\GA4TS.dll”, int, “ga_writechain”, int, LPSTR;
DefineDLLFunc: “C:\GA\GA4TS.dll”, int, “ga_addelitechain”, LPSTR, LPSTR, LPSTR, LPSTR;

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


value1 = ga_getinitialized();
If
    value1 <> 0
then
begin
    ga_create(2, 6, 5000, “C:\\GA\\log.txt”);
    ga_setadvancedoptions(1,6,1,0,0.002);
    ga_setcodelength(0, 1);
    ga_setcodelength(1, 5);
    ga_setcodelength(2, 10);
    ga_setcodelength(3, 10);
    ga_setcodelength(4, 10);
    ga_setcodelength(5, 10);
    value1 = ga_generate(200);
    if
        value1 <> 0
    then
        print(”Error Initialization.”);
    value1 = ga_addelitechain(”I=1;I=0;I=25;I=870;I=382;I=127;”, “”, “”, “”);
    if
        value1 <> 0
    then
        print(”Error Adding.”);
end;

После инициализации параметров ГА, на каждой следующей итерации запрашиваются новые параметры стратегии:


if
    CurrentBar = 1
then
begin
    saucer = MinList(ga_getcurrentgeneint(0), 1); {[0,1]}
    period = MinList(ga_getcurrentgeneint(1), 31) + 10; {[10, 41]}
    AVO16 = MinList(ga_getcurrentgene(2)*10, 10); {(0,10)}
    AVO32 = MinList(ga_getcurrentgene(3)*10, 10); {(0,10)}
    AVO64 = MinList(ga_getcurrentgene(4)*10, 10); {(0,10)}
    AVO128 = MinList(ga_getcurrentgene(5)*10, 10); {(0,10)}
end;

Далее идёт код самой стратегии:


if
    CurrentBar > 1
then
begin {global}
    {body…}
end;

После вычисления текущего результата, параметры надо передать ГА:


if
    LastBarOnChart
then
begin
    ga_setcurrentvalue(0, -GrossProfit/GrossLoss);
    ga_setcurrentvalue(1, MaxIDDrawDown);
    str =
        NumToStr(saucer, 0) + “,” +
        NumToStr(period, 0) + “,” +
        NumToStr(AVO16, 2) + “,” +
        NumToStr(AVO32, 2) + “,” +
        NumToStr(AVO64, 2) + “,” +
        NumToStr(AVO128, 2) + “,” +
        NumToStr(-GrossProfit/GrossLoss, 3) + “,” +
        NumToStr(MaxIDDrawDown, 3);
    print(str);
    value1 = ga_calculated(count);
    if
        value1 = 0
    then
    begin
        ga_writechain(200, “C:\\GA\\” + GetSymbolName + “_” + NumToStr(BarInterval, 0) + “.csv”);
        print(”Calculation Finished!”);
    end;
end;

так же можно распечатывать промежуточные результаты в консоли TS. Файл, сохранённый с результатами оптимизации, состоит из строк, содержащих целочисленные значения генов, записанные через запятую, а последние параметры в строке, это значения целевых функций. Для перевода целочисленных значений в значения с плавающей запятой, используется следующая формула F = I/(2code_length-1).

ПРИМЕР ИСПОЛЬЗОВАНИЯ В C++


typedef VOID (__stdcall* LPGCREATE)(INT,INT,INT,LPSTR);
typedef VOID (__stdcall* LPGSETCODELENGTH)(INT,INT);
typedef VOID (__stdcall* LPGGENERATE)(INT);
typedef VOID (__stdcall* LPGLOADBASEPOPULATION)(LPSTR, INT);
typedef DOUBLE (__stdcall* LPGGETCURRENTGENE)(INT);
typedef INT (__stdcall* LPGGETCURRENTGENEINT)(INT);
typedef INT64 (__stdcall* LPGGETCURRENTGENEINT64)(INT);
typedef VOID (__stdcall* LPGSETCURRENTVALUE)(INT, DOUBLE);
typedef INT (__stdcall* LPGCALCULATED)(INT);
typedef INT (__stdcall* LPGWRITECHAIN)(INT, LPSTR);
typedef VOID (__stdcall* LPGADDELITECHAIN)(LPSTR,LPSTR,LPSTR,LPSTR);
typedef VOID (__stdcall* LPSETADVANCEDOPTION)(INT,INT,INT,INT,DOUBLE);
void main(void)
{
    int i;
    double r;
    double x;
    double y;
    HINSTANCE hDLL;
    LPGCREATE Create;
    LPGSETCODELENGTH SetCodeLength;
    LPGGENERATE Generate;
    LPGLOADBASEPOPULATION LoadBasePopulation;
    LPGGETCURRENTGENE GetCurrentGene;
    LPGGETCURRENTGENEINT GetCurrentGeneInt;
    LPGGETCURRENTGENEINT64 GetCurrentGeneInt64;
    LPGSETCURRENTVALUE SetCurrentValue;
    LPGCALCULATED Calculated;
    LPGWRITECHAIN WriteChain;
    LPGADDELITECHAIN AddEliteChain;
    LPSETADVANCEDOPTION SetAdvancedOptions;
    hDLL = LoadLibrary(”C:\\GA\\GA4TS.dll”);
    if (!hDLL) return;
    Create = (LPGCREATE)GetProcAddress(hDLL, “ga_create”);
    SetCodeLength = (LPGSETCODELENGTH)GetProcAddress(hDLL, “ga_setcodelength”);
    Generate = (LPGGENERATE)GetProcAddress(hDLL, “ga_generate”);
    LoadBasePopulation =(LPGLOADBASEPOPULATION)GetProcAddress(hDLL, “ga_loadbasepopulation”);
    GetCurrentGene = (LPGGETCURRENTGENE)GetProcAddress(hDLL, “ga_getcurrentgene”);
    GetCurrentGeneInt = (LPGGETCURRENTGENEINT)GetProcAddress(hDLL, “ga_getcurrentgeneint”);
    GetCurrentGeneInt64=(LPGGETCURRENTGENEINT64)
    GetProcAddress(hDLL,”ga_getcurrentgeneint64″);
    SetCurrentValue = (LPGSETCURRENTVALUE)GetProcAddress(hDLL, “ga_setcurrentvalue”);
    Calculated = (LPGCALCULATED)GetProcAddress(hDLL, “ga_calculated”);
    WriteChain = (LPGWRITECHAIN)GetProcAddress(hDLL, “ga_writechain”);
    AddEliteChain = (LPGADDELITECHAIN)GetProcAddress(hDLL, “ga_addelitechain”);
    SetAdvancedOptions =(LPSETADVANCEDOPTION)GetProcAddress(hDLL, “ga_setadvancedoptions”);
    if (!
        (Create &&
        SetCodeLength &&
        Generate &&
        LoadBasePopulation &&
        GetCurrentGene &&
        GetCurrentGeneInt &&
        GetCurrentGeneInt64 &&
        SetCurrentValue &&
        Calculated &&
        WriteChain &&
        AddEliteChain &&
        SetAdvancedOptions)
        )
    {
        FreeLibrary(hDLL);
        return;
    }
    Create(2, 2, 10000, “C:\\GA\\log_c.txt”);
    SetAdvancedOptions(1, 6, 1, 0, 0.002);
    SetCodeLength(0, 40);
    SetCodeLength(1, 40);
    Generate(500); // LoadBasePopulation(”c:\\GA\\test.csv”, 500);
    AddEliteChain(”F=0.999;I=7;”, “”, “”, “”);
    for(i = 0; i < 10000; i++)
    {
        x = GetCurrentGene(0);
        y = GetCurrentGene(1);
        r = -4*(x-0.5)*(x-0.5)-4*(y-0.5)*(y-0.5)+ // Rastrigin’s Function
            10*(-2+cos(M_PI*(x-0.5))+cos(M_PI*(y-0.5)));
            SetCurrentValue(0, d);
        SetCurrentValue(1, 4*(x-0.5)*(x-0.5)+4*(y-0.5)*(y-0.5));
        if(Calculated(i) == 0)
            WriteChain(300, “c:\\GA\\test.csv”);
    }
    FreeLibrary(hDLL);
}

Статьи по теме:
GA4TS.DLL – Генетический алгоритм для TradeStation
Поиск оптимальных по Парето стратегий
Тестирование опционных стратегий в Omega TradeStation


Tags: генетический алгоритм, генетический алгоритм парето, парето оптимизация, многокритериальная оптимизация, численная оптимизация, GA4TS, задача оптимизации

Subscribe to comments with RSS or TrackBack to 'Руководство по использованию GA4TS'.

One Response to 'Руководство по использованию GA4TS'

  1. Михаил said,

    on December 21st, 2008 at 7:00 pm

    достаточно познавательно, а примеры вообще класс

Leave a Reply