pinets 0.9.5 → 0.9.7
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/dist/pinets.min.browser.es.js +23 -40
- package/dist/pinets.min.browser.es.js.map +1 -1
- package/dist/pinets.min.browser.js +48 -65
- package/dist/pinets.min.browser.js.map +1 -1
- package/dist/pinets.min.cjs +23 -40
- package/dist/pinets.min.cjs.map +1 -1
- package/dist/pinets.min.es.js +45 -62
- package/dist/pinets.min.es.js.map +1 -1
- package/dist/types/Context.class.d.ts +24 -0
- package/dist/types/PineTS.class.d.ts +18 -1
- package/dist/types/errors/PineRuntimeError.d.ts +27 -0
- package/dist/types/index.d.ts +10 -1
- package/dist/types/marketData/Alpaca/AlpacaProvider.class.d.ts +115 -0
- package/dist/types/marketData/BaseProvider.d.ts +92 -0
- package/dist/types/marketData/Binance/BinanceProvider.class.d.ts +10 -12
- package/dist/types/marketData/FMP/FMPProvider.class.d.ts +69 -0
- package/dist/types/marketData/IProvider.d.ts +20 -7
- package/dist/types/marketData/Mock/MockProvider.class.d.ts +12 -29
- package/dist/types/marketData/Provider.class.d.ts +4 -1
- package/dist/types/marketData/aggregation.d.ts +38 -0
- package/dist/types/marketData/types.d.ts +106 -0
- package/dist/types/namespaces/Core.d.ts +40 -2
- package/dist/types/transpiler/analysis/ScopeManager.d.ts +4 -0
- package/dist/types/transpiler/pineToJS/codegen.d.ts +34 -1
- package/dist/types/transpiler/pineToJS/parser.d.ts +1 -0
- package/dist/types/transpiler/settings.d.ts +1 -0
- package/dist/types/transpiler/transformers/StatementTransformer.d.ts +10 -0
- package/package.json +4 -4
- package/dist/types/NaProxy.d.ts +0 -19
- package/dist/types/TimeSeries.class.d.ts +0 -49
- package/dist/types/TimeSeries.d.ts +0 -15
- package/dist/types/namespaces/Input.d.ts +0 -24
- package/dist/types/namespaces/PineArray.d.ts +0 -62
- package/dist/types/namespaces/PineColor.d.ts +0 -0
- package/dist/types/namespaces/PineMath.d.ts +0 -28
- package/dist/types/namespaces/PineRequest.d.ts +0 -8
- package/dist/types/namespaces/Plot.helper.d.ts +0 -16
- package/dist/types/namespaces/TechnicalAnalysis.d.ts +0 -30
- package/dist/types/namespaces/request/types/barmerge.type.d.ts +0 -7
- package/dist/types/namespaces/strategy/StrategySimulator.d.ts +0 -84
- package/dist/types/namespaces/strategy/closedtrades/index.d.ts +0 -18
- package/dist/types/namespaces/strategy/methods/any.d.ts +0 -5
- package/dist/types/namespaces/strategy/methods/cancel.d.ts +0 -1
- package/dist/types/namespaces/strategy/methods/cancel_all.d.ts +0 -1
- package/dist/types/namespaces/strategy/methods/cash.d.ts +0 -5
- package/dist/types/namespaces/strategy/methods/close.d.ts +0 -1
- package/dist/types/namespaces/strategy/methods/close_all.d.ts +0 -1
- package/dist/types/namespaces/strategy/methods/closedtrades.d.ts +0 -4
- package/dist/types/namespaces/strategy/methods/entry.d.ts +0 -3
- package/dist/types/namespaces/strategy/methods/equity.d.ts +0 -4
- package/dist/types/namespaces/strategy/methods/exit.d.ts +0 -3
- package/dist/types/namespaces/strategy/methods/fixed.d.ts +0 -5
- package/dist/types/namespaces/strategy/methods/long.d.ts +0 -4
- package/dist/types/namespaces/strategy/methods/netprofit.d.ts +0 -4
- package/dist/types/namespaces/strategy/methods/opentrades.d.ts +0 -4
- package/dist/types/namespaces/strategy/methods/order.d.ts +0 -6
- package/dist/types/namespaces/strategy/methods/param.d.ts +0 -5
- package/dist/types/namespaces/strategy/methods/percent_of_equity.d.ts +0 -5
- package/dist/types/namespaces/strategy/methods/position_avg_price.d.ts +0 -5
- package/dist/types/namespaces/strategy/methods/position_entry.d.ts +0 -5
- package/dist/types/namespaces/strategy/methods/position_entry_name.d.ts +0 -5
- package/dist/types/namespaces/strategy/methods/position_size.d.ts +0 -5
- package/dist/types/namespaces/strategy/methods/short.d.ts +0 -4
- package/dist/types/namespaces/strategy/models/Order.d.ts +0 -31
- package/dist/types/namespaces/strategy/models/Position.d.ts +0 -16
- package/dist/types/namespaces/strategy/models/Trade.d.ts +0 -45
- package/dist/types/namespaces/strategy/opentrades/index.d.ts +0 -10
- package/dist/types/namespaces/strategy/risk/index.d.ts +0 -11
- package/dist/types/namespaces/strategy/strategy.index.d.ts +0 -53
- package/dist/types/namespaces/strategy/types.d.ts +0 -92
- package/dist/types/namespaces/strategy/utils.d.ts +0 -28
- package/dist/types/namespaces/ta/getters/obv.d.ts +0 -12
- package/dist/types/namespaces/ta/getters/tr.d.ts +0 -1
- package/dist/types/transpiler/ScopeManager.class.d.ts +0 -36
|
@@ -14,7 +14,31 @@ export declare class Context {
|
|
|
14
14
|
isSecondaryContext: boolean;
|
|
15
15
|
chartTimezone: string | null;
|
|
16
16
|
dataVersion: number;
|
|
17
|
+
__maxLoops: number;
|
|
17
18
|
NA: any;
|
|
19
|
+
/** Runtime warnings (OOB access, etc.) — non-blocking, script continues. */
|
|
20
|
+
warnings: {
|
|
21
|
+
message: string;
|
|
22
|
+
method?: string;
|
|
23
|
+
bar: number;
|
|
24
|
+
}[];
|
|
25
|
+
/** Alert events emitted by alert() and alertcondition() calls. */
|
|
26
|
+
alerts: {
|
|
27
|
+
type: string;
|
|
28
|
+
id: string;
|
|
29
|
+
message: string;
|
|
30
|
+
title?: string;
|
|
31
|
+
freq?: string;
|
|
32
|
+
bar_index: number;
|
|
33
|
+
time: number;
|
|
34
|
+
}[];
|
|
35
|
+
/** Alert mode: 'realtime' = only fire on live bars (TV behavior), 'all' = fire on every bar (backtest). */
|
|
36
|
+
_alertMode: 'realtime' | 'all';
|
|
37
|
+
/** Monotonically increasing counter, incremented each time a bar starts executing.
|
|
38
|
+
* Used by alertcondition/AlertHelper to detect re-execution of the same bar. */
|
|
39
|
+
_execTick: number;
|
|
40
|
+
/** Emit a runtime warning. The script continues execution (returns na/no-op). */
|
|
41
|
+
warn(message: string, method?: string): void;
|
|
18
42
|
lang: any;
|
|
19
43
|
length: number;
|
|
20
44
|
/** References to drawing helpers for streaming rollback */
|
|
@@ -40,6 +40,23 @@ export declare class PineTS {
|
|
|
40
40
|
* @param timezone IANA timezone name (e.g. 'America/New_York'), UTC offset ('UTC+5'), or 'UTC'
|
|
41
41
|
*/
|
|
42
42
|
setTimezone(timezone: string): void;
|
|
43
|
+
private _maxLoops;
|
|
44
|
+
/**
|
|
45
|
+
* Set the maximum number of iterations allowed per loop.
|
|
46
|
+
* Mirrors TradingView's internal loop protection. If a for/while loop
|
|
47
|
+
* exceeds this limit, a runtime error is thrown.
|
|
48
|
+
* @param maxLoops Maximum iterations per loop (default: 500000)
|
|
49
|
+
*/
|
|
50
|
+
setMaxLoops(maxLoops: number): void;
|
|
51
|
+
private _alertMode;
|
|
52
|
+
/**
|
|
53
|
+
* Set alert mode.
|
|
54
|
+
* - 'realtime' (default): alerts only fire on the last (realtime) bar,
|
|
55
|
+
* matching TradingView behavior.
|
|
56
|
+
* - 'all': alerts fire on every bar, useful for backtesting alert strategies.
|
|
57
|
+
* @param mode Alert firing mode
|
|
58
|
+
*/
|
|
59
|
+
setAlertMode(mode: 'realtime' | 'all'): void;
|
|
43
60
|
constructor(source: IProvider | any[], tickerId?: string, timeframe?: string, limit?: number, sDate?: number, eDate?: number);
|
|
44
61
|
setDebugSettings({ ln, debug }: {
|
|
45
62
|
ln: boolean;
|
|
@@ -74,7 +91,7 @@ export declare class PineTS {
|
|
|
74
91
|
live?: boolean;
|
|
75
92
|
interval?: number;
|
|
76
93
|
}): {
|
|
77
|
-
on: (event: 'data' | 'error', callback: Function) => void;
|
|
94
|
+
on: (event: 'data' | 'error' | 'warning' | 'alert', callback: Function) => void;
|
|
78
95
|
stop: () => void;
|
|
79
96
|
};
|
|
80
97
|
/**
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runtime error thrown by PineTS when a Pine Script runtime violation occurs.
|
|
3
|
+
* Mirrors TradingView behavior where operations like out-of-bounds array/matrix
|
|
4
|
+
* access or infinite loops halt the script with a runtime error.
|
|
5
|
+
*
|
|
6
|
+
* Consumers can catch this specific error type to distinguish Pine runtime
|
|
7
|
+
* errors from general JavaScript errors:
|
|
8
|
+
*
|
|
9
|
+
* ```typescript
|
|
10
|
+
* try {
|
|
11
|
+
* const result = await pineTS.run(code);
|
|
12
|
+
* } catch (err) {
|
|
13
|
+
* if (err instanceof PineRuntimeError) {
|
|
14
|
+
* console.log('Pine runtime error:', err.message);
|
|
15
|
+
* console.log('Method:', err.method); // e.g. 'array.get'
|
|
16
|
+
* }
|
|
17
|
+
* }
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
export declare class PineRuntimeError extends Error {
|
|
21
|
+
/**
|
|
22
|
+
* The Pine Script method that caused the error (e.g. 'array.get', 'matrix.set').
|
|
23
|
+
* May be undefined for non-method errors (e.g. loop guard).
|
|
24
|
+
*/
|
|
25
|
+
method?: string;
|
|
26
|
+
constructor(message: string, method?: string);
|
|
27
|
+
}
|
package/dist/types/index.d.ts
CHANGED
|
@@ -2,4 +2,13 @@ import PineTS from './PineTS.class';
|
|
|
2
2
|
import { Context } from './Context.class';
|
|
3
3
|
import { Provider } from './marketData/Provider.class';
|
|
4
4
|
import { Indicator } from './Indicator';
|
|
5
|
-
|
|
5
|
+
import { PineRuntimeError } from './errors/PineRuntimeError';
|
|
6
|
+
export { BaseProvider } from './marketData/BaseProvider';
|
|
7
|
+
export { BinanceProvider } from './marketData/Binance/BinanceProvider.class';
|
|
8
|
+
export { FMPProvider } from './marketData/FMP/FMPProvider.class';
|
|
9
|
+
export { AlpacaProvider } from './marketData/Alpaca/AlpacaProvider.class';
|
|
10
|
+
export type { IProvider, ISymbolInfo, BaseProviderConfig, ApiKeyProviderConfig } from './marketData/IProvider';
|
|
11
|
+
export type { Kline, PeriodType } from './marketData/types';
|
|
12
|
+
export { computeNextPeriodStart, localTimeToUTC, computeSessionClose, TIMEFRAME_SECONDS, TIMEFRAME_PERIOD_INFO } from './marketData/types';
|
|
13
|
+
export { aggregateCandles, selectSubTimeframe, getAggregationRatio } from './marketData/aggregation';
|
|
14
|
+
export { PineTS, Context, Provider, Indicator, PineRuntimeError };
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { ISymbolInfo, ApiKeyProviderConfig } from '@pinets/marketData/IProvider';
|
|
2
|
+
import { BaseProvider } from '@pinets/marketData/BaseProvider';
|
|
3
|
+
import { Kline } from '@pinets/marketData/types';
|
|
4
|
+
/**
|
|
5
|
+
* Configuration for AlpacaProvider.
|
|
6
|
+
*
|
|
7
|
+
* @property apiKey - Alpaca API Key ID
|
|
8
|
+
* @property apiSecret - Alpaca API Secret Key
|
|
9
|
+
* @property paper - Use paper trading endpoint for asset info (default: true)
|
|
10
|
+
* @property feed - Market data feed: 'sip' (paid, full market) or 'iex' (free tier). Default: 'sip'
|
|
11
|
+
* @property dataUrl - Override the market data base URL
|
|
12
|
+
* @property tradingUrl - Override the trading/asset API base URL
|
|
13
|
+
*/
|
|
14
|
+
export interface AlpacaProviderConfig extends ApiKeyProviderConfig {
|
|
15
|
+
apiSecret: string;
|
|
16
|
+
paper?: boolean;
|
|
17
|
+
feed?: 'sip' | 'iex';
|
|
18
|
+
dataUrl?: string;
|
|
19
|
+
tradingUrl?: string;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Alpaca Markets data provider.
|
|
23
|
+
*
|
|
24
|
+
* Supports US stocks and crypto via Alpaca's Market Data API v2.
|
|
25
|
+
* All timeframes (1Min through 1Month) are natively supported.
|
|
26
|
+
*
|
|
27
|
+
* ## Usage
|
|
28
|
+
*
|
|
29
|
+
* ### Direct instantiation:
|
|
30
|
+
* ```typescript
|
|
31
|
+
* const alpaca = new AlpacaProvider({
|
|
32
|
+
* apiKey: 'PK...',
|
|
33
|
+
* apiSecret: '...',
|
|
34
|
+
* });
|
|
35
|
+
* const pineTS = new PineTS(alpaca, 'AAPL', 'D', null, sDate, eDate);
|
|
36
|
+
* ```
|
|
37
|
+
*
|
|
38
|
+
* ### Via Provider registry:
|
|
39
|
+
* ```typescript
|
|
40
|
+
* Provider.Alpaca.configure({ apiKey: 'PK...', apiSecret: '...' });
|
|
41
|
+
* const pineTS = new PineTS(Provider.Alpaca, 'AAPL', 'D', null, sDate, eDate);
|
|
42
|
+
* ```
|
|
43
|
+
*
|
|
44
|
+
* ## API Keys
|
|
45
|
+
* Get free API keys at https://alpaca.markets/
|
|
46
|
+
* Free tier provides IEX data; paid plan adds SIP (full market) data.
|
|
47
|
+
*
|
|
48
|
+
* ## Symbol Format
|
|
49
|
+
* - Stocks: `AAPL`, `MSFT`, `SPY`
|
|
50
|
+
* - Crypto: `BTC/USD`, `ETH/USD` (slash notation)
|
|
51
|
+
*/
|
|
52
|
+
export declare class AlpacaProvider extends BaseProvider<AlpacaProviderConfig> {
|
|
53
|
+
private _apiKey;
|
|
54
|
+
private _apiSecret;
|
|
55
|
+
private _dataUrl;
|
|
56
|
+
private _tradingUrl;
|
|
57
|
+
private _feed;
|
|
58
|
+
private _assetCache;
|
|
59
|
+
/** Calendar cache: date string "YYYY-MM-DD" → { open, close } times. */
|
|
60
|
+
private _calendarCache;
|
|
61
|
+
constructor(config?: AlpacaProviderConfig);
|
|
62
|
+
configure(config: AlpacaProviderConfig): void;
|
|
63
|
+
private _headers;
|
|
64
|
+
protected getSupportedTimeframes(): Set<string>;
|
|
65
|
+
protected _getMarketDataNative(tickerId: string, timeframe: string, limit?: number, sDate?: number, eDate?: number): Promise<Kline[]>;
|
|
66
|
+
/**
|
|
67
|
+
* Fetch all bars with automatic pagination.
|
|
68
|
+
*/
|
|
69
|
+
private _fetchAllBars;
|
|
70
|
+
/**
|
|
71
|
+
* Build the bars URL for stocks or crypto.
|
|
72
|
+
*/
|
|
73
|
+
private _buildBarsUrl;
|
|
74
|
+
getSymbolInfo(tickerId: string): Promise<ISymbolInfo>;
|
|
75
|
+
/**
|
|
76
|
+
* Convert bars for crypto (24/7 — no session boundaries).
|
|
77
|
+
* closeTime = next bar's openTime, or openTime + period for last bar.
|
|
78
|
+
*/
|
|
79
|
+
private _convertBarsCrypto;
|
|
80
|
+
/**
|
|
81
|
+
* Convert bars for stocks using the Alpaca trading calendar.
|
|
82
|
+
* closeTime = exact session close from the calendar (handles early closes, DST).
|
|
83
|
+
*/
|
|
84
|
+
private _convertBarsStock;
|
|
85
|
+
/** Build a Kline from an AlpacaBar + computed times. */
|
|
86
|
+
private _toKline;
|
|
87
|
+
/**
|
|
88
|
+
* Find the last trading day of the week containing `barDate` and return
|
|
89
|
+
* its session close time in UTC ms.
|
|
90
|
+
*/
|
|
91
|
+
private _weeklyCloseFromCalendar;
|
|
92
|
+
/**
|
|
93
|
+
* Find the last trading day of the month containing `barDate` and return
|
|
94
|
+
* its session close time in UTC ms.
|
|
95
|
+
*/
|
|
96
|
+
private _monthlyCloseFromCalendar;
|
|
97
|
+
/**
|
|
98
|
+
* Ensure the calendar cache covers the given date range.
|
|
99
|
+
* Fetches from Alpaca's `GET /v2/calendar` endpoint, which returns
|
|
100
|
+
* per-day trading hours including early closes (data from 1970-2029).
|
|
101
|
+
*/
|
|
102
|
+
private _ensureCalendar;
|
|
103
|
+
private _fetchAsset;
|
|
104
|
+
/**
|
|
105
|
+
* Parse an Alpaca timeframe string (e.g., '1Min', '4Hour', '1Month')
|
|
106
|
+
* into a PeriodType and multiplier for calendar-aware date math.
|
|
107
|
+
*/
|
|
108
|
+
private _parseAlpacaTimeframe;
|
|
109
|
+
/** Resolve PineTS timeframe to Alpaca timeframe string. */
|
|
110
|
+
private _resolveTimeframe;
|
|
111
|
+
/** Heuristic: crypto tickers contain '/'. */
|
|
112
|
+
private _isCrypto;
|
|
113
|
+
/** Add N days to a "YYYY-MM-DD" date string. */
|
|
114
|
+
private _addDaysToDate;
|
|
115
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { IProvider, ISymbolInfo, BaseProviderConfig } from './IProvider';
|
|
2
|
+
import { Kline } from './types';
|
|
3
|
+
/**
|
|
4
|
+
* Abstract base class for market data providers.
|
|
5
|
+
*
|
|
6
|
+
* Provides shared logic: closeTime normalization, fail-early API key
|
|
7
|
+
* validation, and **automatic candle aggregation** for unsupported
|
|
8
|
+
* timeframes.
|
|
9
|
+
*
|
|
10
|
+
* ## Aggregation
|
|
11
|
+
*
|
|
12
|
+
* When a provider doesn't natively support a timeframe, `getMarketData()`
|
|
13
|
+
* automatically:
|
|
14
|
+
* 1. Selects the best sub-timeframe the provider supports
|
|
15
|
+
* 2. Fetches sub-candles via `_getMarketDataNative()`
|
|
16
|
+
* 3. Aggregates them into the requested timeframe
|
|
17
|
+
*
|
|
18
|
+
* Providers declare native support via `getSupportedTimeframes()` and
|
|
19
|
+
* implement `_getMarketDataNative()` for the actual API call.
|
|
20
|
+
*
|
|
21
|
+
* ## Usage
|
|
22
|
+
*
|
|
23
|
+
* ```typescript
|
|
24
|
+
* class MyProvider extends BaseProvider<MyConfig> {
|
|
25
|
+
* protected getSupportedTimeframes() {
|
|
26
|
+
* return new Set(['1', '5', '15', '60', 'D']);
|
|
27
|
+
* }
|
|
28
|
+
* protected async _getMarketDataNative(...) { ... }
|
|
29
|
+
* }
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
export declare abstract class BaseProvider<TConfig extends BaseProviderConfig = BaseProviderConfig> implements IProvider {
|
|
33
|
+
private _configured;
|
|
34
|
+
private _requiresApiKey;
|
|
35
|
+
private _providerName;
|
|
36
|
+
private _aggregationSubTimeframe;
|
|
37
|
+
constructor(options: {
|
|
38
|
+
requiresApiKey: boolean;
|
|
39
|
+
providerName: string;
|
|
40
|
+
});
|
|
41
|
+
/**
|
|
42
|
+
* Fail-early check — call at the top of `_getMarketDataNative()` / `getSymbolInfo()`
|
|
43
|
+
* in providers that require an API key.
|
|
44
|
+
*/
|
|
45
|
+
protected ensureConfigured(): void;
|
|
46
|
+
/**
|
|
47
|
+
* Base configure — marks the provider as configured.
|
|
48
|
+
* Subclasses override to store their specific config, and must call `super.configure(config)`.
|
|
49
|
+
*/
|
|
50
|
+
configure(config: TConfig): void;
|
|
51
|
+
/** Whether this provider has been configured (always true for keyless providers). */
|
|
52
|
+
get isConfigured(): boolean;
|
|
53
|
+
/**
|
|
54
|
+
* Shared closeTime normalization utility.
|
|
55
|
+
* Delegates to the standalone `normalizeCloseTime()` from `types.ts`.
|
|
56
|
+
*/
|
|
57
|
+
protected normalizeCloseTime(data: Kline[]): void;
|
|
58
|
+
/**
|
|
59
|
+
* Override the sub-timeframe used for aggregation.
|
|
60
|
+
* When set, this timeframe is used instead of auto-selecting the best divisor.
|
|
61
|
+
* Set to `null` to re-enable automatic selection.
|
|
62
|
+
*/
|
|
63
|
+
setAggregationSubTimeframe(subTimeframe: string | null): void;
|
|
64
|
+
/**
|
|
65
|
+
* Return the set of timeframes this provider supports natively.
|
|
66
|
+
*
|
|
67
|
+
* Override in subclasses. Default: all canonical timeframes (no aggregation).
|
|
68
|
+
* Use canonical keys: '1','3','5','15','30','45','60','120','180','240','D','W','M'
|
|
69
|
+
* and optionally second-based: '1S','5S','10S','15S','30S'.
|
|
70
|
+
*/
|
|
71
|
+
protected getSupportedTimeframes(): Set<string>;
|
|
72
|
+
/**
|
|
73
|
+
* Fetch market data — delegates to native fetch or aggregates from sub-candles.
|
|
74
|
+
*
|
|
75
|
+
* 1. If the timeframe is natively supported, delegates to `_getMarketDataNative()`.
|
|
76
|
+
* 2. Otherwise, selects the best sub-timeframe, fetches sub-candles, and aggregates.
|
|
77
|
+
*/
|
|
78
|
+
getMarketData(tickerId: string, timeframe: string, limit?: number, sDate?: number, eDate?: number): Promise<Kline[]>;
|
|
79
|
+
/**
|
|
80
|
+
* Fetch market data natively from the provider's API.
|
|
81
|
+
*
|
|
82
|
+
* Subclasses MUST implement this. It is called by the BaseProvider
|
|
83
|
+
* orchestrator either for the requested timeframe (if natively supported)
|
|
84
|
+
* or for a sub-candle timeframe (if aggregation is needed).
|
|
85
|
+
*/
|
|
86
|
+
protected abstract _getMarketDataNative(tickerId: string, timeframe: string, limit?: number, sDate?: number, eDate?: number): Promise<Kline[]>;
|
|
87
|
+
abstract getSymbolInfo(tickerId: string): Promise<ISymbolInfo>;
|
|
88
|
+
/**
|
|
89
|
+
* Compute how many sub-candles to fetch to produce `limit` aggregated candles.
|
|
90
|
+
*/
|
|
91
|
+
private _computeSubLimit;
|
|
92
|
+
}
|
|
@@ -1,15 +1,13 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import { ISymbolInfo } from '@pinets/marketData/IProvider';
|
|
2
|
+
import { BaseProvider } from '@pinets/marketData/BaseProvider';
|
|
3
|
+
import { Kline } from '@pinets/marketData/types';
|
|
4
|
+
/** Config for BinanceProvider (no API key needed). */
|
|
5
|
+
export interface BinanceProviderConfig {
|
|
6
|
+
}
|
|
7
|
+
export declare class BinanceProvider extends BaseProvider<BinanceProviderConfig> {
|
|
3
8
|
private cacheManager;
|
|
4
9
|
private activeApiUrl;
|
|
5
10
|
constructor();
|
|
6
|
-
/**
|
|
7
|
-
* Normalize closeTime to TradingView convention: closeTime = next bar's openTime.
|
|
8
|
-
* Binance raw API returns closeTime as (nextBarOpen - 1ms). For all bars except the
|
|
9
|
-
* last, we use the next bar's actual openTime (exact). For the last bar, we add 1ms
|
|
10
|
-
* to the raw value.
|
|
11
|
-
*/
|
|
12
|
-
private _normalizeCloseTime;
|
|
13
11
|
/**
|
|
14
12
|
* Resolves the working Binance API endpoint.
|
|
15
13
|
* Tries default first, then falls back to US endpoint.
|
|
@@ -21,13 +19,13 @@ export declare class BinanceProvider implements IProvider {
|
|
|
21
19
|
* Used internally by pagination methods that assemble chunks before normalizing.
|
|
22
20
|
*/
|
|
23
21
|
private _fetchRawChunk;
|
|
24
|
-
getMarketDataInterval(tickerId: string, timeframe: string, sDate: number, eDate: number): Promise<
|
|
22
|
+
getMarketDataInterval(tickerId: string, timeframe: string, sDate: number, eDate: number): Promise<Kline[]>;
|
|
25
23
|
private getMarketDataBackwards;
|
|
26
|
-
|
|
24
|
+
protected getSupportedTimeframes(): Set<string>;
|
|
25
|
+
protected _getMarketDataNative(tickerId: string, timeframe: string, limit?: number, sDate?: number, eDate?: number): Promise<Kline[]>;
|
|
27
26
|
/**
|
|
28
27
|
* Determines if pagination is needed based on the parameters
|
|
29
28
|
*/
|
|
30
29
|
private shouldPaginate;
|
|
31
30
|
getSymbolInfo(tickerId: string): Promise<ISymbolInfo>;
|
|
32
|
-
configure(config: any): void;
|
|
33
31
|
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { ISymbolInfo, ApiKeyProviderConfig } from '@pinets/marketData/IProvider';
|
|
2
|
+
import { BaseProvider } from '@pinets/marketData/BaseProvider';
|
|
3
|
+
import { Kline } from '@pinets/marketData/types';
|
|
4
|
+
/** Configuration for FMPProvider — requires an API key. */
|
|
5
|
+
export interface FMPProviderConfig extends ApiKeyProviderConfig {
|
|
6
|
+
/** Optional: override the base URL (e.g. for proxy or self-hosted). */
|
|
7
|
+
baseUrl?: string;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Financial Modeling Prep (FMP) market data provider.
|
|
11
|
+
*
|
|
12
|
+
* Supports stocks, ETFs, crypto, and forex via FMP's stable API.
|
|
13
|
+
*
|
|
14
|
+
* ## Usage
|
|
15
|
+
*
|
|
16
|
+
* ### Direct instantiation:
|
|
17
|
+
* ```typescript
|
|
18
|
+
* const fmp = new FMPProvider({ apiKey: 'your-key' });
|
|
19
|
+
* const pineTS = new PineTS(fmp, 'AAPL', 'D', null, sDate, eDate);
|
|
20
|
+
* ```
|
|
21
|
+
*
|
|
22
|
+
* ### Via Provider registry:
|
|
23
|
+
* ```typescript
|
|
24
|
+
* Provider.FMP.configure({ apiKey: 'your-key' });
|
|
25
|
+
* const pineTS = new PineTS(Provider.FMP, 'AAPL', 'D', null, sDate, eDate);
|
|
26
|
+
* ```
|
|
27
|
+
*
|
|
28
|
+
* ## API Key
|
|
29
|
+
* Get a free API key (250 req/day) at https://financialmodelingprep.com/
|
|
30
|
+
* Intraday data (1min, 5min, 15min, 30min, 1h, 4h) requires a paid plan.
|
|
31
|
+
*
|
|
32
|
+
* ## Symbol Format
|
|
33
|
+
* Use standard ticker symbols: `AAPL`, `MSFT`, `SPY`, `BTCUSD`, `EURUSD`
|
|
34
|
+
*/
|
|
35
|
+
export declare class FMPProvider extends BaseProvider<FMPProviderConfig> {
|
|
36
|
+
private _apiKey;
|
|
37
|
+
private _baseUrl;
|
|
38
|
+
private _profileCache;
|
|
39
|
+
constructor(config?: FMPProviderConfig);
|
|
40
|
+
configure(config: FMPProviderConfig): void;
|
|
41
|
+
protected getSupportedTimeframes(): Set<string>;
|
|
42
|
+
protected _getMarketDataNative(tickerId: string, timeframe: string, limit?: number, sDate?: number, eDate?: number): Promise<Kline[]>;
|
|
43
|
+
/**
|
|
44
|
+
* Fetch daily EOD data from FMP and convert to Kline format.
|
|
45
|
+
*/
|
|
46
|
+
private _fetchDailyData;
|
|
47
|
+
/**
|
|
48
|
+
* Fetch intraday chart data from FMP and convert to Kline format.
|
|
49
|
+
* Note: Requires a paid FMP plan.
|
|
50
|
+
*/
|
|
51
|
+
private _fetchIntradayData;
|
|
52
|
+
getSymbolInfo(tickerId: string): Promise<ISymbolInfo>;
|
|
53
|
+
private _fetchProfile;
|
|
54
|
+
/**
|
|
55
|
+
* Resolve session string and timezone for a ticker by fetching its profile.
|
|
56
|
+
* Falls back to NYSE defaults if profile is unavailable.
|
|
57
|
+
*/
|
|
58
|
+
private _resolveSessionInfo;
|
|
59
|
+
/** Convert ms timestamp to FMP date string "YYYY-MM-DD". */
|
|
60
|
+
private _msToDateStr;
|
|
61
|
+
/** Convert FMP date string "YYYY-MM-DD" to ms timestamp (UTC midnight). */
|
|
62
|
+
private _dateStrToMs;
|
|
63
|
+
/** Convert FMP datetime string "YYYY-MM-DD HH:MM:SS" to ms timestamp. */
|
|
64
|
+
private _dateTimeStrToMs;
|
|
65
|
+
/** Heuristic: crypto tickers end with USD/USDT/BTC/ETH. */
|
|
66
|
+
private _isCrypto;
|
|
67
|
+
/** Heuristic: forex pairs are 6 chars, two 3-letter currency codes. */
|
|
68
|
+
private _isForex;
|
|
69
|
+
}
|
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
import type { Kline } from './types';
|
|
2
|
+
/** Base config — all providers extend this (may be empty for keyless providers). */
|
|
3
|
+
export interface BaseProviderConfig {
|
|
4
|
+
}
|
|
5
|
+
/** Config for providers that require an API key (FMP, Alpaca, etc.). */
|
|
6
|
+
export interface ApiKeyProviderConfig extends BaseProviderConfig {
|
|
7
|
+
apiKey: string;
|
|
8
|
+
}
|
|
1
9
|
export type ISymbolInfo = {
|
|
2
10
|
current_contract: string;
|
|
3
11
|
description: string;
|
|
@@ -44,16 +52,21 @@ export type ISymbolInfo = {
|
|
|
44
52
|
* Market data provider interface.
|
|
45
53
|
*
|
|
46
54
|
* ## closeTime convention
|
|
47
|
-
* Providers MUST return `closeTime`
|
|
48
|
-
* `
|
|
49
|
-
*
|
|
50
|
-
*
|
|
55
|
+
* Providers MUST return `closeTime` as the **session close time** for the bar,
|
|
56
|
+
* mirroring TradingView's `time_close` built-in variable.
|
|
57
|
+
*
|
|
58
|
+
* - **Stocks / regulated markets**: `closeTime` = the session close time on
|
|
59
|
+
* the bar's trading day (e.g., 16:00 ET for NYSE daily bars, 13:00 ET for
|
|
60
|
+
* early-close days). For weekly/monthly bars, use the session close of the
|
|
61
|
+
* last trading day in the period.
|
|
62
|
+
* - **24/7 markets (crypto)**: `closeTime` = the start of the next bar
|
|
63
|
+
* (equivalent to `openTime + barDuration`), since there are no session gaps.
|
|
51
64
|
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
65
|
+
* Use `computeSessionClose()` from `types.ts` for session-aware computation,
|
|
66
|
+
* or the Alpaca Calendar API for exact per-day close times including early closes.
|
|
54
67
|
*/
|
|
55
68
|
export interface IProvider {
|
|
56
|
-
getMarketData(tickerId: string, timeframe: string, limit?: number, sDate?: number, eDate?: number): Promise<
|
|
69
|
+
getMarketData(tickerId: string, timeframe: string, limit?: number, sDate?: number, eDate?: number): Promise<Kline[]>;
|
|
57
70
|
getSymbolInfo(tickerId: string): Promise<ISymbolInfo>;
|
|
58
71
|
configure(config: any): void;
|
|
59
72
|
}
|
|
@@ -1,17 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
close: number;
|
|
8
|
-
volume: number;
|
|
9
|
-
closeTime: number;
|
|
10
|
-
quoteAssetVolume: number;
|
|
11
|
-
numberOfTrades: number;
|
|
12
|
-
takerBuyBaseAssetVolume: number;
|
|
13
|
-
takerBuyQuoteAssetVolume: number;
|
|
14
|
-
ignore: number | string;
|
|
1
|
+
import { ISymbolInfo } from '@pinets/marketData/IProvider';
|
|
2
|
+
import { BaseProvider } from '@pinets/marketData/BaseProvider';
|
|
3
|
+
import { Kline } from '@pinets/marketData/types';
|
|
4
|
+
/** Config for MockProvider. */
|
|
5
|
+
export interface MockProviderConfig {
|
|
6
|
+
dataDirectory?: string;
|
|
15
7
|
}
|
|
16
8
|
/**
|
|
17
9
|
* Mock Market Data Provider for Unit Tests
|
|
@@ -30,14 +22,12 @@ interface Kline {
|
|
|
30
22
|
*
|
|
31
23
|
* Example: BTCUSDC-1h-1704067200000-1763683199000.json
|
|
32
24
|
*/
|
|
33
|
-
export declare class MockProvider
|
|
25
|
+
export declare class MockProvider extends BaseProvider<MockProviderConfig> {
|
|
34
26
|
private dataCache;
|
|
35
27
|
private exchangeInfoCache;
|
|
36
28
|
private dataDirectory;
|
|
37
|
-
constructor(
|
|
38
|
-
configure(
|
|
39
|
-
dataDirectory?: string;
|
|
40
|
-
}): void;
|
|
29
|
+
constructor(dataDirectoryOrConfig?: string | MockProviderConfig);
|
|
30
|
+
configure(config: MockProviderConfig): void;
|
|
41
31
|
/**
|
|
42
32
|
* Generates a cache key for the data file
|
|
43
33
|
*/
|
|
@@ -58,8 +48,9 @@ export declare class MockProvider implements IProvider {
|
|
|
58
48
|
* Normalizes timeframe to match file naming convention
|
|
59
49
|
*/
|
|
60
50
|
private normalizeTimeframe;
|
|
51
|
+
protected getSupportedTimeframes(): Set<string>;
|
|
61
52
|
/**
|
|
62
|
-
* Implements
|
|
53
|
+
* Implements _getMarketDataNative
|
|
63
54
|
*
|
|
64
55
|
* @param tickerId - Symbol (e.g., 'BTCUSDC')
|
|
65
56
|
* @param timeframe - Timeframe (e.g., '1h', '60', 'D')
|
|
@@ -68,7 +59,7 @@ export declare class MockProvider implements IProvider {
|
|
|
68
59
|
* @param eDate - Optional end date (timestamp in milliseconds)
|
|
69
60
|
* @returns Promise<Kline[]> - Array of candle data
|
|
70
61
|
*/
|
|
71
|
-
|
|
62
|
+
protected _getMarketDataNative(tickerId: string, timeframe: string, limit?: number, sDate?: number, eDate?: number): Promise<Kline[]>;
|
|
72
63
|
/**
|
|
73
64
|
* Loads exchange info from JSON file
|
|
74
65
|
*/
|
|
@@ -80,13 +71,6 @@ export declare class MockProvider implements IProvider {
|
|
|
80
71
|
* @returns Promise<ISymbolInfo> - Symbol information
|
|
81
72
|
*/
|
|
82
73
|
getSymbolInfo(tickerId: string): Promise<ISymbolInfo>;
|
|
83
|
-
/**
|
|
84
|
-
* Normalize closeTime to TradingView convention: closeTime = next bar's openTime.
|
|
85
|
-
* Mock data files contain raw Binance data where closeTime = (nextBarOpen - 1ms).
|
|
86
|
-
* For all bars except the last, we use the next bar's actual openTime. For the
|
|
87
|
-
* last bar, we add 1ms to the raw value.
|
|
88
|
-
*/
|
|
89
|
-
private _normalizeCloseTime;
|
|
90
74
|
/**
|
|
91
75
|
* Clears the data cache
|
|
92
76
|
*/
|
|
@@ -96,4 +80,3 @@ export declare class MockProvider implements IProvider {
|
|
|
96
80
|
*/
|
|
97
81
|
setDataDirectory(directory: string): void;
|
|
98
82
|
}
|
|
99
|
-
export {};
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { IProvider } from './IProvider';
|
|
2
|
+
export { BinanceProvider } from './Binance/BinanceProvider.class';
|
|
3
|
+
export { FMPProvider } from './FMP/FMPProvider.class';
|
|
4
|
+
export { AlpacaProvider } from './Alpaca/AlpacaProvider.class';
|
|
5
|
+
export { BaseProvider } from './BaseProvider';
|
|
2
6
|
type TProvider = {
|
|
3
7
|
[key: string]: IProvider;
|
|
4
8
|
};
|
|
5
9
|
export declare const Provider: TProvider;
|
|
6
10
|
export declare function registerProvider(name: string, provider: IProvider): void;
|
|
7
|
-
export {};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { Kline } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Given a target timeframe and a set of supported timeframes, select the
|
|
4
|
+
* best sub-timeframe to aggregate from.
|
|
5
|
+
*
|
|
6
|
+
* Strategy:
|
|
7
|
+
* - **W/M targets**: always use `'D'` (calendar-based grouping).
|
|
8
|
+
* - **All others**: pick the largest supported timeframe whose duration
|
|
9
|
+
* evenly divides the target duration (using `TIMEFRAME_SECONDS`).
|
|
10
|
+
*
|
|
11
|
+
* @returns The best sub-timeframe, or `null` if none found.
|
|
12
|
+
*/
|
|
13
|
+
export declare function selectSubTimeframe(targetTimeframe: string, supportedTimeframes: Set<string>): string | null;
|
|
14
|
+
/**
|
|
15
|
+
* Compute how many sub-candles fit into one aggregated candle.
|
|
16
|
+
*
|
|
17
|
+
* For fixed-duration aggregation: `targetSeconds / subSeconds`.
|
|
18
|
+
* For calendar-based (W/M from D): returns `Infinity` to signal variable grouping.
|
|
19
|
+
*/
|
|
20
|
+
export declare function getAggregationRatio(targetTimeframe: string, subTimeframe: string): number;
|
|
21
|
+
/**
|
|
22
|
+
* Aggregate sub-candles into higher-timeframe candles.
|
|
23
|
+
*
|
|
24
|
+
* Three modes:
|
|
25
|
+
* 1. **Fixed-ratio** (intraday → higher intraday): groups every N consecutive
|
|
26
|
+
* sub-candles, with session-boundary detection to avoid cross-session merging.
|
|
27
|
+
* 2. **Weekly from daily**: groups daily bars by ISO week number.
|
|
28
|
+
* 3. **Monthly from daily**: groups daily bars by calendar year+month.
|
|
29
|
+
*
|
|
30
|
+
* OHLCV merge:
|
|
31
|
+
* - `open` = first sub-candle's open
|
|
32
|
+
* - `high` = max of all highs
|
|
33
|
+
* - `low` = min of all lows
|
|
34
|
+
* - `close` = last sub-candle's close
|
|
35
|
+
* - `volume` = sum
|
|
36
|
+
* - `closeTime` = last sub-candle's closeTime (preserves session-aware close)
|
|
37
|
+
*/
|
|
38
|
+
export declare function aggregateCandles(subCandles: Kline[], targetTimeframe: string, subTimeframe: string): Kline[];
|