@nshiab/simple-data-analysis-core 2.0.4 → 2.0.5
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/esm/class/SimpleTable.d.ts +202 -8
- package/esm/class/SimpleTable.d.ts.map +1 -1
- package/esm/class/SimpleTable.js +211 -9
- package/esm/methods/addCharacterCount.d.ts +3 -0
- package/esm/methods/addCharacterCount.d.ts.map +1 -0
- package/esm/methods/addCharacterCount.js +15 -0
- package/esm/methods/addGeoNoise.d.ts +7 -0
- package/esm/methods/addGeoNoise.d.ts.map +1 -0
- package/esm/methods/addGeoNoise.js +135 -0
- package/esm/methods/addNoise.d.ts +5 -0
- package/esm/methods/addNoise.d.ts.map +1 -0
- package/esm/methods/addNoise.js +53 -0
- package/esm/methods/addWordCount.d.ts +3 -0
- package/esm/methods/addWordCount.d.ts.map +1 -0
- package/esm/methods/addWordCount.js +15 -0
- package/esm/methods/columnProportions.d.ts +1 -0
- package/esm/methods/columnProportions.d.ts.map +1 -1
- package/esm/methods/columnProportions.js +7 -2
- package/esm/methods/loadArray.d.ts +4 -2
- package/esm/methods/loadArray.d.ts.map +1 -1
- package/esm/methods/loadArray.js +113 -4
- package/esm/methods/loadYahooFinanceData.d.ts +10 -0
- package/esm/methods/loadYahooFinanceData.d.ts.map +1 -0
- package/esm/methods/loadYahooFinanceData.js +133 -0
- package/esm/methods/rowProportions.d.ts +1 -0
- package/esm/methods/rowProportions.d.ts.map +1 -1
- package/esm/methods/rowProportions.js +5 -1
- package/llm.md +291 -14
- package/llms.txt +1 -1
- package/package.json +1 -1
- package/script/class/SimpleTable.d.ts +202 -8
- package/script/class/SimpleTable.d.ts.map +1 -1
- package/script/class/SimpleTable.js +211 -9
- package/script/methods/addCharacterCount.d.ts +3 -0
- package/script/methods/addCharacterCount.d.ts.map +1 -0
- package/script/methods/addCharacterCount.js +21 -0
- package/script/methods/addGeoNoise.d.ts +7 -0
- package/script/methods/addGeoNoise.d.ts.map +1 -0
- package/script/methods/addGeoNoise.js +141 -0
- package/script/methods/addNoise.d.ts +5 -0
- package/script/methods/addNoise.d.ts.map +1 -0
- package/script/methods/addNoise.js +59 -0
- package/script/methods/addWordCount.d.ts +3 -0
- package/script/methods/addWordCount.d.ts.map +1 -0
- package/script/methods/addWordCount.js +21 -0
- package/script/methods/columnProportions.d.ts +1 -0
- package/script/methods/columnProportions.d.ts.map +1 -1
- package/script/methods/columnProportions.js +7 -2
- package/script/methods/loadArray.d.ts +4 -2
- package/script/methods/loadArray.d.ts.map +1 -1
- package/script/methods/loadArray.js +112 -3
- package/script/methods/loadYahooFinanceData.d.ts +10 -0
- package/script/methods/loadYahooFinanceData.d.ts.map +1 -0
- package/script/methods/loadYahooFinanceData.js +139 -0
- package/script/methods/rowProportions.d.ts +1 -0
- package/script/methods/rowProportions.d.ts.map +1 -1
- package/script/methods/rowProportions.js +5 -1
|
@@ -2,7 +2,7 @@ import { type DuckDBValue } from "@duckdb/node-api";
|
|
|
2
2
|
import type SimpleTable from "../class/SimpleTable.js";
|
|
3
3
|
export default function loadArray(simpleTable: SimpleTable, rows: {
|
|
4
4
|
[key: string]: unknown;
|
|
5
|
-
}[]): void;
|
|
5
|
+
}[], options?: NonNullable<Parameters<SimpleTable["loadArray"]>[1]>): void;
|
|
6
6
|
type PreparedArray = {
|
|
7
7
|
keys: string[];
|
|
8
8
|
types: string[];
|
|
@@ -11,7 +11,9 @@ type PreparedArray = {
|
|
|
11
11
|
};
|
|
12
12
|
export declare function prepareArray(rows: {
|
|
13
13
|
[key: string]: unknown;
|
|
14
|
-
}[]
|
|
14
|
+
}[], columnTypes?: {
|
|
15
|
+
[key: string]: string;
|
|
16
|
+
}): PreparedArray;
|
|
15
17
|
export declare function executePreparedArray(simpleTable: SimpleTable, prepared: PreparedArray): Promise<void>;
|
|
16
18
|
export {};
|
|
17
19
|
//# sourceMappingURL=loadArray.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loadArray.d.ts","sourceRoot":"","sources":["../../src/methods/loadArray.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"loadArray.d.ts","sourceRoot":"","sources":["../../src/methods/loadArray.ts"],"names":[],"mappings":"AAAA,OAAO,EAQL,KAAK,WAAW,EACjB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,KAAK,WAAW,MAAM,yBAAyB,CAAC;AAKvD,MAAM,CAAC,OAAO,UAAU,SAAS,CAC/B,WAAW,EAAE,WAAW,EACxB,IAAI,EAAE;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CAAE,EAAE,EAClC,OAAO,GAAE,WAAW,CAAC,UAAU,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAM,QAiBnE;AAED,KAAK,aAAa,GAAG;IACnB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,WAAW,EAAE,WAAW,EAAE,EAAE,CAAC;IAC7B,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF,wBAAgB,YAAY,CAC1B,IAAI,EAAE;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CAAE,EAAE,EAClC,WAAW,GAAE;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;CAAO,GAC1C,aAAa,CA2Ff;AAED,wBAAsB,oBAAoB,CACxC,WAAW,EAAE,WAAW,EACxB,QAAQ,EAAE,aAAa,iBA+BxB"}
|
package/esm/methods/loadArray.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import { arrayValue, DuckDBDataChunk, DuckDBTimestampValue, } from "@duckdb/node-api";
|
|
1
|
+
import { arrayValue, DuckDBDataChunk, DuckDBDateValue, DuckDBTimestampTZValue, DuckDBTimestampValue, DuckDBTimeValue, } from "@duckdb/node-api";
|
|
2
2
|
import queueOp from "../helpers/queueOp.js";
|
|
3
3
|
import parseType from "../helpers/parseTypes.js";
|
|
4
4
|
import parseDuckDBType from "../helpers/parseDuckDBType.js";
|
|
5
5
|
import quoteIdentifier from "../helpers/quoteIdentifier.js";
|
|
6
|
-
export default function loadArray(simpleTable, rows) {
|
|
6
|
+
export default function loadArray(simpleTable, rows, options = {}) {
|
|
7
7
|
// This validation doesn't need the database, so it stays at call time.
|
|
8
8
|
if (rows.length === 0) {
|
|
9
9
|
throw new Error("The array is empty. loadArray needs at least one object to infer the column types.");
|
|
10
10
|
}
|
|
11
|
-
const prepared = prepareArray(rows);
|
|
11
|
+
const prepared = prepareArray(rows, options.columnTypes);
|
|
12
12
|
queueOp(simpleTable, {
|
|
13
13
|
kind: "barrier",
|
|
14
14
|
method: "loadArray()",
|
|
@@ -16,14 +16,38 @@ export default function loadArray(simpleTable, rows) {
|
|
|
16
16
|
execute: () => executePreparedArray(simpleTable, prepared),
|
|
17
17
|
});
|
|
18
18
|
}
|
|
19
|
-
export function prepareArray(rows) {
|
|
19
|
+
export function prepareArray(rows, columnTypes = {}) {
|
|
20
20
|
const keys = Object.keys(rows[0]);
|
|
21
|
+
const overrides = new Map();
|
|
22
|
+
for (const [key, type] of Object.entries(columnTypes)) {
|
|
23
|
+
if (!keys.includes(key)) {
|
|
24
|
+
throw new Error(`Unknown column ${JSON.stringify(key)} in loadArray columnTypes.`);
|
|
25
|
+
}
|
|
26
|
+
try {
|
|
27
|
+
const normalized = /^FLOAT\[[1-9]\d*\]$/i.test(type)
|
|
28
|
+
? type.toUpperCase()
|
|
29
|
+
: parseType(type);
|
|
30
|
+
parseDuckDBType(normalized);
|
|
31
|
+
overrides.set(key, normalized);
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
throw new Error(`Unsupported type ${JSON.stringify(type)} for column ${JSON.stringify(key)}.`);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
21
37
|
const firstNonNullValue = keys.map((key) => rows.find((obj) => obj[key] !== null && obj[key] !== undefined)?.[key]);
|
|
22
38
|
const types = [];
|
|
23
39
|
const columnsData = keys.map(() => new Array(rows.length));
|
|
24
40
|
for (let i = 0; i < keys.length; i++) {
|
|
25
41
|
const key = keys[i];
|
|
26
42
|
const columnData = columnsData[i];
|
|
43
|
+
const override = overrides.get(key);
|
|
44
|
+
if (override !== undefined) {
|
|
45
|
+
types[i] = override;
|
|
46
|
+
for (let j = 0; j < rows.length; j++) {
|
|
47
|
+
columnData[j] = prepareTypedValue(rows[j][key], override, key, j + 1);
|
|
48
|
+
}
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
27
51
|
const value = firstNonNullValue[i];
|
|
28
52
|
const type = typeof value;
|
|
29
53
|
if (type === "symbol" || type === "function") {
|
|
@@ -96,3 +120,88 @@ export async function executePreparedArray(simpleTable, prepared) {
|
|
|
96
120
|
}
|
|
97
121
|
appender.flushSync();
|
|
98
122
|
}
|
|
123
|
+
/** Validates and snapshots a value for an explicitly declared destination type. */
|
|
124
|
+
function prepareTypedValue(value, type, column, row) {
|
|
125
|
+
if (value === null || value === undefined || Number.isNaN(value))
|
|
126
|
+
return null;
|
|
127
|
+
let compatible = false;
|
|
128
|
+
if (type === "VARCHAR" && typeof value === "string")
|
|
129
|
+
return value;
|
|
130
|
+
if (type === "BOOLEAN" && typeof value === "boolean")
|
|
131
|
+
return value;
|
|
132
|
+
if (type === "DOUBLE") {
|
|
133
|
+
if (typeof value === "number")
|
|
134
|
+
return value;
|
|
135
|
+
compatible = typeof value === "bigint";
|
|
136
|
+
if (typeof value === "bigint") {
|
|
137
|
+
const number = Number(value);
|
|
138
|
+
if (Number.isFinite(number) && BigInt(number) === value)
|
|
139
|
+
return number;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
else if (type === "INTEGER") {
|
|
143
|
+
compatible = typeof value === "number" || typeof value === "bigint";
|
|
144
|
+
if (typeof value === "number") {
|
|
145
|
+
if (Number.isInteger(value) && value >= -2147483648 && value <= 2147483647) {
|
|
146
|
+
return value;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
else if (typeof value === "bigint" && value >= -2147483648n && value <= 2147483647n) {
|
|
150
|
+
return Number(value);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
else if (type === "BIGINT") {
|
|
154
|
+
compatible = typeof value === "number" || typeof value === "bigint";
|
|
155
|
+
if (typeof value === "bigint") {
|
|
156
|
+
if (value >= -9223372036854775808n && value <= 9223372036854775807n) {
|
|
157
|
+
return value;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
else if (typeof value === "number" && Number.isInteger(value) &&
|
|
161
|
+
value >= -(2 ** 63) && value < 2 ** 63) {
|
|
162
|
+
// The upper bound is exclusive: 2 ** 63 - 1 rounds up as a JS number.
|
|
163
|
+
return BigInt(value);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
else if (["DATE", "TIME", "TIMESTAMP", "TIMESTAMP WITH TIME ZONE"].includes(type)) {
|
|
167
|
+
if (type === "TIME" && value instanceof DuckDBTimeValue) {
|
|
168
|
+
if (value.micros >= 0n && value.micros <= 86400000000n) {
|
|
169
|
+
return new DuckDBTimeValue(value.micros);
|
|
170
|
+
}
|
|
171
|
+
compatible = true;
|
|
172
|
+
}
|
|
173
|
+
else if (value instanceof Date) {
|
|
174
|
+
const millis = value.getTime();
|
|
175
|
+
compatible = Number.isFinite(millis);
|
|
176
|
+
if (compatible) {
|
|
177
|
+
if (type === "DATE" && millis % 86400000 === 0) {
|
|
178
|
+
return new DuckDBDateValue(millis / 86400000);
|
|
179
|
+
}
|
|
180
|
+
const micros = BigInt(millis) * 1000n;
|
|
181
|
+
if (type === "TIMESTAMP")
|
|
182
|
+
return new DuckDBTimestampValue(micros);
|
|
183
|
+
if (type === "TIMESTAMP WITH TIME ZONE") {
|
|
184
|
+
return new DuckDBTimestampTZValue(micros);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
else if (type.startsWith("FLOAT[") && Array.isArray(value)) {
|
|
190
|
+
compatible = true;
|
|
191
|
+
const size = Number(type.slice(6, -1));
|
|
192
|
+
if (value.length === size &&
|
|
193
|
+
value.every((item) => item === null || item === undefined ||
|
|
194
|
+
(typeof item === "number" &&
|
|
195
|
+
(Number.isNaN(item) || Math.fround(item) === item)))) {
|
|
196
|
+
return arrayValue(value.map((item) => item === undefined || Number.isNaN(item)
|
|
197
|
+
? null
|
|
198
|
+
: item));
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
const displayed = typeof value === "string"
|
|
202
|
+
? JSON.stringify(value)
|
|
203
|
+
: String(value);
|
|
204
|
+
throw new Error(`Column ${JSON.stringify(column)}, row ${row}: value ${displayed} ${compatible
|
|
205
|
+
? `cannot be stored as ${type} without losing information`
|
|
206
|
+
: `is incompatible with ${type}`}. Select a type compatible with this value.`);
|
|
207
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type SimpleTable from "../class/SimpleTable.js";
|
|
2
|
+
declare const INTERVAL_SECONDS: {
|
|
3
|
+
readonly "1d": number;
|
|
4
|
+
readonly "1h": number;
|
|
5
|
+
readonly "1m": 60;
|
|
6
|
+
};
|
|
7
|
+
type YahooInterval = keyof typeof INTERVAL_SECONDS;
|
|
8
|
+
export default function loadYahooFinanceData(table: SimpleTable, symbol: string, startDate: Date, endDate: Date, interval: YahooInterval): void;
|
|
9
|
+
export {};
|
|
10
|
+
//# sourceMappingURL=loadYahooFinanceData.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loadYahooFinanceData.d.ts","sourceRoot":"","sources":["../../src/methods/loadYahooFinanceData.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,WAAW,MAAM,yBAAyB,CAAC;AAKvD,QAAA,MAAM,gBAAgB;;;;CAIZ,CAAC;AAeX,KAAK,aAAa,GAAG,MAAM,OAAO,gBAAgB,CAAC;AA6BnD,MAAM,CAAC,OAAO,UAAU,oBAAoB,CAC1C,KAAK,EAAE,WAAW,EAClB,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,IAAI,EACf,OAAO,EAAE,IAAI,EACb,QAAQ,EAAE,aAAa,GACtB,IAAI,CAeN"}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import SDAError from "../class/SDAError.js";
|
|
2
|
+
import queueOp from "../helpers/queueOp.js";
|
|
3
|
+
import { executePreparedArray, prepareArray } from "./loadArray.js";
|
|
4
|
+
const INTERVAL_SECONDS = {
|
|
5
|
+
"1d": 24 * 60 * 60,
|
|
6
|
+
"1h": 60 * 60,
|
|
7
|
+
"1m": 60,
|
|
8
|
+
};
|
|
9
|
+
const COLUMN_TYPES = {
|
|
10
|
+
datetime: "TIMESTAMP",
|
|
11
|
+
open: "DOUBLE",
|
|
12
|
+
high: "DOUBLE",
|
|
13
|
+
low: "DOUBLE",
|
|
14
|
+
close: "DOUBLE",
|
|
15
|
+
adjustedClose: "DOUBLE",
|
|
16
|
+
volume: "DOUBLE",
|
|
17
|
+
};
|
|
18
|
+
const USER_AGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36";
|
|
19
|
+
export default function loadYahooFinanceData(table, symbol, startDate, endDate, interval) {
|
|
20
|
+
assertArguments(symbol, startDate, endDate, interval);
|
|
21
|
+
const request = {
|
|
22
|
+
symbol,
|
|
23
|
+
startDate: new Date(startDate),
|
|
24
|
+
endDate: new Date(endDate),
|
|
25
|
+
interval,
|
|
26
|
+
};
|
|
27
|
+
queueOp(table, {
|
|
28
|
+
kind: "barrier",
|
|
29
|
+
method: "loadYahooFinanceData()",
|
|
30
|
+
parameters: request,
|
|
31
|
+
execute: () => executeLoadYahooFinanceData(table, request),
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
async function executeLoadYahooFinanceData(table, request) {
|
|
35
|
+
try {
|
|
36
|
+
const rows = await getYahooFinanceData(request);
|
|
37
|
+
await executePreparedArray(table, prepareArray(rows, COLUMN_TYPES));
|
|
38
|
+
}
|
|
39
|
+
catch (error) {
|
|
40
|
+
if (error instanceof SDAError) {
|
|
41
|
+
throw error;
|
|
42
|
+
}
|
|
43
|
+
throw new SDAError({
|
|
44
|
+
method: "loadYahooFinanceData()",
|
|
45
|
+
parameters: request,
|
|
46
|
+
query: "",
|
|
47
|
+
cause: error,
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
async function getYahooFinanceData(request) {
|
|
52
|
+
const { symbol, startDate, endDate, interval } = request;
|
|
53
|
+
const startTime = startDate.getTime();
|
|
54
|
+
const exclusiveEndTime = getExclusiveEndTime(endDate, interval);
|
|
55
|
+
const url = new URL(`https://query1.finance.yahoo.com/v8/finance/chart/${encodeURIComponent(symbol)}`);
|
|
56
|
+
url.search = new URLSearchParams({
|
|
57
|
+
includeAdjustedClose: "true",
|
|
58
|
+
interval,
|
|
59
|
+
period1: String(Math.floor(startTime / 1000)),
|
|
60
|
+
period2: String(Math.ceil(exclusiveEndTime / 1000)),
|
|
61
|
+
}).toString();
|
|
62
|
+
const response = await fetch(url, {
|
|
63
|
+
headers: { "User-Agent": USER_AGENT },
|
|
64
|
+
});
|
|
65
|
+
if (!response.ok) {
|
|
66
|
+
const text = (await response.text()).slice(0, 500).trim();
|
|
67
|
+
throw new Error(`Failed to fetch Yahoo Finance data: ${response.status} ${response.statusText}${text.length > 0 ? `. ${text}` : ""}. Yahoo may have changed, rate-limited, or disabled this undocumented endpoint.`);
|
|
68
|
+
}
|
|
69
|
+
const data = await response.json();
|
|
70
|
+
if (data.chart?.error) {
|
|
71
|
+
throw new Error(data.chart.error.description ??
|
|
72
|
+
"Yahoo Finance returned an unknown error.");
|
|
73
|
+
}
|
|
74
|
+
const result = data.chart?.result?.[0];
|
|
75
|
+
const timestamps = result?.timestamp;
|
|
76
|
+
if (!result || !timestamps?.length) {
|
|
77
|
+
throw new Error("No Yahoo Finance data found.");
|
|
78
|
+
}
|
|
79
|
+
const quote = result.indicators?.quote?.[0];
|
|
80
|
+
const adjustedClose = result.indicators?.adjclose?.[0]?.adjclose;
|
|
81
|
+
const rows = [];
|
|
82
|
+
for (let index = 0; index < timestamps.length; index++) {
|
|
83
|
+
const timestamp = timestamps[index] * 1000;
|
|
84
|
+
if (Number.isFinite(timestamp) && timestamp >= startTime &&
|
|
85
|
+
timestamp < exclusiveEndTime) {
|
|
86
|
+
rows.push({
|
|
87
|
+
datetime: new Date(timestamp),
|
|
88
|
+
open: getFiniteValue(quote?.open, index),
|
|
89
|
+
high: getFiniteValue(quote?.high, index),
|
|
90
|
+
low: getFiniteValue(quote?.low, index),
|
|
91
|
+
close: getFiniteValue(quote?.close, index),
|
|
92
|
+
adjustedClose: getFiniteValue(adjustedClose, index),
|
|
93
|
+
volume: getFiniteValue(quote?.volume, index),
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
if (rows.length === 0) {
|
|
98
|
+
throw new Error(`No Yahoo Finance data found for ${symbol}.`);
|
|
99
|
+
}
|
|
100
|
+
return rows;
|
|
101
|
+
}
|
|
102
|
+
function getFiniteValue(values, index) {
|
|
103
|
+
const value = values?.[index];
|
|
104
|
+
return typeof value === "number" && Number.isFinite(value) ? value : null;
|
|
105
|
+
}
|
|
106
|
+
function getExclusiveEndTime(endDate, interval) {
|
|
107
|
+
const end = new Date(endDate);
|
|
108
|
+
if (interval === "1d") {
|
|
109
|
+
end.setUTCHours(0, 0, 0, 0);
|
|
110
|
+
}
|
|
111
|
+
else if (interval === "1h") {
|
|
112
|
+
end.setUTCMinutes(0, 0, 0);
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
end.setUTCSeconds(0, 0);
|
|
116
|
+
}
|
|
117
|
+
return end.getTime() + INTERVAL_SECONDS[interval] * 1000;
|
|
118
|
+
}
|
|
119
|
+
function assertArguments(symbol, startDate, endDate, interval) {
|
|
120
|
+
if (typeof symbol !== "string" || symbol.trim().length === 0) {
|
|
121
|
+
throw new TypeError("loadYahooFinanceData() symbol must be a non-empty string.");
|
|
122
|
+
}
|
|
123
|
+
if (!(startDate instanceof Date) || !(endDate instanceof Date) ||
|
|
124
|
+
!Number.isFinite(startDate.getTime()) || !Number.isFinite(endDate.getTime())) {
|
|
125
|
+
throw new RangeError("loadYahooFinanceData() startDate and endDate must be valid dates.");
|
|
126
|
+
}
|
|
127
|
+
if (endDate.getTime() < startDate.getTime()) {
|
|
128
|
+
throw new RangeError("loadYahooFinanceData() endDate must be equal to or later than startDate.");
|
|
129
|
+
}
|
|
130
|
+
if (interval !== "1d" && interval !== "1h" && interval !== "1m") {
|
|
131
|
+
throw new Error('loadYahooFinanceData() interval must be "1d", "1h", or "1m".');
|
|
132
|
+
}
|
|
133
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type SimpleTable from "../class/SimpleTable.js";
|
|
2
2
|
export default function rowProportions(simpleTable: SimpleTable, columns: string[], options?: {
|
|
3
3
|
suffix?: string;
|
|
4
|
+
base?: number;
|
|
4
5
|
decimals?: number;
|
|
5
6
|
}): void;
|
|
6
7
|
//# sourceMappingURL=rowProportions.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rowProportions.d.ts","sourceRoot":"","sources":["../../src/methods/rowProportions.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,WAAW,MAAM,yBAAyB,CAAC;AAEvD,MAAM,CAAC,OAAO,UAAU,cAAc,CACpC,WAAW,EAAE,WAAW,EACxB,OAAO,EAAE,MAAM,EAAE,EACjB,OAAO,GAAE;IACP,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACd,
|
|
1
|
+
{"version":3,"file":"rowProportions.d.ts","sourceRoot":"","sources":["../../src/methods/rowProportions.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,WAAW,MAAM,yBAAyB,CAAC;AAEvD,MAAM,CAAC,OAAO,UAAU,cAAc,CACpC,WAAW,EAAE,WAAW,EACxB,OAAO,EAAE,MAAM,EAAE,EACjB,OAAO,GAAE;IACP,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;CACd,QA4CP"}
|
|
@@ -2,6 +2,10 @@ import quoteIdentifier from "../helpers/quoteIdentifier.js";
|
|
|
2
2
|
import assertNewColumns from "../helpers/assertNewColumns.js";
|
|
3
3
|
import queueOp from "../helpers/queueOp.js";
|
|
4
4
|
export default function rowProportions(simpleTable, columns, options = {}) {
|
|
5
|
+
if (options.base !== undefined &&
|
|
6
|
+
(!Number.isFinite(options.base) || options.base <= 0)) {
|
|
7
|
+
throw new Error("rowProportions() options.base must be a finite number greater than 0.");
|
|
8
|
+
}
|
|
5
9
|
columns = [...columns];
|
|
6
10
|
options = structuredClone(options);
|
|
7
11
|
queueOp(simpleTable, {
|
|
@@ -14,7 +18,7 @@ export default function rowProportions(simpleTable, columns, options = {}) {
|
|
|
14
18
|
assertNewColumns(schema, columns.map((col) => `${col}${suffix}`), "rowProportions()");
|
|
15
19
|
let query = `SELECT *,`;
|
|
16
20
|
for (const col of columns) {
|
|
17
|
-
const tempQuery = `${quoteIdentifier(col)} / (${columns.map((d) => `${quoteIdentifier(d)}`).join(" + ")})`;
|
|
21
|
+
const tempQuery = `${quoteIdentifier(col)} / (${columns.map((d) => `${quoteIdentifier(d)}`).join(" + ")}) * ${options.base ?? 1}`;
|
|
18
22
|
if (typeof options.decimals === "number") {
|
|
19
23
|
query += ` ROUND(${tempQuery}, ${options.decimals})`;
|
|
20
24
|
}
|