Skip to content

Commit c752089

Browse files
authored
Updates to V3 (#10)
The new endpoint, https://api.regalytics.ai/api/v3, changes the format: 'articles' to 'results', 'states' to 'state' and 'countries' to 'country'. The 'id' from 'int' to 'string'.
1 parent 37a09d8 commit c752089

5 files changed

Lines changed: 50 additions & 49 deletions

File tree

.github/workflows/build.yml

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,18 @@ on:
88

99
jobs:
1010
build:
11-
runs-on: ubuntu-20.04
12-
container:
13-
image: quantconnect/lean:foundation
11+
runs-on: ubuntu-20.04
1412
steps:
15-
- uses: actions/checkout@v2
13+
- name: Checkout
14+
uses: actions/checkout@v2
15+
16+
- name: Free space
17+
run: df -h && rm -rf /opt/hostedtoolcache* && df -h
18+
19+
- name: Pull Foundation Image
20+
uses: addnab/docker-run-action@v3
21+
with:
22+
image: quantconnect/lean:foundation
1623

1724
- name: BuildDataSource
1825
run: dotnet build ./QuantConnect.DataSource.csproj /p:Configuration=Release /v:quiet /p:WarningLevel=1

QuantConnect.DataSource.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
</PropertyGroup>
1010
<ItemGroup>
1111
<PackageReference Include="QuantConnect.Common" Version="2.5.*" />
12-
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
12+
<PackageReference Include="Newtonsoft.Json" Version="13.0.2" />
1313
</ItemGroup>
1414

1515
<ItemGroup>

RegalyticsRegulatoryArticle.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ public class RegalyticsRegulatoryArticle : BaseData
3434
public static int DataSourceId { get; } = 2030;
3535

3636
[JsonProperty(PropertyName = "id")]
37-
public int Id { get; set; }
37+
public string Id { get; set; }
3838

3939
[JsonProperty(PropertyName = "title")]
4040
public string Title { get; set; }

process.py

Lines changed: 22 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,22 @@
1-
import json
2-
import pathlib
1+
from json import dumps
2+
from pathlib import Path
33
from datetime import datetime, timezone
4-
import os
5-
import requests
4+
from os import environ
5+
from requests import post
66

7-
URL = os.environ["REGALYTICS_API_BASE_URL"]
8-
HEADERS = {
9-
'Content-Type': 'application/json'
10-
}
11-
ARTICLE_PATH = pathlib.Path('/temp-output-directory/alternative/regalytics/articles')
7+
URL = environ.get("REGALYTICS_API_BASE_URL", "https://api.regalytics.ai/api/v3")
8+
API_KEY = environ.get("REGALYTICS_API_KEY", "")
9+
DEPLOYMENT_DATE = environ.get('QC_DATAFLEET_DEPLOYMENT_DATE', f'{datetime.now():%Y%m%d}')
1210

1311
# objectives:# download data from API -> temp folder or in memory. Output processed datat to /temp-output-directory/alternative/regalytics/articles/yyyyMMdd.json
12+
ARTICLE_PATH = Path('/temp-output-directory/alternative/regalytics/articles')
1413
ARTICLE_PATH.mkdir(parents=True, exist_ok=True)
1514
articles_by_date = {}
1615

17-
process_datetime = datetime.strptime(os.environ['QC_DATAFLEET_DEPLOYMENT_DATE'], '%Y%m%d').date()
18-
process_date = process_datetime.strftime('%Y-%m-%d')
16+
process_date = datetime.strptime(DEPLOYMENT_DATE, '%Y%m%d').strftime('%Y-%m-%d')
1917

20-
url = f"{URL}/search"
21-
payload = json.dumps({
22-
"apikey": os.environ["REGALYTICS_API_KEY"],
18+
payload = dumps({
19+
"apikey": API_KEY,
2320
"search_options": {
2421
"created_at": {
2522
"start": process_date,
@@ -28,18 +25,17 @@
2825
}
2926
})
3027

31-
response = requests.post(url, headers=HEADERS, data=payload).json()
32-
articles = response['articles']
28+
response = post(f"{URL}/search", headers={ 'Content-Type': 'application/json' }, data=payload).json()
3329

3430
# "agencies": [
3531
# {
3632
# "name": "Iowa Department of Human Services",
37-
# "states": [
33+
# "state": [
3834
# {
3935
# "name": "Iowa"
4036
# }
4137
# ],
42-
# "countries": [
38+
# "country": [
4339
# {
4440
# "name": "United States"
4541
# }
@@ -51,26 +47,18 @@
5147
# 1. query all data, -> /api/v2/.../get-all; 2. look at latest_update, add delta of 1/2 days;
5248
# 3. write data to date of latest_update + delta. This date must be on the date we published the article on Regalytics
5349

54-
for article in articles:
50+
for article in response.get('results', []):
5551
article['in_federal_register'] = 'yes' in article['in_federal_register'].lower()
5652
# State -> Dictionary<string, List<string>>
5753
states = {}
58-
for agency in article['agencies']:
59-
state = agency['states']
60-
61-
if 'states' not in agency or state is None:
54+
for agency in article.get('agencies', []):
55+
state = agency.get('state')
56+
if not state:
6257
continue
6358

64-
if 'countries' not in agency:
65-
continue
66-
67-
countries = agency['countries']
68-
if countries is None:
69-
continue
70-
71-
for country in countries:
59+
for country in agency.get('country', []):
7260
name = country['name']
73-
61+
7462
if not name in states:
7563
country_states = []
7664
states[name] = country_states
@@ -88,7 +76,7 @@
8876
article['created_at'] = article['created_at'][:-3] + article['created_at'][-2:] # %z only accepts `-0400` instead of `-04:00` in Python3.6
8977
created_at = datetime.strptime(article['created_at'], '%Y-%m-%dT%H:%M:%S.%f%z').astimezone(timezone.utc)
9078
article['created_at'] = created_at.strftime('%Y-%m-%dT%H:%M:%S.%f')
91-
date_key = created_at.date().strftime('%Y%m%d')
79+
date_key = created_at.strftime('%Y%m%d')
9280

9381
if date_key not in articles_by_date:
9482
date_articles = []
@@ -99,11 +87,6 @@
9987
date_articles.append(article)
10088

10189
for date, articles in articles_by_date.items():
102-
lines = []
103-
for article in articles:
104-
lines.append(json.dumps(article, indent=None))
105-
106-
article_lines = '\n'.join(lines)
107-
10890
with open(ARTICLE_PATH / f'{date}.json', 'w') as article_file:
91+
article_lines = '\n'.join([dumps(article, indent=None) for article in articles])
10992
article_file.write(article_lines)

tests/RegalyticsRegulatoryArticleTests.cs

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,18 @@ public void CloneCollection()
5555

5656
AssertAreEqual(expected, result);
5757
}
58-
58+
59+
[Test]
60+
public void BackwardCompatibilityToV2()
61+
{
62+
// The Id is a number in v2
63+
var line = "{\"id\": 2051381, \"title\": \"House of Representatives Study Bill HSB692: A bill for an act relating to school security, including by modifying provisions related to the issuance of school bonds, requiring schools to conduct school safety reviews and have access to the statewide interoperable communications system, establishing the school emergency radio access grant program and the firearm detection software grant program within the department of homeland security and emergency management, requiring the department of public (I)\", \"summary\": \"Introduced on 2024-02-12. House Study Bill 692 is a piece of legislation in Iowa that focuses on school security. It includes provisions related to the issuance of school bonds, requires schools to conduct safety reviews and have access to a statewide communications system, establishes grant programs for school emergency radio access and firearm detection software, and requires the Department of Public Safety to convene a task force on school safety standards. The bill also appropriates funds for these programs and specifies that the state cost of compliance with the legislation will be paid by school districts from state school foundation aid. The bill takes effect upon enactment. (99IA202320242022HSB692)\", \"status\": \"New\", \"classification\": \"State\", \"filing_type\": \"Single\", \"in_federal_register\": false, \"federal_register_number\": null, \"regalytics_alert_id\": \"99IA2022HSB69225120240212\", \"proposed_comments_due_date\": null, \"original_publication_date\": \"2024-02-12\", \"federal_register_publication_date\": null, \"rule_effective_date\": null, \"latest_update\": \"2024-02-12\", \"alert_type\": \"Study Bill\", \"docket_file_number\": \"\", \"order_notice\": \"\", \"sec_release_number\": \"\", \"agencies\": [\"Iowa House of Representatives\"], \"sector_type\": [{\"name\": \"Financial\"}], \"tags\": [{\"name\": \"All State and Federal Legislatures\"}, {\"name\": \"Introduced Bill\"}], \"subtype_classification\": [{\"name\": \"House of Representatives Study Bill\", \"higher_order_alert_classification\": {\"name\": \"Rule\"}}], \"pdf_url\": \"https://www.legis.iowa.gov/legislation/BillBook?ga=90&ba=HSB692\", \"created_at\": \"2024-02-12T22:31:40.567008\", \"states\": {\"United States\": [\"Iowa\"]}}";
64+
var instance = new RegalyticsRegulatoryArticle();
65+
var config = new SubscriptionDataConfig(instance.GetType(), Symbol.None, Resolution.Daily, TimeZones.Utc, TimeZones.Utc, false, false, false);
66+
var data = instance.Reader(config, line, new DateTime(2024, 2, 12), false) as RegalyticsRegulatoryArticle;
67+
Assert.AreEqual("2051381", data.Id);
68+
}
69+
5970
private void AssertAreEqual(object expected, object result, bool filterByCustomAttributes = false)
6071
{
6172
foreach (var propertyInfo in expected.GetType().GetProperties())
@@ -80,7 +91,7 @@ private BaseData CreateNewInstance()
8091
Time = DateTime.Today,
8192
DataType = MarketDataType.Base,
8293

83-
Id = 0,
94+
Id = "0",
8495
Title = "string",
8596
Summary = "string",
8697
Status = "string",
@@ -111,7 +122,7 @@ private BaseData CreateNewCollectionInstance()
111122
Time = DateTime.Today,
112123
DataType = MarketDataType.Base,
113124

114-
Id = 0,
125+
Id = "0",
115126
Title = "string",
116127
Summary = "string",
117128
Status = "string",
@@ -136,7 +147,7 @@ private BaseData CreateNewCollectionInstance()
136147
Time = DateTime.Today,
137148
DataType = MarketDataType.Base,
138149

139-
Id = 0,
150+
Id = "0",
140151
Title = "string",
141152
Summary = "string",
142153
Status = "string",

0 commit comments

Comments
 (0)