laplace-api 3.1.0 → 4.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/publish.yml +37 -0
- package/.github/workflows/test.yml +25 -0
- package/README.md +461 -2
- package/package.json +1 -1
- package/src/client/broker.ts +79 -99
- package/src/client/capital_increase.ts +17 -22
- package/src/client/collections.ts +61 -40
- package/src/client/financial_fundamentals.ts +40 -35
- package/src/client/financial_ratios.ts +168 -128
- package/src/client/funds.ts +139 -0
- package/src/client/key-insights.ts +17 -0
- package/src/client/live-price-web-socket.ts +84 -11
- package/src/client/live-price.ts +210 -58
- package/src/client/politician.ts +75 -0
- package/src/client/stocks.ts +85 -2
- package/src/test/broker.test.ts +581 -170
- package/src/test/capital_increase.test.ts +266 -15
- package/src/test/collections.test.ts +460 -17
- package/src/test/custom_theme.test.ts +256 -65
- package/src/test/financial_fundamentals.test.ts +301 -45
- package/src/test/financial_ratios.test.ts +376 -75
- package/src/test/funds.test.ts +317 -0
- package/src/test/helpers.ts +58 -0
- package/src/test/key-insight.test.ts +110 -0
- package/src/test/live-price.test.ts +427 -67
- package/src/test/politician.test.ts +253 -0
- package/src/test/readme.test.ts +483 -0
- package/src/test/search.test.ts +308 -23
- package/src/test/stocks.test.ts +800 -70
- package/src/utilities/configuration.ts +23 -10
- package/src/utilities/test.env +2 -2
|
@@ -1,3 +1,30 @@
|
|
|
1
|
+
import { Logger } from "winston";
|
|
2
|
+
import { LaplaceConfiguration } from "../utilities/configuration";
|
|
3
|
+
import { Client } from "./client";
|
|
4
|
+
|
|
5
|
+
interface WebSocketUrlResponse {
|
|
6
|
+
url: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
interface WebSocketUrlParams {
|
|
10
|
+
externalUserId: string;
|
|
11
|
+
feeds: LivePriceFeed[];
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export enum AccessorType {
|
|
15
|
+
User = "user",
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
interface UpdateUserDetailsParams {
|
|
19
|
+
externalUserID: string;
|
|
20
|
+
firstName?: string;
|
|
21
|
+
lastName?: string;
|
|
22
|
+
address?: string;
|
|
23
|
+
city?: string;
|
|
24
|
+
countryCode?: string;
|
|
25
|
+
accessorType?: AccessorType;
|
|
26
|
+
active: boolean;
|
|
27
|
+
}
|
|
1
28
|
|
|
2
29
|
interface RawBISTStockLiveData {
|
|
3
30
|
_id: number;
|
|
@@ -88,7 +115,7 @@ export class WebSocketError extends Error {
|
|
|
88
115
|
}
|
|
89
116
|
}
|
|
90
117
|
|
|
91
|
-
export class LivePriceWebSocketClient {
|
|
118
|
+
export class LivePriceWebSocketClient extends Client {
|
|
92
119
|
private ws: WebSocket | null = null;
|
|
93
120
|
private subscriptionCounter = 0;
|
|
94
121
|
private subscriptions = new Map<
|
|
@@ -99,7 +126,10 @@ export class LivePriceWebSocketClient {
|
|
|
99
126
|
feed: LivePriceFeed;
|
|
100
127
|
}
|
|
101
128
|
>();
|
|
102
|
-
private symbolLastData = new Map<
|
|
129
|
+
private symbolLastData = new Map<
|
|
130
|
+
string,
|
|
131
|
+
BISTStockLiveData | USStockLiveData
|
|
132
|
+
>();
|
|
103
133
|
private reconnectAttempts = 0;
|
|
104
134
|
private reconnectTimeout: NodeJS.Timeout | null = null;
|
|
105
135
|
private isClosed: boolean = false;
|
|
@@ -110,8 +140,19 @@ export class LivePriceWebSocketClient {
|
|
|
110
140
|
private lastMessageTimestamp: number = 0;
|
|
111
141
|
private inactivityCheckInterval: NodeJS.Timeout | null = null;
|
|
112
142
|
private readonly INACTIVITY_TIMEOUT = 15000;
|
|
143
|
+
private externalUserId: string | null = null;
|
|
144
|
+
private feeds: LivePriceFeed[] | null = null;
|
|
113
145
|
|
|
114
|
-
constructor(
|
|
146
|
+
constructor(
|
|
147
|
+
feeds: LivePriceFeed[],
|
|
148
|
+
externalUserId: string,
|
|
149
|
+
cfg: LaplaceConfiguration,
|
|
150
|
+
logger: Logger,
|
|
151
|
+
options: WebSocketOptions = {}
|
|
152
|
+
) {
|
|
153
|
+
super(cfg, logger);
|
|
154
|
+
this.feeds = feeds;
|
|
155
|
+
this.externalUserId = externalUserId;
|
|
115
156
|
this.options = {
|
|
116
157
|
enableLogging: true,
|
|
117
158
|
logLevel: LogLevel.Error,
|
|
@@ -128,17 +169,17 @@ export class LivePriceWebSocketClient {
|
|
|
128
169
|
clearInterval(this.inactivityCheckInterval);
|
|
129
170
|
this.inactivityCheckInterval = null;
|
|
130
171
|
}
|
|
131
|
-
|
|
132
|
-
this.inactivityCheckInterval = setInterval(async ()=> {
|
|
172
|
+
|
|
173
|
+
this.inactivityCheckInterval = setInterval(async () => {
|
|
133
174
|
if (Date.now() - this.lastMessageTimestamp >= this.INACTIVITY_TIMEOUT) {
|
|
134
175
|
this.stopInactivityInterval();
|
|
135
176
|
try {
|
|
136
177
|
this.attemptReconnect();
|
|
137
|
-
} catch(error) {
|
|
178
|
+
} catch (error) {
|
|
138
179
|
this.log(`Failed to reconnect: ${error}`, "error");
|
|
139
180
|
}
|
|
140
181
|
}
|
|
141
|
-
}, this.INACTIVITY_TIMEOUT)
|
|
182
|
+
}, this.INACTIVITY_TIMEOUT);
|
|
142
183
|
}
|
|
143
184
|
|
|
144
185
|
private stopInactivityInterval() {
|
|
@@ -175,12 +216,43 @@ export class LivePriceWebSocketClient {
|
|
|
175
216
|
}
|
|
176
217
|
}
|
|
177
218
|
|
|
178
|
-
async
|
|
219
|
+
async updateUserDetails(params: UpdateUserDetailsParams): Promise<void> {
|
|
220
|
+
const url = new URL(`${this["baseUrl"]}/api/v1/ws/user`);
|
|
221
|
+
|
|
222
|
+
await this.sendRequest<void>({
|
|
223
|
+
method: "PUT",
|
|
224
|
+
url: url.toString(),
|
|
225
|
+
data: params,
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
private async getWebSocketUrl(): Promise<string> {
|
|
230
|
+
const url = new URL(`${this["baseUrl"]}/api/v2/ws/url`);
|
|
231
|
+
|
|
232
|
+
const params: WebSocketUrlParams = {
|
|
233
|
+
externalUserId: this.externalUserId!,
|
|
234
|
+
feeds: this.feeds!,
|
|
235
|
+
};
|
|
236
|
+
|
|
237
|
+
const response = await this.sendRequest<WebSocketUrlResponse>({
|
|
238
|
+
method: "POST",
|
|
239
|
+
url: url.toString(),
|
|
240
|
+
data: params,
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
return response.url;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
async connect(url?: string): Promise<WebSocket> {
|
|
179
247
|
this.log("Connecting to WebSocket...");
|
|
180
|
-
this.
|
|
248
|
+
if (!this.externalUserId || !this.feeds) {
|
|
249
|
+
throw new Error("External user ID and feeds are required");
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
this.wsUrl = url || (await this.getWebSocketUrl());
|
|
181
253
|
|
|
182
254
|
if (!this.ws || this.ws.readyState === WebSocket.CLOSED) {
|
|
183
|
-
this.ws = new WebSocket(
|
|
255
|
+
this.ws = new WebSocket(this.wsUrl);
|
|
184
256
|
this.connectPromise = this.setupWebSocket();
|
|
185
257
|
|
|
186
258
|
await this.connectPromise;
|
|
@@ -419,7 +491,8 @@ export class LivePriceWebSocketClient {
|
|
|
419
491
|
if (symbolHandlers.length === 1) {
|
|
420
492
|
symbolsToAdd.push(symbol);
|
|
421
493
|
} else if (symbolHandlers.length > 1) {
|
|
422
|
-
const lastData: BISTStockLiveData | USStockLiveData | undefined =
|
|
494
|
+
const lastData: BISTStockLiveData | USStockLiveData | undefined =
|
|
495
|
+
this.symbolLastData.get(symbol);
|
|
423
496
|
if (lastData) {
|
|
424
497
|
typedHandler(lastData);
|
|
425
498
|
}
|
package/src/client/live-price.ts
CHANGED
|
@@ -1,83 +1,235 @@
|
|
|
1
1
|
import { Client } from "./client";
|
|
2
2
|
import { Region } from "./collections";
|
|
3
|
-
import { v4 as uuidv4 } from
|
|
4
|
-
import { LivePriceFeed } from "./live-price-web-socket";
|
|
3
|
+
import { v4 as uuidv4 } from "uuid";
|
|
5
4
|
|
|
6
|
-
|
|
7
|
-
url: string;
|
|
8
|
-
}
|
|
5
|
+
export type MessageType = "pr" | "state_change" | "heartbeat" | "ob";
|
|
9
6
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
7
|
+
// Stream Message Wrapper - v2 formatter wraps all messages in this structure
|
|
8
|
+
export interface StreamMessage<T> {
|
|
9
|
+
t: MessageType;
|
|
10
|
+
d: T;
|
|
13
11
|
}
|
|
14
12
|
|
|
15
|
-
export interface
|
|
16
|
-
s: string;
|
|
13
|
+
export interface BISTStockPriceData {
|
|
14
|
+
s: string; // Symbol
|
|
17
15
|
ch: number; // DailyPercentChange
|
|
18
16
|
p: number; // ClosePrice
|
|
17
|
+
d: number; // Date
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface USStockPriceData {
|
|
21
|
+
s: string; // Symbol
|
|
22
|
+
p: number; // Price
|
|
23
|
+
d: number; // Date
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export type BISTStockStreamData = StreamMessage<BISTStockPriceData>;
|
|
27
|
+
export type USStockStreamData = StreamMessage<USStockPriceData>;
|
|
28
|
+
|
|
29
|
+
export enum OrderbookLevelSide {
|
|
30
|
+
Bid = "bid",
|
|
31
|
+
Ask = "ask"
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export interface OrderbookLevel {
|
|
35
|
+
level: number;
|
|
36
|
+
vol: number;
|
|
37
|
+
orders: number;
|
|
38
|
+
p: number;
|
|
39
|
+
side: OrderbookLevelSide;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export interface OrderbookDeletedLevel {
|
|
43
|
+
level: number;
|
|
44
|
+
side: OrderbookLevelSide;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export interface OrderbookLiveData {
|
|
48
|
+
updated?: OrderbookLevel[];
|
|
49
|
+
deleted?: OrderbookDeletedLevel[];
|
|
50
|
+
symbol: string;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export enum PriceDataType {
|
|
54
|
+
Live = "live",
|
|
55
|
+
Delayed = "delayed",
|
|
56
|
+
Orderbook = "orderbook",
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export interface ILivePriceClient<T> {
|
|
60
|
+
close(): void;
|
|
61
|
+
receive(): AsyncIterable<T>;
|
|
62
|
+
subscribe(symbols: string[]): Promise<void>;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
class LivePriceClientImpl<T> implements ILivePriceClient<T> {
|
|
66
|
+
private client: Client;
|
|
67
|
+
private region: Region;
|
|
68
|
+
private dataType: PriceDataType;
|
|
69
|
+
private symbols: string[] = [];
|
|
70
|
+
private closed = false;
|
|
71
|
+
private currentStream: AsyncIterable<T> | null = null;
|
|
72
|
+
private cancelFn: (() => void) | null = null;
|
|
73
|
+
|
|
74
|
+
constructor(client: Client, region: Region, dataType: PriceDataType) {
|
|
75
|
+
this.client = client;
|
|
76
|
+
this.region = region;
|
|
77
|
+
this.dataType = dataType;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
close(): void {
|
|
81
|
+
if (this.closed) return;
|
|
82
|
+
|
|
83
|
+
this.closed = true;
|
|
84
|
+
if (this.cancelFn) {
|
|
85
|
+
this.cancelFn();
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
receive(): AsyncIterable<T> {
|
|
90
|
+
if (!this.currentStream) {
|
|
91
|
+
throw new Error("Not subscribed. Call subscribe() first.");
|
|
92
|
+
}
|
|
93
|
+
return this.currentStream;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
async subscribe(symbols: string[]): Promise<void> {
|
|
97
|
+
// Cancel existing connection
|
|
98
|
+
if (this.cancelFn) {
|
|
99
|
+
this.cancelFn();
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const streamId = uuidv4();
|
|
103
|
+
let url: string;
|
|
104
|
+
|
|
105
|
+
switch (this.dataType) {
|
|
106
|
+
case PriceDataType.Live:
|
|
107
|
+
url = `${
|
|
108
|
+
this.client["baseUrl"]
|
|
109
|
+
}/api/v2/stock/price/live?filter=${symbols.join(",")}®ion=${
|
|
110
|
+
this.region
|
|
111
|
+
}&stream=${streamId}`;
|
|
112
|
+
break;
|
|
113
|
+
case PriceDataType.Delayed:
|
|
114
|
+
url = `${
|
|
115
|
+
this.client["baseUrl"]
|
|
116
|
+
}/api/v1/stock/price/delayed?filter=${symbols.join(",")}®ion=${
|
|
117
|
+
this.region
|
|
118
|
+
}&stream=${streamId}`;
|
|
119
|
+
break;
|
|
120
|
+
case PriceDataType.Orderbook:
|
|
121
|
+
url = `${
|
|
122
|
+
this.client["baseUrl"]
|
|
123
|
+
}/api/v1/stock/orderbook/live?filter=${symbols.join(",")}®ion=${
|
|
124
|
+
this.region
|
|
125
|
+
}&stream=${streamId}`;
|
|
126
|
+
break;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
const { events, cancel } = this.client.sendSSERequest<T>(url);
|
|
130
|
+
|
|
131
|
+
this.currentStream = events;
|
|
132
|
+
this.cancelFn = cancel;
|
|
133
|
+
this.symbols = symbols;
|
|
134
|
+
this.closed = false;
|
|
135
|
+
}
|
|
19
136
|
}
|
|
20
137
|
|
|
21
|
-
export
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
138
|
+
export function getLivePrice<T>(
|
|
139
|
+
client: Client,
|
|
140
|
+
symbols: string[],
|
|
141
|
+
region: Region
|
|
142
|
+
): ILivePriceClient<T> {
|
|
143
|
+
if (!client) {
|
|
144
|
+
throw new Error("Client cannot be null");
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const livePriceClient = new LivePriceClientImpl<T>(client, region, PriceDataType.Live);
|
|
148
|
+
livePriceClient.subscribe(symbols).catch((error) => {
|
|
149
|
+
console.error("Failed to initialize live price client", error);
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
return livePriceClient;
|
|
25
153
|
}
|
|
26
154
|
|
|
27
|
-
function
|
|
155
|
+
export function getDelayedPrice<T>(
|
|
28
156
|
client: Client,
|
|
29
157
|
symbols: string[],
|
|
30
158
|
region: Region,
|
|
31
|
-
|
|
32
|
-
)
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
const
|
|
159
|
+
): ILivePriceClient<T> {
|
|
160
|
+
if (!client) {
|
|
161
|
+
throw new Error("Client cannot be null");
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
const livePriceClient = new LivePriceClientImpl<T>(client, region, PriceDataType.Delayed);
|
|
165
|
+
livePriceClient.subscribe(symbols).catch((error) => {
|
|
166
|
+
console.error("Failed to initialize live price client", error);
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
return livePriceClient;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
function getOrderbook<T>(
|
|
173
|
+
client: Client,
|
|
174
|
+
symbols: string[],
|
|
175
|
+
region: Region,
|
|
176
|
+
): ILivePriceClient<T> {
|
|
177
|
+
if (!client) {
|
|
178
|
+
throw new Error("Client cannot be null");
|
|
179
|
+
}
|
|
37
180
|
|
|
38
|
-
|
|
181
|
+
const orderbookClient = new LivePriceClientImpl<T>(client, region, PriceDataType.Orderbook);
|
|
182
|
+
orderbookClient.subscribe(symbols).catch((error) => {
|
|
183
|
+
console.error("Failed to initialize orderbook client", error);
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
return orderbookClient;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
export function getLivePriceForBIST(
|
|
190
|
+
client: Client,
|
|
191
|
+
symbols: string[]
|
|
192
|
+
): ILivePriceClient<BISTStockStreamData> {
|
|
193
|
+
return getLivePrice<BISTStockStreamData>(client, symbols, Region.Tr);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
export function getLivePriceForUS(
|
|
197
|
+
client: Client,
|
|
198
|
+
symbols: string[]
|
|
199
|
+
): ILivePriceClient<USStockStreamData> {
|
|
200
|
+
return getLivePrice<USStockStreamData>(client, symbols, Region.Us);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
export function getDelayedPriceForBIST(
|
|
204
|
+
client: Client,
|
|
205
|
+
symbols: string[]
|
|
206
|
+
): ILivePriceClient<BISTStockStreamData> {
|
|
207
|
+
return getDelayedPrice<BISTStockStreamData>(client, symbols, Region.Tr);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
export function getOrderbookForBIST(
|
|
211
|
+
client: Client,
|
|
212
|
+
symbols: string[]
|
|
213
|
+
): ILivePriceClient<OrderbookLiveData> {
|
|
214
|
+
return getOrderbook<OrderbookLiveData>(client, symbols, Region.Tr);
|
|
39
215
|
}
|
|
40
216
|
|
|
41
217
|
export class LivePriceClient extends Client {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
const params: WebSocketUrlParams = {
|
|
49
|
-
externalUserId,
|
|
50
|
-
feeds
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
const response = await this.sendRequest<WebSocketUrlResponse>({
|
|
54
|
-
method: "POST",
|
|
55
|
-
url: url.toString(),
|
|
56
|
-
data: params,
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
return response.url;
|
|
218
|
+
getLivePriceForBIST(symbols: string[]): ILivePriceClient<BISTStockStreamData> {
|
|
219
|
+
return getLivePriceForBIST(this, symbols);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
getLivePriceForUS(symbols: string[]): ILivePriceClient<USStockStreamData> {
|
|
223
|
+
return getLivePriceForUS(this, symbols);
|
|
60
224
|
}
|
|
61
225
|
|
|
62
|
-
|
|
63
|
-
symbols: string[],
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
): {
|
|
67
|
-
events: AsyncIterable<BISTStockLiveData>,
|
|
68
|
-
cancel: () => void
|
|
69
|
-
} {
|
|
70
|
-
return getSSELivePrice<BISTStockLiveData>(this, symbols, region, streamId);
|
|
226
|
+
getDelayedPriceForBIST(
|
|
227
|
+
symbols: string[],
|
|
228
|
+
): ILivePriceClient<BISTStockStreamData> {
|
|
229
|
+
return getDelayedPriceForBIST(this, symbols);
|
|
71
230
|
}
|
|
72
231
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
region: Region,
|
|
76
|
-
streamId?: string,
|
|
77
|
-
): {
|
|
78
|
-
events: AsyncIterable<USStockLiveData>,
|
|
79
|
-
cancel: () => void
|
|
80
|
-
} {
|
|
81
|
-
return getSSELivePrice<USStockLiveData>(this, symbols, region, streamId);
|
|
232
|
+
getOrderbookForBIST(symbols: string[]): ILivePriceClient<OrderbookLiveData> {
|
|
233
|
+
return getOrderbookForBIST(this, symbols);
|
|
82
234
|
}
|
|
83
235
|
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { Client } from "./client";
|
|
2
|
+
|
|
3
|
+
export interface Politician {
|
|
4
|
+
id: number;
|
|
5
|
+
politicianName: string;
|
|
6
|
+
totalHoldings: number;
|
|
7
|
+
lastUpdated: Date;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface Holding {
|
|
11
|
+
politicianName: string;
|
|
12
|
+
symbol: string;
|
|
13
|
+
company: string;
|
|
14
|
+
holding: string;
|
|
15
|
+
allocation: string;
|
|
16
|
+
lastUpdated: Date;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface HoldingShort {
|
|
20
|
+
symbol: string;
|
|
21
|
+
company: string;
|
|
22
|
+
holding: string;
|
|
23
|
+
allocation: string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface TopHolding {
|
|
27
|
+
symbol: string;
|
|
28
|
+
company: string;
|
|
29
|
+
politicians: TopHoldingPolitician[];
|
|
30
|
+
count: number;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export interface TopHoldingPolitician {
|
|
34
|
+
name: string;
|
|
35
|
+
holding: string;
|
|
36
|
+
allocation: string;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export interface PoliticianDetail {
|
|
40
|
+
id: number;
|
|
41
|
+
name: string;
|
|
42
|
+
holdings: HoldingShort[];
|
|
43
|
+
totalHoldings: number;
|
|
44
|
+
lastUpdated: Date;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export class PoliticianClient extends Client {
|
|
48
|
+
async getAllPolitician(): Promise<Politician[]> {
|
|
49
|
+
return await this.sendRequest<Politician[]>({
|
|
50
|
+
method: 'GET',
|
|
51
|
+
url: `/api/v1/politician`,
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
async getPoliticianHoldingBySymbol(symbol: string): Promise<Holding[]> {
|
|
56
|
+
return await this.sendRequest<Holding[]>({
|
|
57
|
+
method: 'GET',
|
|
58
|
+
url: `/api/v1/holding/${symbol}`
|
|
59
|
+
})
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
async getAllTopHoldings(): Promise<TopHolding[]> {
|
|
63
|
+
return await this.sendRequest<TopHolding[]>({
|
|
64
|
+
method: 'GET',
|
|
65
|
+
url: `/api/v1/top-holding`
|
|
66
|
+
})
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
async getPoliticianDetail(id: number): Promise<PoliticianDetail> {
|
|
70
|
+
return await this.sendRequest<PoliticianDetail>({
|
|
71
|
+
method: 'GET',
|
|
72
|
+
url: `/api/v1/politician/${id}`
|
|
73
|
+
})
|
|
74
|
+
}
|
|
75
|
+
}
|
package/src/client/stocks.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { PaginatedResponse } from './capital_increase';
|
|
1
2
|
import { Client } from './client';
|
|
2
3
|
import { Region, Locale } from './collections';
|
|
3
4
|
import { LaplaceHTTPError } from './errors';
|
|
@@ -64,7 +65,7 @@ export interface StockDetail extends Stock {
|
|
|
64
65
|
shortDescription: string;
|
|
65
66
|
localizedShortDescription: LocaleString;
|
|
66
67
|
region: string;
|
|
67
|
-
markets
|
|
68
|
+
markets?: Market[];
|
|
68
69
|
}
|
|
69
70
|
|
|
70
71
|
export enum Market {
|
|
@@ -102,8 +103,10 @@ export interface StockRestriction {
|
|
|
102
103
|
id: number;
|
|
103
104
|
title: string;
|
|
104
105
|
description: string;
|
|
106
|
+
symbol?: string;
|
|
105
107
|
startDate: string;
|
|
106
108
|
endDate: string;
|
|
109
|
+
market?: string;
|
|
107
110
|
}
|
|
108
111
|
|
|
109
112
|
export interface TickRule {
|
|
@@ -111,7 +114,7 @@ export interface TickRule {
|
|
|
111
114
|
additionalPrice: number;
|
|
112
115
|
lowerPriceLimit: number;
|
|
113
116
|
upperPriceLimit: number;
|
|
114
|
-
rules: TickSizeRule[];
|
|
117
|
+
rules: TickSizeRule[] | null;
|
|
115
118
|
}
|
|
116
119
|
|
|
117
120
|
export interface TickSizeRule {
|
|
@@ -120,6 +123,32 @@ export interface TickSizeRule {
|
|
|
120
123
|
tickSize: number;
|
|
121
124
|
}
|
|
122
125
|
|
|
126
|
+
export interface EarningsTranscriptListItem {
|
|
127
|
+
symbol: string;
|
|
128
|
+
year: number;
|
|
129
|
+
quarter: number;
|
|
130
|
+
date: string;
|
|
131
|
+
fiscal_year: number;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
export interface EarningsTranscriptWithSummary {
|
|
135
|
+
symbol: string;
|
|
136
|
+
year: number;
|
|
137
|
+
quarter: number;
|
|
138
|
+
date: string;
|
|
139
|
+
content: string;
|
|
140
|
+
summary?: string;
|
|
141
|
+
has_summary: boolean;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export interface MarketState {
|
|
145
|
+
id: number;
|
|
146
|
+
marketSymbol?: string | null;
|
|
147
|
+
state: string;
|
|
148
|
+
lastTimestamp: string;
|
|
149
|
+
stockSymbol?: string | null;
|
|
150
|
+
}
|
|
151
|
+
|
|
123
152
|
export class StockClient extends Client {
|
|
124
153
|
async getAllStocks(region: Region, page: number|null = null, pageSize: number|null = null): Promise<Stock[]> {
|
|
125
154
|
return this.sendRequest<Stock[]>({
|
|
@@ -188,6 +217,14 @@ export class StockClient extends Client {
|
|
|
188
217
|
});
|
|
189
218
|
}
|
|
190
219
|
|
|
220
|
+
async getAllStockRestrictions(region: Region): Promise<StockRestriction[]> {
|
|
221
|
+
return this.sendRequest<StockRestriction[]>({
|
|
222
|
+
method: 'GET',
|
|
223
|
+
url: '/api/v1/stock/restrictions/all',
|
|
224
|
+
params: { region },
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
|
|
191
228
|
async getTickRules(symbol: string, region: Region): Promise<TickRule> {
|
|
192
229
|
return this.sendRequest<TickRule>({
|
|
193
230
|
method: 'GET',
|
|
@@ -195,4 +232,50 @@ export class StockClient extends Client {
|
|
|
195
232
|
params: { symbol, region },
|
|
196
233
|
});
|
|
197
234
|
}
|
|
235
|
+
|
|
236
|
+
async getEarningsTranscripts(symbol: string, region: Region): Promise<EarningsTranscriptListItem[]> {
|
|
237
|
+
return this.sendRequest<EarningsTranscriptListItem[]>({
|
|
238
|
+
method: 'GET',
|
|
239
|
+
url: '/api/v1/earnings/transcripts',
|
|
240
|
+
params: { symbol, region },
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
async getEarningsTranscript(symbol: string, year: number, quarter: number): Promise<EarningsTranscriptWithSummary> {
|
|
245
|
+
return this.sendRequest<EarningsTranscriptWithSummary>({
|
|
246
|
+
method: 'GET',
|
|
247
|
+
url: '/api/v1/earnings/transcript',
|
|
248
|
+
params: { symbol, year, quarter },
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
async getStockStateAll(page: number, size: number, region: Region): Promise<PaginatedResponse<MarketState>> {
|
|
253
|
+
return this.sendRequest<PaginatedResponse<MarketState>>({
|
|
254
|
+
method: 'GET',
|
|
255
|
+
url: '/api/v1/state/stock/all',
|
|
256
|
+
params: { page, size, region },
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
async getStockState(symbol: string): Promise<MarketState> {
|
|
261
|
+
return this.sendRequest<MarketState>({
|
|
262
|
+
method: 'GET',
|
|
263
|
+
url: `/api/v1/state/stock/${symbol}`,
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
async getStateAll(page: number, size: number, region: Region): Promise<PaginatedResponse<MarketState>> {
|
|
268
|
+
return this.sendRequest<PaginatedResponse<MarketState>>({
|
|
269
|
+
method: 'GET',
|
|
270
|
+
url: '/api/v1/state/all',
|
|
271
|
+
params: { page, size, region },
|
|
272
|
+
});
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
async getState(symbol: string): Promise<MarketState> {
|
|
276
|
+
return this.sendRequest<MarketState>({
|
|
277
|
+
method: 'GET',
|
|
278
|
+
url: `/api/v1/state/${symbol}`,
|
|
279
|
+
});
|
|
280
|
+
}
|
|
198
281
|
}
|