Skip to content

Commit 21a87bd

Browse files
Merge pull request #5 from LouisSzeto/master
New api endpoint, `BaseDataCollection` abstraction, demo algos
2 parents a53da8e + 57869bb commit 21a87bd

10 files changed

Lines changed: 550 additions & 211 deletions

.github/workflows/build.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,4 @@ jobs:
2121
run: dotnet build ./tests/Tests.csproj /p:Configuration=Release /v:quiet /p:WarningLevel=1
2222

2323
- name: Run Tests
24-
run: dotnet test ./tests/bin/Release/net5.0/Tests.dll
24+
run: dotnet test ./tests/bin/Release/net6.0/Tests.dll

QuantConnect.DataSource.csproj

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,25 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
4-
<TargetFramework>net5.0</TargetFramework>
4+
<TargetFramework>net6.0</TargetFramework>
55
<RootNamespace>QuantConnect.DataSource</RootNamespace>
66
<AssemblyName>QuantConnect.DataSource.RegalyticsArticles</AssemblyName>
77
<OutputPath>bin\$(Configuration)</OutputPath>
88
<DocumentationFile>$(OutputPath)\QuantConnect.DataSource.RegalyticsArticles.xml</DocumentationFile>
99
</PropertyGroup>
1010
<ItemGroup>
1111
<PackageReference Include="QuantConnect.Common" Version="2.5.*" />
12-
<PackageReference Include="protobuf-net" Version="3.0.29" />
1312
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
1413
</ItemGroup>
1514

1615
<ItemGroup>
1716
<Compile Remove="tests\**" />
1817
<EmbeddedResource Remove="tests\**" />
1918
<None Remove="tests\**" />
20-
<Compile Remove="Demonstration.cs" />
19+
<Compile Remove="RegalyticsRegulatoryArticlesDataAlgorithm.cs" />
20+
<None Remove="RegalyticsRegulatoryArticlesDataAlgorithm.py" />
2121
<None Remove=".gitignore" />
22-
<None Remove="process.sample.ipynb" />
23-
<None Remove="process.sample.py" />
24-
<None Remove="process.sample.sh" />
22+
<None Remove="process.py" />
2523
</ItemGroup>
2624

2725
</Project>

RegalyticsRegulatoryArticle.cs

Lines changed: 9 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -15,24 +15,19 @@
1515
*/
1616

1717
using System;
18-
using NodaTime;
19-
using ProtoBuf;
20-
using System.IO;
21-
using QuantConnect.Data;
2218
using System.Collections.Generic;
2319
using Newtonsoft.Json;
24-
using DateTimeUtilityFunctions = QuantConnect.Securities.Future.FuturesExpiryUtilityFunctions;
20+
using NodaTime;
21+
using QuantConnect.Data;
22+
using QuantConnect.Util;
2523

2624
namespace QuantConnect.DataSource
2725
{
2826
/// <summary>
2927
/// Regalytics Regulatory articles
3028
/// </summary>
31-
[ProtoContract(SkipConstructor = true)]
3229
public class RegalyticsRegulatoryArticle : BaseData
3330
{
34-
private DateTime _endTime;
35-
3631
/// <summary>
3732
/// Data source ID
3833
/// </summary>
@@ -92,34 +87,11 @@ public class RegalyticsRegulatoryArticle : BaseData
9287
[JsonProperty(PropertyName = "pdf_url")]
9388
public string AnnouncementUrl { get; set; }
9489

95-
public override DateTime EndTime
96-
{
97-
get { return _endTime; }
98-
set { _endTime = value; }
99-
}
90+
[JsonProperty(PropertyName = "created_at")]
91+
[JsonConverter(typeof(DateTimeJsonConverter), "yyyy-MM-dd'T'HH:mm:ss.ffffff")]
92+
public DateTime CreatedAt { get; set; }
10093

101-
/// <summary>
102-
/// Return the URL string source of the file. This will be converted to a stream
103-
/// </summary>
104-
/// <param name="config">Configuration object</param>
105-
/// <param name="date">Date of this source file</param>
106-
/// <param name="isLiveMode">true if we're in live mode, false for backtesting mode</param>
107-
/// <returns>String URL of source file.</returns>
108-
public override SubscriptionDataSource GetSource(SubscriptionDataConfig config, DateTime date, bool isLiveMode)
109-
{
110-
var publicationDate = DateTimeUtilityFunctions.AddBusinessDays(date.Date, -1, false);
111-
112-
return new SubscriptionDataSource(
113-
Path.Combine(
114-
Globals.DataFolder,
115-
"alternative",
116-
"regalytics",
117-
"articles",
118-
$"{publicationDate:yyyyMMdd}.json"
119-
),
120-
SubscriptionTransportMedium.LocalFile
121-
);
122-
}
94+
public override DateTime EndTime => Time.AddDays(1);
12395

12496
/// <summary>
12597
/// Parses the data from the line provided and loads it into LEAN
@@ -139,10 +111,7 @@ public override BaseData Reader(SubscriptionDataConfig config, string line, Date
139111
// us around 08:00:00 Eastern Time.
140112

141113
article.Symbol = config.Symbol;
142-
article.Time = article.LatestUpdate;
143-
article.EndTime = DateTimeUtilityFunctions.AddBusinessDays(article.LatestUpdate.Date, 1, false)
144-
.AddHours(8)
145-
.ConvertTo(TimeZones.NewYork, config.ExchangeTimeZone);
114+
article.Time = article.CreatedAt.Date;
146115

147116
return article;
148117
}
@@ -177,6 +146,7 @@ public override BaseData Clone()
177146
States = States,
178147
Agencies = Agencies,
179148
AnnouncementUrl = AnnouncementUrl,
149+
CreatedAt = CreatedAt
180150
};
181151
}
182152

RegalyticsRegulatoryArticles.cs

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
/*
2+
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
3+
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software
10+
* distributed under the License is distributed on an "AS IS" BASIS,
11+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
* See the License for the specific language governing permissions and
13+
* limitations under the License.
14+
*
15+
*/
16+
17+
using System;
18+
using System.Collections.Generic;
19+
using System.IO;
20+
using System.Linq;
21+
using NodaTime;
22+
using QuantConnect.Data;
23+
using QuantConnect.Data.UniverseSelection;
24+
using QuantConnect.Util;
25+
26+
namespace QuantConnect.DataSource
27+
{
28+
/// <summary>
29+
/// Regalytics Regulatory articles collection
30+
/// </summary>
31+
public class RegalyticsRegulatoryArticles : BaseDataCollection
32+
{
33+
private static readonly RegalyticsRegulatoryArticle _factory = new();
34+
35+
/// <summary>
36+
/// Return the URL string source of the file. This will be converted to a stream
37+
/// </summary>
38+
/// <param name="config">Configuration object</param>
39+
/// <param name="date">Date of this source file</param>
40+
/// <param name="isLiveMode">true if we're in live mode, false for backtesting mode</param>
41+
/// <returns>String URL of source file.</returns>
42+
public override SubscriptionDataSource GetSource(SubscriptionDataConfig config, DateTime date, bool isLiveMode)
43+
{
44+
return new SubscriptionDataSource(
45+
Path.Combine(
46+
Globals.DataFolder,
47+
"alternative",
48+
"regalytics",
49+
"articles",
50+
$"{date:yyyyMMdd}.json"
51+
),
52+
SubscriptionTransportMedium.LocalFile,
53+
FileFormat.FoldingCollection
54+
);
55+
}
56+
57+
/// <summary>
58+
/// Parses the data from the line provided and loads it into LEAN
59+
/// </summary>
60+
/// <param name="config">Subscription configuration</param>
61+
/// <param name="line">Line of data</param>
62+
/// <param name="date">Date</param>
63+
/// <param name="isLiveMode">Is live mode</param>
64+
/// <returns>New instance</returns>
65+
public override BaseData Reader(SubscriptionDataConfig config, string line, DateTime date, bool isLiveMode)
66+
{
67+
return _factory.Reader(config, line, date, isLiveMode);
68+
}
69+
70+
/// <summary>
71+
/// Clones the data
72+
/// </summary>
73+
/// <returns>A clone of the object</returns>
74+
public override BaseData Clone()
75+
{
76+
return new RegalyticsRegulatoryArticles
77+
{
78+
Symbol = Symbol,
79+
Time = Time,
80+
EndTime = EndTime,
81+
Data = Data?.ToList(point => point.Clone())
82+
};
83+
}
84+
85+
/// <summary>
86+
/// Formats a string with QuiverCNBC data
87+
/// </summary>
88+
/// <returns>string containing QuiverCNBC information</returns>
89+
public override string ToString()
90+
{
91+
return $"[{string.Join(",", Data.Select(data => data.ToString()))}]";
92+
}
93+
94+
/// <summary>
95+
/// Indicates whether the data source is tied to an underlying symbol and requires that corporate events be applied to it as well, such as renames and delistings
96+
/// </summary>
97+
/// <returns>false</returns>
98+
public override bool RequiresMapping()
99+
{
100+
return _factory.RequiresMapping();
101+
}
102+
103+
/// <summary>
104+
/// Indicates whether the data is sparse.
105+
/// If true, we disable logging for missing files
106+
/// </summary>
107+
/// <returns>true</returns>
108+
public override bool IsSparseData()
109+
{
110+
return _factory.IsSparseData();
111+
}
112+
113+
/// <summary>
114+
/// Gets the default resolution for this data and security type
115+
/// </summary>
116+
public override Resolution DefaultResolution()
117+
{
118+
return _factory.DefaultResolution();
119+
}
120+
121+
/// <summary>
122+
/// Gets the supported resolution for this data and security type
123+
/// </summary>
124+
public override List<Resolution> SupportedResolutions()
125+
{
126+
return _factory.SupportedResolutions();
127+
}
128+
129+
/// <summary>
130+
/// Specifies the data time zone for this data type. This is useful for custom data types
131+
/// </summary>
132+
/// <returns>The <see cref="T:NodaTime.DateTimeZone" /> of this data type</returns>
133+
public override DateTimeZone DataTimeZone()
134+
{
135+
return _factory.DataTimeZone();
136+
}
137+
}
138+
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
/*
2+
* QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
3+
* Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software
10+
* distributed under the License is distributed on an "AS IS" BASIS,
11+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
* See the License for the specific language governing permissions and
13+
* limitations under the License.
14+
*
15+
*/
16+
17+
using System.Linq;
18+
using QuantConnect.Algorithm;
19+
using QuantConnect.Data;
20+
using QuantConnect.DataSource;
21+
using QuantConnect.Util;
22+
23+
namespace QuantConnect.DataLibrary.Tests
24+
{
25+
public class RegalyticsDataAlgorithm : QCAlgorithm
26+
{
27+
private readonly string[] _negativeSentimentPhrases = new [] {"emergency rule", "proposed rule change", "development of rulemaking"};
28+
private Symbol _symbol;
29+
private Symbol _regalyticsSymbol;
30+
31+
public override void Initialize()
32+
{
33+
SetStartDate(2022, 7, 10);
34+
SetEndDate(2022, 7, 15);
35+
SetCash(100000);
36+
37+
_symbol = AddEquity("SPY", Resolution.Daily).Symbol;
38+
39+
// Requesting data
40+
_regalyticsSymbol = AddData<RegalyticsRegulatoryArticles>("REG").Symbol;
41+
42+
// Historical data
43+
var history = History<RegalyticsRegulatoryArticles>(_regalyticsSymbol, 7, Resolution.Daily);
44+
Debug($"We got {history.Count()} items from our history request");
45+
}
46+
47+
public override void OnData(Slice slice)
48+
{
49+
var data = slice.Get<RegalyticsRegulatoryArticles>();
50+
if (!data.IsNullOrEmpty())
51+
{
52+
foreach (var articles in data.Values)
53+
{
54+
Log($"{Time} {articles.ToString()}");
55+
foreach (RegalyticsRegulatoryArticle article in articles)
56+
{
57+
// based on the custom data property we will buy or short the underlying equity
58+
if (_negativeSentimentPhrases.Any(p => article.Title.ToLower().Contains(p)))
59+
{
60+
SetHoldings(_symbol, -1);
61+
}
62+
else
63+
{
64+
SetHoldings(_symbol, 1);
65+
}
66+
}
67+
}
68+
}
69+
}
70+
}
71+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
# QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
2+
# Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
7+
#
8+
# Unless required by applicable law or agreed to in writing, software
9+
# distributed under the License is distributed on an "AS IS" BASIS,
10+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
# See the License for the specific language governing permissions and
12+
# limitations under the License.
13+
14+
from AlgorithmImports import *
15+
16+
### <summary>
17+
### Example algorithm using the Regalytics data as a source of alpha
18+
### </summary>
19+
class RegalyticsDataAlgorithm(QCAlgorithm):
20+
21+
negative_sentiment_phrases = ['restrict', 'barrier', 'tariff']
22+
23+
def Initialize(self):
24+
''' Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized.'''
25+
self.SetStartDate(2022, 7, 10)
26+
self.SetEndDate(2022, 7, 15)
27+
self.SetCash(100000);
28+
29+
self.symbol = self.AddEquity("SPY", Resolution.Daily).Symbol
30+
31+
# Requesting data
32+
self.regalyticsSymbol = self.AddData(RegalyticsRegulatoryArticles, "REG").Symbol
33+
34+
# Historical data
35+
history = self.History(self.regalyticsSymbol, 7, Resolution.Daily)
36+
self.Debug(f"We got {len(history)} items from our history request")
37+
38+
def OnData(self, slice):
39+
''' OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here.
40+
:param Slice slice: Slice object keyed by symbol containing the stock data
41+
'''
42+
data = slice.Get(RegalyticsRegulatoryArticles)
43+
if not data: return
44+
45+
for articles in data.values():
46+
self.Log(articles.ToString())
47+
48+
for article in articles:
49+
# based on the custom data property we will buy or short the underlying equity
50+
if any([p in article.Title.lower() for p in self.negative_sentiment_phrases]):
51+
self.SetHoldings(self.symbol, -1)
52+
else:
53+
self.SetHoldings(self.symbol, 1)

0 commit comments

Comments
 (0)