Update news event data retrieval due to Cloudflare scraping protections on Forex Factory

This commit is contained in:
moshferatu 2024-07-04 19:39:32 -07:00
parent 20768cebac
commit c318149d5a

View File

@ -1,31 +1,17 @@
#region Using declarations #region Using declarations
using NinjaTrader.Gui;
using NinjaTrader.Gui.Chart;
using NinjaTrader.Gui.Tools;
using SharpDX;
using SharpDX.DirectWrite;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel; using System.ComponentModel;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using System.Linq; using System.Net.Http;
using System.Text; using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media; using System.Windows.Media;
using System.Xml.Serialization; using System.Xml.Serialization;
using NinjaTrader.Cbi;
using NinjaTrader.Gui;
using NinjaTrader.Gui.Chart;
using NinjaTrader.Gui.SuperDom;
using NinjaTrader.Gui.Tools;
using NinjaTrader.Data;
using NinjaTrader.NinjaScript;
using NinjaTrader.Core.FloatingPoint;
using NinjaTrader.NinjaScript.DrawingTools;
using System.Net.Http;
using SharpDX.DirectWrite;
using SharpDX;
using System.Xml.Linq;
using System.Xml;
using System.Text.RegularExpressions;
using System.Windows.Markup;
#endregion #endregion
//This namespace holds Indicators in this folder and is required. Do not change it. //This namespace holds Indicators in this folder and is required. Do not change it.
@ -82,11 +68,11 @@ namespace NinjaTrader.NinjaScript.Indicators
HttpClient client = new HttpClient(); HttpClient client = new HttpClient();
client.DefaultRequestHeaders.UserAgent.ParseAdd("Mozilla/5.0 (Windows NT 10.0; Win64; x64)"); client.DefaultRequestHeaders.UserAgent.ParseAdd("Mozilla/5.0 (Windows NT 10.0; Win64; x64)");
string newsUrl = "https://www.forexfactory.com/calendar?day=" + DateTime.Now.ToString("MMMdd.yyyy").ToLower(); string newsUrl = "https://nfs.faireconomy.media/ff_calendar_thisweek.json";
HttpResponseMessage response = await client.GetAsync(newsUrl); HttpResponseMessage response = await client.GetAsync(newsUrl);
response.EnsureSuccessStatusCode(); response.EnsureSuccessStatusCode();
string responseBody = await response.Content.ReadAsStringAsync();
string responseBody = await response.Content.ReadAsStringAsync();
ParseNewsEvents(responseBody); ParseNewsEvents(responseBody);
ForceRefresh(); ForceRefresh();
@ -97,66 +83,40 @@ namespace NinjaTrader.NinjaScript.Indicators
} }
} }
private void ParseNewsEvents(string html) private void ParseNewsEvents(string json)
{ {
try try
{ {
// Regex to match the rows with class "calendar__row" var events = Regex.Matches(json, @"\{[^}]*\}");
var rowRegex = new Regex(@"<tr[^>]*class=""[^""]*calendar__row[^""]*""[^>]*>(.*?)</tr>", RegexOptions.Singleline);
// Regex to extract time and title from the row foreach (Match eventMatch in events)
var timeRegex = new Regex(@"<td[^>]*class=""[^""]*calendar__time[^""]*""[^>]*>(.*?)</td>", RegexOptions.Singleline);
var currencyRegex = new Regex(@"<td[^>]*class=""[^""]*calendar__currency[^""]*""[^>]*>(.*?)</td>", RegexOptions.Singleline);
var titleRegex = new Regex(@"<span[^>]*class=""[^""]*calendar__event-title[^""]*""[^>]*>(.*?)</span>", RegexOptions.Singleline);
var rowMatches = rowRegex.Matches(html);
foreach (Match rowMatch in rowMatches)
{ {
string rowContent = rowMatch.Groups[1].Value; string eventString = eventMatch.Value;
var timeMatch = timeRegex.Match(rowContent); string date = ExtractJsonValue(eventString, "date");
var currencyMatch = currencyRegex.Match(rowContent); string currency = ExtractJsonValue(eventString, "country");
var titleMatch = titleRegex.Match(rowContent); string title = ExtractJsonValue(eventString, "title");
if (timeMatch.Success && titleMatch.Success) DateTime eventTime = DateTime.Parse(date);
{ if (eventTime.Date != currentDate)
string time = timeMatch.Groups[1].Value.Trim(); continue;
string currency = currencyMatch.Groups[1].Value.Trim();
string title = titleMatch.Groups[1].Value.Trim();
// Remove any extraneous HTML tags from the time string string time = eventTime.ToString("hh:mmtt").ToLower();
time = Regex.Replace(time, "<.*?>", string.Empty);
// Convert the time to the user's time zone
time = ConvertToUserTimeZone(time);
newsEvents.Add(new NewsEvent { Time = time, Currency = currency, Title = title }); newsEvents.Add(new NewsEvent { Time = time, Currency = currency, Title = title });
} }
} }
}
catch (Exception ex) catch (Exception ex)
{ {
Print("Error parsing news events: " + ex.Message); Print("Error parsing news events: " + ex.Message);
} }
} }
private string ConvertToUserTimeZone(string time) private string ExtractJsonValue(string json, string key)
{ {
try string pattern = $"\"{key}\":\"(.*?)\"";
{ Match match = Regex.Match(json, pattern);
// Assumed to be in US Eastern Time return match.Success ? match.Groups[1].Value : string.Empty;
DateTime easternTime = DateTime.ParseExact(time, "h:mmtt", System.Globalization.CultureInfo.InvariantCulture);
TimeZoneInfo easternTimeZone = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");
DateTime userTime = TimeZoneInfo.ConvertTime(easternTime, easternTimeZone, Core.Globals.GeneralOptions.TimeZoneInfo);
// Format the time as "hh:mmtt" (e.g., "06:30am")
return userTime.ToString("hh:mmtt").ToLower();
}
catch (Exception)
{
return time; // Return original time if conversion fails
}
} }
protected override void OnBarUpdate() { protected override void OnBarUpdate() {