- ago
Hello,

I have two questions regarding Event Data Points:

1. Is there a method similar to EarningsDate.GetNextUseCache in WL6 that can get the upcoming earning date from "Zacks"?

2. The code below is an attempt to mimic the inWindow method of the Community Components in WL6. It does the job, however, it seems that the GetEventDataPoints ignores the Data Range assign in the back testing and gets events for all the data. Hence the line (edp.Date > bars.DateTimes[0] was needed. Is that a correct understanding?

Thanks.

CODE:
using WealthLab.Backtest; using WealthLab.Core; using System.Collections.Generic; using System; using System.Drawing; using System.Linq; namespace WealthScript12 {    public class MyStrategy2 : UserStrategyBase    {       public override void Initialize(BarHistory bars)       {          earnings = bars.GetEventDataPoints("Earnings");          inWindow = new bool[bars.Count];          before = 1;          after = 1;          foreach (EventDataPoint edp in earnings)          {             if (edp.Date > bars.DateTimes[0])             {                int edayIndex = bars.IndexOf(edp.Date);                for (int i = edayIndex - before; i <= edayIndex + after; i++)                   inWindow[i] = true;                WriteToDebugLog(edp.ProviderName + "\t" + edp.Name + "\t" + edp.Date.ToShortDateString() + "\t" + edp.Details["Time"] + "\t" + edp.Value);             }          }          for (int i = 0; i < bars.Count; i++)          {             if (inWindow[i])                SetBackgroundColor(bars, i, Color.FromArgb(30, Color.Red));          }       }       //execute the strategy rules here, this is executed once for each bar in the backtest history       public override void Execute(BarHistory bars, int idx)       {       }              List<EventDataPoint> earnings;       EventDataPoint nextEarning;       bool[] inWindow;       int before;       int after;    } }


0
1,291
Solved
13 Replies

Reply

Bookmark

Sort
- ago
#1
Hello,

1. We have an automatically updating DataSetProvider called Upcoming Events. It's part of the DataExtensions. You can see it on the screenshot and give it a try:
https://www.wealth-lab.com/extension/detail/DataExtensions#screenshots

There is no such method as in WL6 but you can start a feature request and if it gets enough votes we'll implement it.
0
Best Answer
- ago
#2
QUOTE:
1. We have an automatically updating DataSetProvider called Upcoming Events.

And is the current implementation already caching upcoming earning dates today, or does this still need to be implemented somehow?

The WL6 EarningsDate.GetNextUseCache scraped four different websites for its information. Is this WL7 DataSetProvider doing the same thing now?

I'm very happy with the EarningsDate.GetNextUseCache function WL6 has. I thought about duplicating its functionality with the WL7 EventDataProvider, but perhaps that thinking was misguided. I want a provider that would cache the future earnings dates and check for periodic updates.
0
- ago
#3
QUOTE:
And is the current implementation already caching upcoming earning dates today, or does this still need to be implemented somehow?

Yes, the upcoming events are cached for today and replaced with new events at the next market session.
0
- ago
#4
QUOTE:
Yes, the upcoming events are cached for today ...

So you're saying the DataSetProvider only caches in volatile memory for one day. What about the EventDataProvider? Will that cache on disk and only request occasional updates rather than everyday?

The WL6 EarningsDate.GetNextUseCache function has a disk cache, so it's fast and not constantly requesting updates everyday. That's much better. Daily updates take a great deal of extra time to do and some data sources (e.g. YCharts) charge monthly for bandwidth, so disk caching can save time and money.
0
- ago
#5
QUOTE:
So you're saying the DataSetProvider only caches in volatile memory for one day.

Yes. This principle applies to select DataSetProviders like the StockScanner and HighShortInterest.

QUOTE:
What about the EventDataProvider? Will that cache on disk and only request occasional updates rather than everyday?

If you're talking about the Zacks event provider for historical Earnings items, then their history is saved firmly in a file on a per stock basis. Just like any other event provider for splits, dividends, EPS, insider transaction and other items.

Don't ask me about the exact frequency of event updates but their last date is cached on a per symbol basis to avoid repeated requests.

P.S. A side note. There is no "upcoming earnings provider" nor we intend to build one: it would make no sense since the future bars do not appear on the chart.
0
- ago
#6
QUOTE:
There is no "upcoming earnings provider" nor we intend to build one: it would make no sense since the future bars do not appear on the chart.

I follow your point; the EventDataProvider is designed for caching vector (not scaler) data for Chart display.

I'm just wondering if one wants to write a disk caching, GetNextUseCache function; if he could do it with the EventDataProvider even though its plotting functions would never be used and its vectors would only contain one element per stock? Perhaps it's a bad fit for implementing the GetNextUseCache function--bad idea. :(

So the conclusion for implementing the GetNextUseCache function is to write custom "scaler" disk caching code for the front end (strategy side) and use the DataSetProvider as the data gathering back end (Internet side)? Is this the best approach?
0
Cone8
 ( 4.98% )
- ago
#7
QUOTE:
There is no "upcoming earnings provider" nor we intend to build one: it would make no sense since the future bars do not appear on the chart.
Maybe we can reconsider?

Schedule events like earnings and dividends are good to know before they occur. A couple examples - a dip buyer may want to use a LimitMove order type on an earnings release. Another strategy might want to buy a stock 2 days before a scheduled dividend. Both of these examples can be backtested, but not easily traded unless upcoming events were known.
0
- ago
#8
Haven't we discussed this before? My point is, the provider that is unable to serve its goal of plotting an event item in the future is an oddball.

But we can extract and cache the upcoming earnings of a stock in the manner of the EarningsDate helper class, that's for sure.
0
Glitch8
 ( 10.62% )
- ago
#9
Why can't the Event Provider plot future earnings in a chart with extended space to the right? Also, those future EventDataPoints would still be available for use in a C# coded Strategy.
0
- ago
#10
QUOTE:
Also, those future EventDataPoints would still be available for use in a C# coded Strategy.


Exactly. Being able to use the date in a C# strategy would be helpful in different situations: Prevent a signal from triggering 3 days before earning, or the examples that Robert mentioned...
0
- ago
#11
QUOTE:
Being able to use the date in a C# strategy would be helpful in different situations: Prevent a signal from triggering 3 days before earning,...

I agree. And that's what I use the GetNextUseCache function for today on WL6. The question remains should the WL framework provide a built in way to cache this scaler (or very short vector) data conveniently?

I also thought about calculating a leading PEG ratio, but I would require three future "estimated" earnings values for that. And the only data source for that (I know about) is Zacks where their lowest tier is $1000/month for 200 metrics. I don't want to pay that for leading PEG ratios. There would need to be a cheaper data option before I become interested.
0
- ago
#12
@Shaaker

Here is a quick demo that scrapes the upcoming earnings date from Zacks, caches in global memory and prints to the chart.

Before it can run it will throw several compiler warnings. Open the Assembly References and check half a dozen of assemblies the error messages will suggest you to.



QUOTE:
using WealthLab.Backtest;
using System;
using WealthLab.Core;
using System.Collections.Generic;
using System.Net;
using System.Linq;
using System.Globalization;
using System.Drawing;

namespace WealthScript3
{
public class ZacksUpcomingEarnings : UserStrategyBase
{
public override void Initialize(BarHistory bars)
{
var symbol = bars.Symbol;

DateTime ue;
if (GetGlobal(symbol) == null)
{
ue = GetUpcomingEarnings(symbol).ReportDate;
SetGlobal(symbol, ue);
}
else
ue = (DateTime)GetGlobal(symbol);

if (ue != null)
DrawHeaderText("Report Date: " + ue.ToShortDateString(), Color.Blue, 14);
}

public override void Execute(BarHistory bars, int idx)
{
}

public static UpcomingEarnings GetUpcomingEarnings(string symbol)
{
try
{
using (WebClient wc = new WebClient())
{
wc.Headers.Add("Referer", "https://zacks.com/");
wc.Headers.Add("UserAgent", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:95.0) Gecko/20100101 Firefox/95.0");
wc.Headers.Add("Content-Type", "text/html, application/xhtml+xml, image/jxr, */*");

string text = wc.DownloadString(string.Format("https://www.zacks.com/stock/research/{0}/earnings-calendar", symbol.ToUpper()));
var doc = new HtmlAgilityPack.HtmlDocument();
doc.LoadHtml(text);

var repDate = Convert.ToDateTime(doc.DocumentNode.SelectNodes("//div[@class='key-expected-earnings-data-module']//th")[4].ChildNodes[0].InnerText, CultureInfo.GetCultureInfo("en-US"));

var table = doc.DocumentNode.SelectSingleNode("//div[@class='key-expected-earnings-data-module']//table")
.Descendants()
.Skip(1)
.Where(tr => tr.Elements("td").Count() > 1)
.Select(tr => tr.Elements("td").Select(td => td.InnerText.Trim()).ToList())
.ToList().Select(n =>
new
{
Symbol = symbol,
PeriodEnding = n[0],
Value = n[2],
Estimate = n[1],
});


var t = table.ToList()[0];
var ue = new UpcomingEarnings(symbol, repDate, t.Value, t.Estimate, t.PeriodEnding);

return ue;
}
}
catch (Exception)
{
}

return null;
}
}

public class UpcomingEarnings
{
public string Symbol { get; set; }
public DateTime ReportDate { get; set; }
public string Value { get; set; }
public string Estimate { get; set; }
public string PeriodEnding { get; set; }

public UpcomingEarnings(string symbol, DateTime reportDate, string val, string estimate, string periodEnding)
{
Symbol = symbol; ReportDate = reportDate; Value = val; Estimate = estimate; PeriodEnding = periodEnding;
}
}
}
0
- ago
#13
Heads-up for a breaking change! The EarningsDate class and related Event provider are moving to the Fundamental extension in build 11:
https://www.wealth-lab.com/extension/detail/Fundamental
0

Reply

Bookmark

Sort