Voici ce que vous pouvez faire avec OpenCL directement dans MetaTrader 5, sans aucune DLL. - page 4
Vous manquez des opportunités de trading :
- Applications de trading gratuites
- Plus de 8 000 signaux à copier
- Actualités économiques pour explorer les marchés financiers
Inscription
Se connecter
Vous acceptez la politique du site Web et les conditions d'utilisation
Si vous n'avez pas de compte, veuillez vous inscrire
Oui, je connais un peu l'OCL, j'en suis conscient. Il n'est pas nécessaire de charger l'ensemble de l'EA dans la carte, laissez-les charger quelques fragments de code parallèles, ils représentent généralement un pourcentage du code entier.
Alors, pourquoi est-ce que je ne vois que les cœurs du CPU (Core i5, 8 cœurs - 8 agents) lors de l'optimisation alors que j'ai une NVIDIA 780GTX ?
Utilisez-vous OpenCL dans votre code ?
Vous pensez probablement que tout votre code doit être chargé sur la carte graphique. Ce qui n'est pas vrai.
Je vous recommande vivement de lire notre article sur OpenCL dans MetaTrader 5 où tout est expliqué en détail comment cela fonctionne :
Afin d'obtenir une accélération significative, vous devez envoyer l'ensemble du conseiller au GPU, mais pour cela, vous devez écrire votre propre testeur.
Voici un exemple d'un tel testeur, un réseau de neurones avec logique de trading, code OCL :
//Функция для ядра
string GPU_kernel( int hl1NeuronCount,
int hl2NeuronCount,
int sampleCount,
int signalCount)
{
return
(
"#define HL1Count " + ( string )hl1NeuronCount + " \r\n"
"#define HL2Count " + ( string )hl2NeuronCount + " \r\n"
//------------------------------------------------------------------------------------
"#define NeuronSensitivity " + ( string )NeuronSensitivity_P + " \r\n"
//------------------------------------------------------------------------------------
"#define sampleCount " + ( string )sampleCount + " \r\n"
//------------------------------------------------------------------------------------
"#define signalCount " + ( string )signalCount + " \r\n"
//------------------------------------------------------------------------------------
"#define StrArrSaSize " + ( string )( sizeof (ArrSample) / sizeof ( float )) + "\r\n"
"typedef struct{float C[StrArrSaSize];} ArrSa; \r\n"
//------------------------------------------------------------------------------------
"#define StrArrWeSize " + ( string )( sizeof (ArrWe) / sizeof ( float )) + " \r\n"
"typedef struct{float C[StrArrWeSize];} ArrWe; \r\n"
//------------------------------------------------------------------------------------
"#define StrArrCrSize " + ( string )( sizeof (ArrCr) / sizeof ( float )) + " \r\n"
"typedef struct{float C[StrArrCrSize];}ArrCr; \r\n"
//------------------------------------------------------------------------------------
"#define Spread " + ( string )(Spread_P * Point ()) + " \r\n"
//------------------------------------------------------------------------------------
"#define Point " + ( string ) Point () + " \r\n"
"#define SL " + ( string )(StopLoss_P * Point ()) + " \r\n"
"#define TP " + ( string )(TakeProfit_P * Point ()) + " \r\n"
//------------------------------------------------------------------------------------
" \r\n"
"__kernel void Work(__global ArrSa *Sample, \r\n"
" __global ArrWe *Weights, \r\n"
" __global ArrCr *Result) \r\n"
"{ \r\n"
" int thread = get_global_id(0); \r\n"
" \r\n"
" //------------------Переменные нейронной сети---------------------------------\r\n"
" float nHL1 [HL1Count]; // Нейроны первого скрытого слоя \r\n"
" float nHL2 [HL2Count]; // Нейроны второго скрытого слоя \r\n"
" ArrWe parametr = Weights[thread]; // Параметры системы \r\n"
" int cnt_W = 0; // счетчик весов \r\n"
" float out = 0.0; // выход сети \r\n"
" \r\n"
" //-------------------Переменные для торговли----------------------------------\r\n"
" float temp = 0.0; // для временного хранения чего нибудь \r\n"
" \r\n"
" //---параметры цены \r\n"
" float priceASK = 0.0; // текущая Ask цена \r\n"
" float priceBID = 0.0; // текущая Bid цена \r\n"
" float pricePrevHighASK = 0.0; // максимум предыдущей свечи Ask \r\n"
" float pricePrevHighBID = 0.0; // максимум предыдущей свечи Bid \r\n"
" float pricePrevLowASK = 0.0; // минимум предыдущей свечи Ask \r\n"
" float pricePrevLowBID = 0.0; // минимум предыдущей свечи Bid \r\n"
" \r\n"
" float posType = 0.0; // тип сделки: \r\n"
" // 1.0 - buy, \r\n"
" //-1.0 - sell; \r\n"
" // 0.0 - нет открытой сделки \r\n"
" float posPriceClose = 0.0; \r\n"
" float posPriceClosePrevHi = 0.0; \r\n"
" float posPriceClosePrevLo = 0.0; \r\n"
" \r\n"
" //-----------------Текущие показатели позиции---------------------------------\r\n"
" float posPriceSL = 0.0; // цена StopLoss открытой сделки \r\n"
" float posPriceTP = 0.0; // цена TakeProfit открытой сделки \r\n"
" \r\n"
" //--------------------Статистика торговли-------------------------------------\r\n"
" int StTradeProfitCount = 0; // кол-во приб. сделок \r\n"
" int StTradeLossCount = 0; // кол-во уб. сделок \r\n"
" \r\n"
" int StTradeLossSeries = 0; // текущая серия убыточных ордеров \r\n"
" int StTradeMaxLossSer = 0; // самая длинная серия уб.ордеров \r\n"
" \r\n"
" //-----------------------Тут прогон по истории--------------------------------\r\n"
" for(int hist = 0;hist < sampleCount;hist++) \r\n"
" { \r\n"
" cnt_W = 0; \r\n"
" //---------------Обработаем первый скрытый слой-----------------------------\r\n"
" //Добавим смещение точек насыщения нейрона: (+b) \r\n"
" for(int u = 0;u < HL1Count;u++) \r\n"
" { \r\n"
" nHL1[u] = parametr.C[cnt_W]; \r\n"
" cnt_W++; \r\n"
" } \r\n"
" \r\n"
" //Сумма произведений нейронов предыдущего слоя и их весов: \r\n"
" // (+w1*x1+...+wn*xn) для каждого нейрона \r\n"
" for(int u = 0;u < HL1Count;u++) \r\n"
" { \r\n"
" for(int i = 0;i < signalCount;i++) \r\n"
" { \r\n"
" nHL1[u] += Sample[hist].C[i + 3] * parametr.C[cnt_W]; \r\n"
" cnt_W++; \r\n"
" } \r\n"
" } \r\n"
" \r\n"
" //Посчитаем функцию активации для каждого скрытого нейрона \r\n"
" for(int u = 0;u < HL1Count;u++) \r\n"
" { \r\n"
" nHL1[u] = 5.0 * nHL1[u] / (1.0 + fabs(4.02 * nHL1[u])); \r\n"
" } \r\n"
" \r\n"
" //---------------Обработаем второй скрытый слой-----------------------------\r\n"
" //Добавим смещение точек насыщения нейрона: (+b) \r\n"
" for(int u = 0;u < HL2Count;u++) \r\n"
" { \r\n"
" nHL2[u] = parametr.C[cnt_W]; \r\n"
" cnt_W++; \r\n"
" } \r\n"
" \r\n"
suite de code :
" // (+w1*x1+...+wn*xn) для каждого нейрона \r\n"
" for(int u = 0;u < HL2Count;u++) \r\n"
" { \r\n"
" for(int i = 0;i < HL1Count;i++) \r\n"
" { \r\n"
" nHL2[u] += nHL1[i] * parametr.C[cnt_W]; \r\n"
" cnt_W++; \r\n"
" } \r\n"
" } \r\n"
" \r\n"
" //Посчитаем функцию активации для каждого скрытого нейрона \r\n"
" for(int u = 0;u < HL2Count;u++) \r\n"
" { \r\n"
" nHL2[u] = 5.0 * nHL2[u] / (1.0 + fabs(4.02 * nHL2[u])); \r\n"
" } \r\n"
" \r\n"
" //-----------------Обработаем выходной слой---------------------------------\r\n"
" //Добавим смещение точек насыщения нейрона: (+b) \r\n"
" out = parametr.C[cnt_W]; \r\n"
" cnt_W++; \r\n"
" \r\n"
" //Сумма произведений нейронов предыдущего слоя и их весов: \r\n"
" // (+w1*x1+...+wn*xn) для каждого нейрона \r\n"
" for(int i = 0;i < HL2Count;i++) \r\n"
" { \r\n"
" out += nHL2[i] * parametr.C[cnt_W]; \r\n"
" cnt_W++; \r\n"
" } \r\n"
" //==========================================================================\r\n"
" \r\n"
" \r\n"
" //==========================================================================\r\n"
" priceASK = Sample[hist].C[0] + Spread; \r\n"
" priceBID = Sample[hist].C[0]; \r\n"
" \r\n"
" pricePrevHighASK = Sample[hist].C[1] + Spread; \r\n"
" pricePrevHighBID = Sample[hist].C[1]; \r\n"
" \r\n"
" pricePrevLowASK = Sample[hist].C[2] + Spread; \r\n"
" pricePrevLowBID = Sample[hist].C[2]; \r\n"
" \r\n"
" //-----------------проверка условий на выход из рынка-----------------------\r\n"
" // если есть открытая поза \r\n"
" if(posType != 0.0) \r\n"
" { \r\n"
" if(posType == 1.0) \r\n"
" { \r\n"
" posPriceClose = priceBID; \r\n"
" posPriceClosePrevHi = pricePrevHighBID; \r\n"
" posPriceClosePrevLo = pricePrevLowBID; \r\n"
" } \r\n"
" else \r\n"
" { \r\n"
" posPriceClose = priceASK; \r\n"
" posPriceClosePrevHi = pricePrevHighASK; \r\n"
" posPriceClosePrevLo = pricePrevLowASK; \r\n"
" } \r\n"
" \r\n"
" \r\n"
" // может уже сработал SL? \r\n"
" if(posType * (posPriceSL - posPriceClose) >= 0.0 || \r\n"
" posType * (posPriceSL - posPriceClosePrevLo) >= 0.0) \r\n"
" { \r\n"
" // на одну убыточную сделку больше \r\n"
" StTradeLossCount++; \r\n"
" // текущая серия убыточных сделок увеличилась \r\n"
" StTradeLossSeries++; \r\n"
" // если серия уб. сделок больше чем в истори, то запомним \r\n"
" StTradeMaxLossSer = (StTradeMaxLossSer < StTradeLossSeries) ? \r\n"
" StTradeLossSeries : StTradeMaxLossSer; \r\n"
" // позиция закрыта \r\n"
" posType = 0.0; \r\n"
" } \r\n"
" // нет, SL не сработал \r\n"
" else \r\n"
" { \r\n"
" // может уже сработал TP? \r\n"
" if(posType * (posPriceClose - posPriceTP) >= 0.0 || \r\n"
" posType * (posPriceClosePrevHi - posPriceTP) >= 0.0) \r\n"
" { \r\n"
" // на одну прибыльную сделку больше \r\n"
" StTradeProfitCount++; \r\n"
" // текущая серия убыточных сделок закончилась \r\n"
" StTradeLossSeries = 0; \r\n"
" // позиция закрыта \r\n"
" posType = 0.0; \r\n"
" } \r\n"
" } \r\n"
" \r\n"
" } \r\n"
" //--------------------------------------------------------------------------\r\n"
" \r\n"
" \r\n"
" //-----------------проверка сигнала на вход в рынок-------------------------\r\n"
" // если нет открытых поз проверим возможность открытия \r\n"
" if(posType == 0.0 && hist < (sampleCount - 1)) \r\n"
" { \r\n"
" // если есть сигнал на покупку \r\n"
" if(NeuronSensitivity < out) \r\n"
" { \r\n"
" posPriceTP = priceASK + TP; \r\n"
" posPriceSL = priceASK - SL; \r\n"
" posType = 1.0; \r\n"
" } \r\n"
" // если есть сигнал на продажу \r\n"
" if(out < -NeuronSensitivity) \r\n"
" { \r\n"
" posPriceSL = priceBID + SL; \r\n"
" posPriceTP = priceBID - TP; \r\n"
" posType = -1.0; \r\n"
" } \r\n"
" } \r\n"
" } \r\n"
" \r\n"
" \r\n"
" //----------------------------------------------------------------------------\r\n"
" float Profit = ((float)StTradeProfitCount*TP)-((float)StTradeLossCount*SL); \r\n"
" Result[thread].C[0] = Profit; \r\n"
" Result[thread].C[1] = -StTradeMaxLossSer; \r\n"
"} \r\n"
);
}
//————————————————————————————————————————————————————————————————————————————————————————————————
Il s'agit d'une démonstration non seulement des calculs GPU dans le code MQL5, mais aussi des capacités graphiques du terminal :
Le code source complet sous forme de script est joint. Le bogue sur OpenCL 1.2 a été corrigé.
la suite du code :
À propos, est-il possible d'envoyer du code à l'OCL d'une manière ou d'une autre sous la forme d'un fichier, plutôt que sous la forme d'un poste de travail ? Sinon, ça donne un peu la chair de poule.
À propos, est-il possible d'envoyer du code à OCL non pas sous forme de feuille ligne par ligne, mais en quelque sorte sous forme de fichier ? Ça a l'air un peu effrayant.
Il est important de noter qu'aujourd'hui, fin 2016, il est déjà possible de revendiquer la présence d'OpenCL dans les systèmes cibles.
Même s'il n'y a pas de GPU, OpenCL fonctionnera sur le CPU en utilisant tous les cœurs. Voici à quoi ressemble l'ensemble des dispositifs :
OpenCL Device #1: CPU GenuineIntel Intel(R) Xeon(R) CPU E5-2690 v3 @ 2.60 GHz with OpenCL 1.2 (24 units, 2598 MHz, 32680 Mb, version 2117.13 (sse2,avx), rating 85)
Le terminal sélectionne automatiquement le dispositif le plus rapide en fonction de la cote de performance. Il est également possible de sélectionner manuellement n'importe quel dispositif via la fonction CLContextCreate.
Malheureusement, oubliez OpenCL sur Windows XP. Et les systèmes d'exploitation 32 bits en général - nous sommes en 2017.
Plus désagréable encore est la situation de Nvidia, qui sabote essentiellement la norme OpenCL et ne met pas en œuvre OpenCL 2.0. Elle a d'abord saboté la mise en œuvre d'OpenCL 1.2, puis d'OpenCL 2.0. Il fait cela pour promouvoir sa propre mise en œuvre de CUDA, ce qui nuit à l'ensemble de la communauté.
Par ailleurs, Nvidia abaisse délibérément la précision de ses cartes pour gamers afin de limiter leur utilisation en mathématiques et de stimuler l'achat de cartes spécialisées (Tesla).
Dans ce contexte, AMD semble l'emporter, non seulement en raison de sa rapidité mathématique (les fermes d'exploitation minière sont généralement construites sur AMD), mais aussi en raison de sa stratégie de normes ouvertes (elle s'est beaucoup ouverte et fait entrer dans le domaine public). L'introduction d'OpenCL 2.0 dans les cartes AMD a rapproché cette spécification des capacités de CUDA et il est désormais inutile de préparer le terrain pour CUDA.