mahmoudezoj
پنج شنبه 11 اردیبهشت 1404, 16:16 عصر
سلام دوستان. من در بخش پایتون بیشتر از یکماه پیش درخواستی گذاشتم که مثل اینکه کسی توی این سایت نمیتونه انجامش بده. گفتم شاید اینجا دوستان بتونن کمک کنن قسمتی از کارم درست بشه.
من یک فایل dll میخوام که اخبار اقتصادی فارکسی رو از سایت https://www.investing.com/economic-calendar/ دریافت کنه که من بتونم با استفاده از یک اندیکاتور اطلاعات رو از dll بگیرم و اخبار با تمام جزئیات (یعنی زمان، درجه اهمیت خبر، نرخ قدیمی، نرخ پیشّینی، نرخ واقعی و...) روی چارت MT4 نمایش داده بشه.
من خودم البته به کمک هوش مصنوعی کد زیر ررو نوشتم ولی خطا میده و روی چارت MT4 چیزی نمایش داده نمیشه. قابل توجه اینکه تمام فایلهای لازم روی سیستمم هست. اسم این فایل dll رو هم NewsFetcher.cpp گذاشتم.
کسی میتونه کمکم کنه؟
#include <windows.h>
#include <string>
#include <fstream>
#include "curl/curl.h"
#include <regex>
#include <ctime>
#pragma comment(lib, "libcurl.lib")
static std::string downloadedHtml;
struct NewsItem {
time_t time;
char currency[4];
char impact[10];
char title[256];
};
size_t WriteCallback(void* contents, size_t size, size_t nmemb, void* userp) {
size_t totalSize = size * nmemb;
downloadedHtml.append((char*)contents, totalSize);
return totalSize;
}
time_t ParseDateTimeToTimestamp(const std::string& dateTime) {
try {
struct tm tm = {0};
int year, month, day, hour, minute, second;
// فرمت 1: "YYYY/MM/DD HH:MM:SS"
if (sscanf(dateTime.c_str(), "%d/%d/%d %d:%d:%d", &year, &month, &day, &hour, &minute, &second) == 6) {
tm.tm_year = year - 1900;
tm.tm_mon = month - 1;
tm.tm_mday = day;
tm.tm_hour = hour;
tm.tm_min = minute;
tm.tm_sec = second;
tm.tm_isdst = -1;
return mktime(&tm);
}
// فرمت 2: "YYYY-MM-DDTHH:MM:SS"
if (sscanf(dateTime.c_str(), "%d-%d-%dT%d:%d:%d", &year, &month, &day, &hour, &minute, &second) == 6) {
tm.tm_year = year - 1900;
tm.tm_mon = month - 1;
tm.tm_mday = day;
tm.tm_hour = hour;
tm.tm_min = minute;
tm.tm_sec = second;
tm.tm_isdst = -1;
return mktime(&tm);
}
return -1;
} catch (...) {
return -1;
}
}
void LogMessage(const std::string& message) {
std::ofstream logFile("C:\\Users\\mahmo\\AppData\\Roaming\\MetaQuotes\\Te rminal\\287469DEA9630EA94D0715D755974F1B\\MQL4\\Fi les\\debugLog.txt", std::ios::app);
if (logFile.is_open()) {
logFile << message << "\n";
logFile.close();
}
}
extern "C" __declspec(dllexport) int __stdcall FetchNews() {
try {
LogMessage("Starting FetchNews...");
CURL* curl;
CURLcode res;
downloadedHtml.clear();
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if (!curl) {
LogMessage("curl_easy_init failed");
curl_global_cleanup();
return -1;
}
curl_easy_setopt(curl, CURLOPT_URL, "https://www.investing.com/economic-calendar/");
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
curl_easy_setopt(curl, CURLOPT_USERAGENT, "Mozilla/5.0");
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
res = curl_easy_perform(curl);
if (res != CURLE_OK) {
LogMessage("curl_easy_perform failed: " + std::string(curl_easy_strerror(res)));
curl_easy_cleanup(curl);
curl_global_cleanup();
return -2;
}
std::ofstream outFile("C:\\Users\\mahmo\\AppData\\Roaming\\MetaQuotes\\Te rminal\\287469DEA9630EA94D0715D755974F1B\\MQL4\\Fi les\\downloadedHtml.txt");
if (outFile.is_open()) {
outFile << downloadedHtml;
outFile.close();
LogMessage("HTML saved to downloadedHtml.txt");
} else {
LogMessage("Failed to save HTML to file");
}
curl_easy_cleanup(curl);
curl_global_cleanup();
LogMessage("FetchNews completed successfully");
return 0;
} catch (const std::exception& e) {
LogMessage("Exception in FetchNews: " + std::string(e.what()));
return -3;
} catch (...) {
LogMessage("Unknown exception in FetchNews");
return -3;
}
}
int ImpactFromClass(const std::string& impactClass) {
if (impactClass == "bull3") return 3;
if (impactClass == "bull2") return 2;
if (impactClass == "bull1") return 1;
return 0;
}
extern "C" __declspec(dllexport) bool __stdcall GetUpcomingNews(NewsItem* newsArray, int* newsCount, int* fetchErrorCode) {
try {
LogMessage("Starting GetUpcomingNews...");
if (!newsArray || !newsCount || !fetchErrorCode) {
LogMessage("Invalid parameters in GetUpcomingNews");
return false;
}
int fetchResult = FetchNews();
*fetchErrorCode = fetchResult;
if (fetchResult != 0) {
LogMessage("FetchNews failed with code: " + std::to_string(fetchResult));
return false;
}
int maxNews = *newsCount;
*newsCount = 0;
// مرحله 1: پیدا کردن تمام ردیفهای <tr> مربوط به رویدادها
LogMessage("Finding event rows...");
std::regex rowRegex(R"(<tr[^>]*data-event-datetime="([^"]+)"[^>]*>(.*?)</tr>)", std::regex::icase);
auto rowBegin = std::sregex_iterator(downloadedHtml.begin(), downloadedHtml.end(), rowRegex);
auto rowEnd = std::sregex_iterator();
time_t currentTimestamp = time(nullptr);
LogMessage("Current timestamp: " + std::to_string(currentTimestamp));
for (std::sregex_iterator i = rowBegin; i != rowEnd; ++i) {
std::smatch rowMatch = *i;
std::string dateTime = rowMatch[1];
std::string rowContent = rowMatch[2];
LogMessage("Found event row with datetime: " + dateTime);
time_t eventTimestamp = ParseDateTimeToTimestamp(dateTime);
if (eventTimestamp == -1) {
LogMessage("Invalid datetime format: " + dateTime);
continue;
}
int diff = static_cast<int>(eventTimestamp - currentTimestamp);
LogMessage("Event timestamp: " + std::to_string(eventTimestamp) + ", Diff: " + std::to_string(diff));
if (diff <= 0 || *newsCount >= maxNews) continue;
// مرحله 2: استخراج ارز
std::regex currencyRegex(R"(<td class="left flagCur noWrap">[^<]*<span[^>]*>[^<]*</span>\s*([A-Z]{3})</td>)", std::regex::icase);
std::smatch currencyMatch;
if (!std::regex_search(rowContent, currencyMatch, currencyRegex)) {
LogMessage("Currency not found for event at " + dateTime);
continue;
}
std::string currency = currencyMatch[1];
// مرحله 3: استخراج تأثیر
std::regex impactRegex(R"(<td class="left textNum sentiment noWrap"[^>]*data-img_key="(bull\d)">)", std::regex::icase);
std::smatch impactMatch;
if (!std::regex_search(rowContent, impactMatch, impactRegex)) {
LogMessage("Impact not found for event at " + dateTime);
continue;
}
std::string impactClass = impactMatch[1];
int impactCode = ImpactFromClass(impactClass);
if (impactCode == 0) {
LogMessage("Invalid impact class: " + impactClass);
continue;
}
// مرحله 4: استخراج عنوان
std::regex titleRegex(R"(<td class="left event"[^>]*><a[^>]*>(.*?)</a>)", std::regex::icase);
std::smatch titleMatch;
if (!std::regex_search(rowContent, titleMatch, titleRegex)) {
LogMessage("Title not found for event at " + dateTime);
continue;
}
std::string title = titleMatch[1];
// پر کردن ساختار NewsItem
newsArray[*newsCount].time = eventTimestamp;
strncpy_s(newsArray[*newsCount].currency, currency.c_str(), _TRUNCATE);
switch (impactCode) {
case 3: strncpy_s(newsArray[*newsCount].impact, "High", _TRUNCATE); break;
case 2: strncpy_s(newsArray[*newsCount].impact, "Medium", _TRUNCATE); break;
case 1: strncpy_s(newsArray[*newsCount].impact, "Low", _TRUNCATE); break;
}
strncpy_s(newsArray[*newsCount].title, title.c_str(), _TRUNCATE);
LogMessage("Added event: " + std::string(newsArray[*newsCount].title) + ", Currency: " + std::string(newsArray[*newsCount].currency) + ", Impact: " + std::string(newsArray[*newsCount].impact));
(*newsCount)++;
}
if (*newsCount > 0) {
*fetchErrorCode = 0;
LogMessage("GetUpcomingNews completed successfully with " + std::to_string(*newsCount) + " events");
return true;
} else {
*fetchErrorCode = -9;
LogMessage("No upcoming events found");
return false;
}
} catch (const std::regex_error& e) {
LogMessage("Regex error in GetUpcomingNews: " + std::string(e.what()));
*fetchErrorCode = -10;
return false;
} catch (const std::exception& e) {
LogMessage("Exception in GetUpcomingNews: " + std::string(e.what()));
*fetchErrorCode = -11;
return false;
} catch (...) {
LogMessage("Unknown exception in GetUpcomingNews");
*fetchErrorCode = -12;
return false;
}
}
من یک فایل dll میخوام که اخبار اقتصادی فارکسی رو از سایت https://www.investing.com/economic-calendar/ دریافت کنه که من بتونم با استفاده از یک اندیکاتور اطلاعات رو از dll بگیرم و اخبار با تمام جزئیات (یعنی زمان، درجه اهمیت خبر، نرخ قدیمی، نرخ پیشّینی، نرخ واقعی و...) روی چارت MT4 نمایش داده بشه.
من خودم البته به کمک هوش مصنوعی کد زیر ررو نوشتم ولی خطا میده و روی چارت MT4 چیزی نمایش داده نمیشه. قابل توجه اینکه تمام فایلهای لازم روی سیستمم هست. اسم این فایل dll رو هم NewsFetcher.cpp گذاشتم.
کسی میتونه کمکم کنه؟
#include <windows.h>
#include <string>
#include <fstream>
#include "curl/curl.h"
#include <regex>
#include <ctime>
#pragma comment(lib, "libcurl.lib")
static std::string downloadedHtml;
struct NewsItem {
time_t time;
char currency[4];
char impact[10];
char title[256];
};
size_t WriteCallback(void* contents, size_t size, size_t nmemb, void* userp) {
size_t totalSize = size * nmemb;
downloadedHtml.append((char*)contents, totalSize);
return totalSize;
}
time_t ParseDateTimeToTimestamp(const std::string& dateTime) {
try {
struct tm tm = {0};
int year, month, day, hour, minute, second;
// فرمت 1: "YYYY/MM/DD HH:MM:SS"
if (sscanf(dateTime.c_str(), "%d/%d/%d %d:%d:%d", &year, &month, &day, &hour, &minute, &second) == 6) {
tm.tm_year = year - 1900;
tm.tm_mon = month - 1;
tm.tm_mday = day;
tm.tm_hour = hour;
tm.tm_min = minute;
tm.tm_sec = second;
tm.tm_isdst = -1;
return mktime(&tm);
}
// فرمت 2: "YYYY-MM-DDTHH:MM:SS"
if (sscanf(dateTime.c_str(), "%d-%d-%dT%d:%d:%d", &year, &month, &day, &hour, &minute, &second) == 6) {
tm.tm_year = year - 1900;
tm.tm_mon = month - 1;
tm.tm_mday = day;
tm.tm_hour = hour;
tm.tm_min = minute;
tm.tm_sec = second;
tm.tm_isdst = -1;
return mktime(&tm);
}
return -1;
} catch (...) {
return -1;
}
}
void LogMessage(const std::string& message) {
std::ofstream logFile("C:\\Users\\mahmo\\AppData\\Roaming\\MetaQuotes\\Te rminal\\287469DEA9630EA94D0715D755974F1B\\MQL4\\Fi les\\debugLog.txt", std::ios::app);
if (logFile.is_open()) {
logFile << message << "\n";
logFile.close();
}
}
extern "C" __declspec(dllexport) int __stdcall FetchNews() {
try {
LogMessage("Starting FetchNews...");
CURL* curl;
CURLcode res;
downloadedHtml.clear();
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if (!curl) {
LogMessage("curl_easy_init failed");
curl_global_cleanup();
return -1;
}
curl_easy_setopt(curl, CURLOPT_URL, "https://www.investing.com/economic-calendar/");
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
curl_easy_setopt(curl, CURLOPT_USERAGENT, "Mozilla/5.0");
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
res = curl_easy_perform(curl);
if (res != CURLE_OK) {
LogMessage("curl_easy_perform failed: " + std::string(curl_easy_strerror(res)));
curl_easy_cleanup(curl);
curl_global_cleanup();
return -2;
}
std::ofstream outFile("C:\\Users\\mahmo\\AppData\\Roaming\\MetaQuotes\\Te rminal\\287469DEA9630EA94D0715D755974F1B\\MQL4\\Fi les\\downloadedHtml.txt");
if (outFile.is_open()) {
outFile << downloadedHtml;
outFile.close();
LogMessage("HTML saved to downloadedHtml.txt");
} else {
LogMessage("Failed to save HTML to file");
}
curl_easy_cleanup(curl);
curl_global_cleanup();
LogMessage("FetchNews completed successfully");
return 0;
} catch (const std::exception& e) {
LogMessage("Exception in FetchNews: " + std::string(e.what()));
return -3;
} catch (...) {
LogMessage("Unknown exception in FetchNews");
return -3;
}
}
int ImpactFromClass(const std::string& impactClass) {
if (impactClass == "bull3") return 3;
if (impactClass == "bull2") return 2;
if (impactClass == "bull1") return 1;
return 0;
}
extern "C" __declspec(dllexport) bool __stdcall GetUpcomingNews(NewsItem* newsArray, int* newsCount, int* fetchErrorCode) {
try {
LogMessage("Starting GetUpcomingNews...");
if (!newsArray || !newsCount || !fetchErrorCode) {
LogMessage("Invalid parameters in GetUpcomingNews");
return false;
}
int fetchResult = FetchNews();
*fetchErrorCode = fetchResult;
if (fetchResult != 0) {
LogMessage("FetchNews failed with code: " + std::to_string(fetchResult));
return false;
}
int maxNews = *newsCount;
*newsCount = 0;
// مرحله 1: پیدا کردن تمام ردیفهای <tr> مربوط به رویدادها
LogMessage("Finding event rows...");
std::regex rowRegex(R"(<tr[^>]*data-event-datetime="([^"]+)"[^>]*>(.*?)</tr>)", std::regex::icase);
auto rowBegin = std::sregex_iterator(downloadedHtml.begin(), downloadedHtml.end(), rowRegex);
auto rowEnd = std::sregex_iterator();
time_t currentTimestamp = time(nullptr);
LogMessage("Current timestamp: " + std::to_string(currentTimestamp));
for (std::sregex_iterator i = rowBegin; i != rowEnd; ++i) {
std::smatch rowMatch = *i;
std::string dateTime = rowMatch[1];
std::string rowContent = rowMatch[2];
LogMessage("Found event row with datetime: " + dateTime);
time_t eventTimestamp = ParseDateTimeToTimestamp(dateTime);
if (eventTimestamp == -1) {
LogMessage("Invalid datetime format: " + dateTime);
continue;
}
int diff = static_cast<int>(eventTimestamp - currentTimestamp);
LogMessage("Event timestamp: " + std::to_string(eventTimestamp) + ", Diff: " + std::to_string(diff));
if (diff <= 0 || *newsCount >= maxNews) continue;
// مرحله 2: استخراج ارز
std::regex currencyRegex(R"(<td class="left flagCur noWrap">[^<]*<span[^>]*>[^<]*</span>\s*([A-Z]{3})</td>)", std::regex::icase);
std::smatch currencyMatch;
if (!std::regex_search(rowContent, currencyMatch, currencyRegex)) {
LogMessage("Currency not found for event at " + dateTime);
continue;
}
std::string currency = currencyMatch[1];
// مرحله 3: استخراج تأثیر
std::regex impactRegex(R"(<td class="left textNum sentiment noWrap"[^>]*data-img_key="(bull\d)">)", std::regex::icase);
std::smatch impactMatch;
if (!std::regex_search(rowContent, impactMatch, impactRegex)) {
LogMessage("Impact not found for event at " + dateTime);
continue;
}
std::string impactClass = impactMatch[1];
int impactCode = ImpactFromClass(impactClass);
if (impactCode == 0) {
LogMessage("Invalid impact class: " + impactClass);
continue;
}
// مرحله 4: استخراج عنوان
std::regex titleRegex(R"(<td class="left event"[^>]*><a[^>]*>(.*?)</a>)", std::regex::icase);
std::smatch titleMatch;
if (!std::regex_search(rowContent, titleMatch, titleRegex)) {
LogMessage("Title not found for event at " + dateTime);
continue;
}
std::string title = titleMatch[1];
// پر کردن ساختار NewsItem
newsArray[*newsCount].time = eventTimestamp;
strncpy_s(newsArray[*newsCount].currency, currency.c_str(), _TRUNCATE);
switch (impactCode) {
case 3: strncpy_s(newsArray[*newsCount].impact, "High", _TRUNCATE); break;
case 2: strncpy_s(newsArray[*newsCount].impact, "Medium", _TRUNCATE); break;
case 1: strncpy_s(newsArray[*newsCount].impact, "Low", _TRUNCATE); break;
}
strncpy_s(newsArray[*newsCount].title, title.c_str(), _TRUNCATE);
LogMessage("Added event: " + std::string(newsArray[*newsCount].title) + ", Currency: " + std::string(newsArray[*newsCount].currency) + ", Impact: " + std::string(newsArray[*newsCount].impact));
(*newsCount)++;
}
if (*newsCount > 0) {
*fetchErrorCode = 0;
LogMessage("GetUpcomingNews completed successfully with " + std::to_string(*newsCount) + " events");
return true;
} else {
*fetchErrorCode = -9;
LogMessage("No upcoming events found");
return false;
}
} catch (const std::regex_error& e) {
LogMessage("Regex error in GetUpcomingNews: " + std::string(e.what()));
*fetchErrorCode = -10;
return false;
} catch (const std::exception& e) {
LogMessage("Exception in GetUpcomingNews: " + std::string(e.what()));
*fetchErrorCode = -11;
return false;
} catch (...) {
LogMessage("Unknown exception in GetUpcomingNews");
*fetchErrorCode = -12;
return false;
}
}