-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdllmain.cpp
225 lines (192 loc) · 5.71 KB
/
dllmain.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
#ifdef _WIN32
#include <windows.h>
#endif
#include <iostream>
#include <stdexcept>
#include <string>
#include <vector>
#include <filesystem>
#include <cstring>
#include "neat/genome.hpp"
#include "utils/time_frame.hpp"
#include "trader.hpp"
#include "types.hpp"
// Choose the configuration file to use
#include "configs/default.hpp"
#ifdef _WIN32
#define TEST_DLL_API __declspec(dllexport)
#else
#define TEST_DLL_API
#endif
Config config;
neat::Genome *genome = nullptr;
Trader *trader = nullptr;
#ifdef _WIN32
// Function to display a message in the MetaTrader editor console
void PrintToConsole(const char *message)
{
// Use the MessageBoxA function to display the message
MessageBoxA(NULL, message, "Message from DLL", MB_OK | MB_ICONINFORMATION);
}
#endif
// Function to get the timeframe for a given code
TimeFrame TimeFrameFromCode(int timeframe_code)
{
switch (timeframe_code)
{
case 0:
return TimeFrame::M1;
case 1:
return TimeFrame::M5;
case 2:
return TimeFrame::M15;
case 3:
return TimeFrame::M30;
case 4:
return TimeFrame::H1;
case 5:
return TimeFrame::H4;
case 6:
return TimeFrame::D1;
default:
#if defined(_WIN32)
PrintToConsole("One of the timeframes is not available.");
#endif
std::exit(1);
}
}
TEST_DLL_API void test_dll()
{
// Example function body
}
TEST_DLL_API double make_decision(
Candle *candles_tf_1,
int candles_tf_1_size,
int tf_1_code,
Candle *candles_tf_2,
int candles_tf_2_size,
int tf_2_code,
Candle *candles_tf_3,
int candles_tf_3_size,
int tf_3_code,
int position_type,
double position_pnl,
double position_size,
int position_duration,
double base_currency_conversion_rate,
double account_balance)
{
std::vector<TimeFrame> candles_timeframes;
CandlesData candles_data;
IndicatorsData indicators_data;
std::vector<PositionInfo> position_infos;
if (candles_tf_1_size > 0)
{
TimeFrame tf_1 = TimeFrameFromCode(tf_1_code);
candles_timeframes.push_back(tf_1);
for (int i = 0; i < candles_tf_1_size; ++i)
{
candles_data[tf_1].push_back(candles_tf_1[i]);
}
}
if (candles_tf_2_size > 0)
{
TimeFrame tf_2 = TimeFrameFromCode(tf_2_code);
candles_timeframes.push_back(tf_2);
for (int i = 0; i < candles_tf_2_size; ++i)
{
candles_data[tf_2].push_back(candles_tf_2[i]);
}
}
if (candles_tf_3_size > 0)
{
TimeFrame tf_3 = TimeFrameFromCode(tf_3_code);
candles_timeframes.push_back(tf_3);
for (int i = 0; i < candles_tf_3_size; ++i)
{
candles_data[tf_3].push_back(candles_tf_3[i]);
}
}
// Calculate the indicators and add them to the inputs
for (const auto &[timeframe, indicators] : config.training.inputs.indicators)
{
if (std::find(candles_timeframes.begin(), candles_timeframes.end(), timeframe) == candles_timeframes.end())
{
#if defined(_WIN32)
PrintToConsole("One of the timeframes is not available in the input data.");
#endif
std::exit(1);
}
for (const auto &indicator : indicators)
{
std::vector<double> values = indicator->calculate(candles_data[timeframe], true);
indicators_data[timeframe][indicator->id] = values;
}
}
// Get the position infos from the config
for (const auto &position_info : config.training.inputs.position)
{
position_infos.push_back(position_info);
}
// Update the balance
trader->balance = account_balance;
// Update the current position pnl
if (position_type != 0 && trader->current_position != nullptr)
{
trader->current_position->pnl = position_pnl;
}
trader->update(candles_data);
// Check if the trader has closed the position due to its duration
if (position_type != 0 && trader->current_position == nullptr)
{
return 3; // Close the position
}
// Close the position of trader if the position type is 0
if (position_type == 0 && trader->current_position != nullptr)
{
trader->close_position_by_market();
}
// Update the vision
trader->look(indicators_data, base_currency_conversion_rate, position_infos);
// Make a decision
trader->think();
// Return the decision
return trader->trade();
}
#ifdef _WIN32
BOOL APIENTRY DllMain(HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved)
{
std::string genomePath;
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
// Get the config
config = __config__;
// Construct the full path to the genome file
genomePath = "C:\\Users\\Maxime\\AppData\\Roaming\\MetaQuotes\\Terminal\\D0E8209F77C8CF37AD8BF550E51FF075\\MQL5\\Libraries\\genome.json";
// Load the genome from the file
genome = neat::Genome::load(genomePath);
if (genome == nullptr)
{
PrintToConsole("Cannot load the genome.");
std::exit(1);
}
trader = new Trader(genome, config);
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_DETACH:
// Cleanup resources allocated during initialization
delete genome;
genome = nullptr;
delete trader;
trader = nullptr;
break;
}
return TRUE;
}
#endif