tradeblocks-mcp 1.2.1 → 1.3.0-beta.2
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/test-exports.js +222 -74
- package/dist/test-exports.js.map +1 -1
- package/package.json +2 -1
- package/server/index.js +224 -76
- package/server/index.js.map +1 -1
package/dist/test-exports.js
CHANGED
|
@@ -20348,6 +20348,138 @@ var REPORTING_TRADE_COLUMN_ALIASES = {
|
|
|
20348
20348
|
"PL": "P/L"
|
|
20349
20349
|
};
|
|
20350
20350
|
|
|
20351
|
+
// ../lib/processing/tat-adapter.ts
|
|
20352
|
+
var TAT_SIGNATURE_HEADERS = ["tradeid", "profitloss", "buyingpower"];
|
|
20353
|
+
function isTatFormat(headers) {
|
|
20354
|
+
const lower = headers.map((h) => h.toLowerCase().trim());
|
|
20355
|
+
return TAT_SIGNATURE_HEADERS.every((sig) => lower.includes(sig));
|
|
20356
|
+
}
|
|
20357
|
+
function parseTatDate(dateStr) {
|
|
20358
|
+
if (!dateStr || dateStr.trim() === "") return null;
|
|
20359
|
+
const isoMatch = dateStr.match(/^(\d{4})-(\d{2})-(\d{2})/);
|
|
20360
|
+
if (isoMatch) {
|
|
20361
|
+
const [, year, month, day] = isoMatch;
|
|
20362
|
+
return new Date(parseInt(year), parseInt(month) - 1, parseInt(day));
|
|
20363
|
+
}
|
|
20364
|
+
const usMatch = dateStr.match(/^(\d{1,2})\/(\d{1,2})\/(\d{4})/);
|
|
20365
|
+
if (usMatch) {
|
|
20366
|
+
const [, month, day, year] = usMatch;
|
|
20367
|
+
return new Date(parseInt(year), parseInt(month) - 1, parseInt(day));
|
|
20368
|
+
}
|
|
20369
|
+
return null;
|
|
20370
|
+
}
|
|
20371
|
+
function formatTatTime(timeStr) {
|
|
20372
|
+
if (!timeStr || timeStr.trim() === "") return void 0;
|
|
20373
|
+
if (/[AP]M$/i.test(timeStr.trim())) return timeStr.trim();
|
|
20374
|
+
const match = timeStr.match(/^(\d{1,2}):(\d{2})/);
|
|
20375
|
+
if (!match) return void 0;
|
|
20376
|
+
const hours = parseInt(match[1], 10);
|
|
20377
|
+
const minutes = match[2];
|
|
20378
|
+
const period = hours >= 12 ? "PM" : "AM";
|
|
20379
|
+
const displayHours = hours % 12 || 12;
|
|
20380
|
+
return `${displayHours}:${minutes} ${period}`;
|
|
20381
|
+
}
|
|
20382
|
+
function buildTatLegsString(row) {
|
|
20383
|
+
const symbol = (row.UnderlyingSymbol || "").trim();
|
|
20384
|
+
const tradeType = (row.TradeType || "").trim();
|
|
20385
|
+
const shortPut = (row.ShortPut || "").trim();
|
|
20386
|
+
const shortCall = (row.ShortCall || "").trim();
|
|
20387
|
+
const longPut = (row.LongPut || "").trim();
|
|
20388
|
+
const longCall = (row.LongCall || "").trim();
|
|
20389
|
+
const isPresent = (v) => v !== "" && v !== "0";
|
|
20390
|
+
const shortParts = [];
|
|
20391
|
+
if (isPresent(shortPut)) shortParts.push(`${shortPut}P`);
|
|
20392
|
+
if (isPresent(shortCall)) shortParts.push(`${shortCall}C`);
|
|
20393
|
+
const shortLeg = shortParts.join("/");
|
|
20394
|
+
const longParts = [];
|
|
20395
|
+
if (isPresent(longPut)) longParts.push(`${longPut}P`);
|
|
20396
|
+
if (isPresent(longCall)) longParts.push(`${longCall}C`);
|
|
20397
|
+
const longLeg = longParts.join("/");
|
|
20398
|
+
const prefix = symbol ? `${symbol} ` : "";
|
|
20399
|
+
const suffix = tradeType ? ` ${tradeType}` : "";
|
|
20400
|
+
if (shortLeg && longLeg) {
|
|
20401
|
+
return `${prefix}${shortLeg} | ${longLeg}${suffix}`;
|
|
20402
|
+
}
|
|
20403
|
+
if (shortLeg) return `${prefix}${shortLeg}${suffix}`;
|
|
20404
|
+
if (longLeg) return `${prefix}${longLeg}${suffix}`;
|
|
20405
|
+
return tradeType || "Unknown";
|
|
20406
|
+
}
|
|
20407
|
+
function parseNumber(value, defaultValue) {
|
|
20408
|
+
if (!value || value.trim() === "" || value.toLowerCase() === "nan") {
|
|
20409
|
+
return defaultValue ?? 0;
|
|
20410
|
+
}
|
|
20411
|
+
const cleaned = value.replace(/[$,%]/g, "").trim();
|
|
20412
|
+
const parsed = parseFloat(cleaned);
|
|
20413
|
+
return isNaN(parsed) ? defaultValue ?? 0 : parsed;
|
|
20414
|
+
}
|
|
20415
|
+
function normalizeRowKeys(row) {
|
|
20416
|
+
const keyMap = {};
|
|
20417
|
+
for (const key of Object.keys(row)) {
|
|
20418
|
+
keyMap[key.toLowerCase()] = key;
|
|
20419
|
+
}
|
|
20420
|
+
const canonicalKeys = [
|
|
20421
|
+
"OpenDate",
|
|
20422
|
+
"Date",
|
|
20423
|
+
"CloseDate",
|
|
20424
|
+
"OpenTime",
|
|
20425
|
+
"CloseTime",
|
|
20426
|
+
"TimeOpened",
|
|
20427
|
+
"TimeClosed",
|
|
20428
|
+
"ProfitLoss",
|
|
20429
|
+
"PriceOpen",
|
|
20430
|
+
"PriceClose",
|
|
20431
|
+
"TotalPremium",
|
|
20432
|
+
"Qty",
|
|
20433
|
+
"Strategy",
|
|
20434
|
+
"Template",
|
|
20435
|
+
"Status",
|
|
20436
|
+
"UnderlyingSymbol",
|
|
20437
|
+
"TradeType",
|
|
20438
|
+
"ShortPut",
|
|
20439
|
+
"ShortCall",
|
|
20440
|
+
"LongPut",
|
|
20441
|
+
"LongCall"
|
|
20442
|
+
];
|
|
20443
|
+
const normalized = { ...row };
|
|
20444
|
+
for (const canonical of canonicalKeys) {
|
|
20445
|
+
if (!(canonical in normalized)) {
|
|
20446
|
+
const actual = keyMap[canonical.toLowerCase()];
|
|
20447
|
+
if (actual) normalized[canonical] = row[actual];
|
|
20448
|
+
}
|
|
20449
|
+
}
|
|
20450
|
+
return normalized;
|
|
20451
|
+
}
|
|
20452
|
+
function convertTatRowToReportingTrade(row) {
|
|
20453
|
+
row = normalizeRowKeys(row);
|
|
20454
|
+
const dateOpened = parseTatDate(row.OpenDate) ?? parseTatDate(row.Date);
|
|
20455
|
+
if (!dateOpened || isNaN(dateOpened.getTime())) return null;
|
|
20456
|
+
const plStr = (row.ProfitLoss || "").trim();
|
|
20457
|
+
if (!plStr) return null;
|
|
20458
|
+
const dateClosed = parseTatDate(row.CloseDate) ?? void 0;
|
|
20459
|
+
const timeOpened = formatTatTime(row.OpenTime) ?? formatTatTime(row.TimeOpened);
|
|
20460
|
+
const timeClosed = formatTatTime(row.CloseTime) ?? formatTatTime(row.TimeClosed);
|
|
20461
|
+
const legs = buildTatLegsString(row);
|
|
20462
|
+
const qty = parseNumber(row.Qty, 1);
|
|
20463
|
+
return {
|
|
20464
|
+
// Template = strategy name (matches OO's Strategy); Strategy = user-defined grouping
|
|
20465
|
+
strategy: (row.Template || row.Strategy || "").trim() || "Unknown",
|
|
20466
|
+
dateOpened,
|
|
20467
|
+
timeOpened,
|
|
20468
|
+
openingPrice: 0,
|
|
20469
|
+
// OO reports underlying price level; TAT does not provide this
|
|
20470
|
+
legs,
|
|
20471
|
+
initialPremium: qty !== 0 ? parseNumber(row.TotalPremium) / qty : parseNumber(row.TotalPremium),
|
|
20472
|
+
// Per-spread premium (matches OO semantics)
|
|
20473
|
+
numContracts: qty,
|
|
20474
|
+
// Qty = spreads (matches OO semantics)
|
|
20475
|
+
pl: parseNumber(row.ProfitLoss),
|
|
20476
|
+
closingPrice: row.PriceClose ? parseNumber(row.PriceClose) : void 0,
|
|
20477
|
+
dateClosed,
|
|
20478
|
+
timeClosed,
|
|
20479
|
+
reasonForClose: (row.Status || "").trim() || void 0
|
|
20480
|
+
};
|
|
20481
|
+
}
|
|
20482
|
+
|
|
20351
20483
|
// ../lib/utils/trade-frequency.ts
|
|
20352
20484
|
var MS_PER_DAY = 1e3 * 60 * 60 * 24;
|
|
20353
20485
|
|
|
@@ -20360,7 +20492,7 @@ function parseDatePreservingCalendarDay(dateStr) {
|
|
|
20360
20492
|
}
|
|
20361
20493
|
return new Date(dateStr);
|
|
20362
20494
|
}
|
|
20363
|
-
function
|
|
20495
|
+
function parseNumber2(value, defaultValue) {
|
|
20364
20496
|
if (!value || value.trim() === "" || value.toLowerCase() === "nan") {
|
|
20365
20497
|
if (defaultValue !== void 0) return defaultValue;
|
|
20366
20498
|
return 0;
|
|
@@ -20479,6 +20611,11 @@ async function detectCsvType(filePath) {
|
|
|
20479
20611
|
if (hasSimpleDate && hasValue && matchedTradeColumns.length < 2) {
|
|
20480
20612
|
return "dailylog";
|
|
20481
20613
|
}
|
|
20614
|
+
const tatSignature = ["tradeid", "profitloss", "buyingpower"];
|
|
20615
|
+
const isTat = tatSignature.every((sig) => headers.includes(sig));
|
|
20616
|
+
if (isTat) {
|
|
20617
|
+
return "reportinglog";
|
|
20618
|
+
}
|
|
20482
20619
|
const reportingAliases = Object.keys(REPORTING_TRADE_COLUMN_ALIASES).map(
|
|
20483
20620
|
(k) => k.toLowerCase()
|
|
20484
20621
|
);
|
|
@@ -20609,36 +20746,36 @@ function convertToTrade(raw) {
|
|
|
20609
20746
|
const trade = {
|
|
20610
20747
|
dateOpened,
|
|
20611
20748
|
timeOpened: raw["Time Opened"] || "00:00:00",
|
|
20612
|
-
openingPrice:
|
|
20749
|
+
openingPrice: parseNumber2(raw["Opening Price"]),
|
|
20613
20750
|
legs,
|
|
20614
|
-
premium:
|
|
20751
|
+
premium: parseNumber2(raw["Premium"]),
|
|
20615
20752
|
premiumPrecision,
|
|
20616
|
-
closingPrice: raw["Closing Price"] ?
|
|
20753
|
+
closingPrice: raw["Closing Price"] ? parseNumber2(raw["Closing Price"]) : void 0,
|
|
20617
20754
|
dateClosed,
|
|
20618
20755
|
timeClosed: raw["Time Closed"] || void 0,
|
|
20619
|
-
avgClosingCost: raw["Avg. Closing Cost"] ?
|
|
20756
|
+
avgClosingCost: raw["Avg. Closing Cost"] ? parseNumber2(raw["Avg. Closing Cost"]) : void 0,
|
|
20620
20757
|
reasonForClose: raw["Reason For Close"] || void 0,
|
|
20621
|
-
pl:
|
|
20622
|
-
numContracts: Math.round(
|
|
20623
|
-
fundsAtClose:
|
|
20624
|
-
marginReq:
|
|
20758
|
+
pl: parseNumber2(raw["P/L"]),
|
|
20759
|
+
numContracts: Math.round(parseNumber2(raw["No. of Contracts"], 1)),
|
|
20760
|
+
fundsAtClose: parseNumber2(raw["Funds at Close"]),
|
|
20761
|
+
marginReq: parseNumber2(raw["Margin Req."]),
|
|
20625
20762
|
strategy,
|
|
20626
|
-
openingCommissionsFees:
|
|
20763
|
+
openingCommissionsFees: parseNumber2(
|
|
20627
20764
|
raw["Opening Commissions + Fees"] || raw["Opening comms & fees"],
|
|
20628
20765
|
0
|
|
20629
20766
|
),
|
|
20630
|
-
closingCommissionsFees:
|
|
20767
|
+
closingCommissionsFees: parseNumber2(
|
|
20631
20768
|
raw["Closing Commissions + Fees"] || raw["Closing comms & fees"],
|
|
20632
20769
|
0
|
|
20633
20770
|
),
|
|
20634
|
-
openingShortLongRatio:
|
|
20635
|
-
closingShortLongRatio: raw["Closing Short/Long Ratio"] ?
|
|
20636
|
-
openingVix: raw["Opening VIX"] ?
|
|
20637
|
-
closingVix: raw["Closing VIX"] ?
|
|
20638
|
-
gap: raw["Gap"] ?
|
|
20639
|
-
movement: raw["Movement"] ?
|
|
20640
|
-
maxProfit: raw["Max Profit"] ?
|
|
20641
|
-
maxLoss: raw["Max Loss"] ?
|
|
20771
|
+
openingShortLongRatio: parseNumber2(raw["Opening Short/Long Ratio"], 0),
|
|
20772
|
+
closingShortLongRatio: raw["Closing Short/Long Ratio"] ? parseNumber2(raw["Closing Short/Long Ratio"]) : void 0,
|
|
20773
|
+
openingVix: raw["Opening VIX"] ? parseNumber2(raw["Opening VIX"]) : void 0,
|
|
20774
|
+
closingVix: raw["Closing VIX"] ? parseNumber2(raw["Closing VIX"]) : void 0,
|
|
20775
|
+
gap: raw["Gap"] ? parseNumber2(raw["Gap"]) : void 0,
|
|
20776
|
+
movement: raw["Movement"] ? parseNumber2(raw["Movement"]) : void 0,
|
|
20777
|
+
maxProfit: raw["Max Profit"] ? parseNumber2(raw["Max Profit"]) : void 0,
|
|
20778
|
+
maxLoss: raw["Max Loss"] ? parseNumber2(raw["Max Loss"]) : void 0
|
|
20642
20779
|
};
|
|
20643
20780
|
const customFields = {};
|
|
20644
20781
|
for (const [key, value] of Object.entries(raw)) {
|
|
@@ -20662,13 +20799,13 @@ function convertToDailyLogEntry(raw, blockId) {
|
|
|
20662
20799
|
if (isNaN(date.getTime())) return null;
|
|
20663
20800
|
return {
|
|
20664
20801
|
date,
|
|
20665
|
-
netLiquidity:
|
|
20666
|
-
currentFunds:
|
|
20667
|
-
withdrawn:
|
|
20668
|
-
tradingFunds:
|
|
20669
|
-
dailyPl:
|
|
20670
|
-
dailyPlPct:
|
|
20671
|
-
drawdownPct:
|
|
20802
|
+
netLiquidity: parseNumber2(raw["Net Liquidity"]),
|
|
20803
|
+
currentFunds: parseNumber2(raw["Current Funds"]),
|
|
20804
|
+
withdrawn: parseNumber2(raw["Withdrawn"], 0),
|
|
20805
|
+
tradingFunds: parseNumber2(raw["Trading Funds"]),
|
|
20806
|
+
dailyPl: parseNumber2(raw["P/L"]),
|
|
20807
|
+
dailyPlPct: parseNumber2(raw["P/L %"]),
|
|
20808
|
+
drawdownPct: parseNumber2(raw["Drawdown %"]),
|
|
20672
20809
|
blockId
|
|
20673
20810
|
};
|
|
20674
20811
|
} catch {
|
|
@@ -20935,6 +21072,10 @@ function normalizeRecordHeaders(raw) {
|
|
|
20935
21072
|
return normalized;
|
|
20936
21073
|
}
|
|
20937
21074
|
function convertToReportingTrade(raw) {
|
|
21075
|
+
const keys = Object.keys(raw);
|
|
21076
|
+
if (isTatFormat(keys)) {
|
|
21077
|
+
return convertTatRowToReportingTrade(raw);
|
|
21078
|
+
}
|
|
20938
21079
|
try {
|
|
20939
21080
|
const normalized = normalizeRecordHeaders(raw);
|
|
20940
21081
|
const dateOpened = parseDatePreservingCalendarDay(normalized["Date Opened"]);
|
|
@@ -20945,15 +21086,15 @@ function convertToReportingTrade(raw) {
|
|
|
20945
21086
|
strategy,
|
|
20946
21087
|
dateOpened,
|
|
20947
21088
|
timeOpened: normalized["Time Opened"] || void 0,
|
|
20948
|
-
openingPrice:
|
|
21089
|
+
openingPrice: parseNumber2(normalized["Opening Price"]),
|
|
20949
21090
|
legs: normalized["Legs"] || "",
|
|
20950
|
-
initialPremium:
|
|
20951
|
-
numContracts:
|
|
20952
|
-
pl:
|
|
20953
|
-
closingPrice: normalized["Closing Price"] ?
|
|
21091
|
+
initialPremium: parseNumber2(normalized["Initial Premium"]),
|
|
21092
|
+
numContracts: parseNumber2(normalized["No. of Contracts"], 1),
|
|
21093
|
+
pl: parseNumber2(normalized["P/L"]),
|
|
21094
|
+
closingPrice: normalized["Closing Price"] ? parseNumber2(normalized["Closing Price"]) : void 0,
|
|
20954
21095
|
dateClosed,
|
|
20955
21096
|
timeClosed: normalized["Time Closed"] || void 0,
|
|
20956
|
-
avgClosingCost: normalized["Avg. Closing Cost"] ?
|
|
21097
|
+
avgClosingCost: normalized["Avg. Closing Cost"] ? parseNumber2(normalized["Avg. Closing Cost"]) : void 0,
|
|
20957
21098
|
reasonForClose: normalized["Reason For Close"] || void 0
|
|
20958
21099
|
};
|
|
20959
21100
|
} catch {
|
|
@@ -21173,6 +21314,9 @@ function validateCsvColumns(records, csvType) {
|
|
|
21173
21314
|
break;
|
|
21174
21315
|
}
|
|
21175
21316
|
case "reportinglog": {
|
|
21317
|
+
if (isTatFormat(headers)) {
|
|
21318
|
+
break;
|
|
21319
|
+
}
|
|
21176
21320
|
const dateOpenedAliases = ["Date Opened", "date_opened"];
|
|
21177
21321
|
const plAliases = ["P/L", "pl"];
|
|
21178
21322
|
const hasDateOpened = dateOpenedAliases.some(
|
|
@@ -21194,7 +21338,8 @@ function validateCsvColumns(records, csvType) {
|
|
|
21194
21338
|
return { valid: true };
|
|
21195
21339
|
}
|
|
21196
21340
|
async function importCsv(baseDir, options) {
|
|
21197
|
-
const { csvPath, blockName
|
|
21341
|
+
const { csvPath, blockName } = options;
|
|
21342
|
+
let { csvType = "tradelog" } = options;
|
|
21198
21343
|
try {
|
|
21199
21344
|
await fs.access(csvPath);
|
|
21200
21345
|
} catch {
|
|
@@ -21202,6 +21347,12 @@ async function importCsv(baseDir, options) {
|
|
|
21202
21347
|
}
|
|
21203
21348
|
const content = await fs.readFile(csvPath, "utf-8");
|
|
21204
21349
|
const records = parseCSV(content);
|
|
21350
|
+
if (csvType === "tradelog" && records.length > 0) {
|
|
21351
|
+
const headers = Object.keys(records[0]);
|
|
21352
|
+
if (isTatFormat(headers)) {
|
|
21353
|
+
csvType = "reportinglog";
|
|
21354
|
+
}
|
|
21355
|
+
}
|
|
21205
21356
|
const validation = validateCsvColumns(records, csvType);
|
|
21206
21357
|
if (!validation.valid) {
|
|
21207
21358
|
throw new Error(validation.error);
|
|
@@ -21283,6 +21434,7 @@ async function importCsv(baseDir, options) {
|
|
|
21283
21434
|
return {
|
|
21284
21435
|
blockId,
|
|
21285
21436
|
name: name79,
|
|
21437
|
+
csvType,
|
|
21286
21438
|
recordCount: records.length,
|
|
21287
21439
|
dateRange,
|
|
21288
21440
|
strategies,
|
|
@@ -21837,6 +21989,7 @@ var TICKER_FIELD_CANDIDATES = [
|
|
|
21837
21989
|
"underlying",
|
|
21838
21990
|
"Underlying",
|
|
21839
21991
|
"underlyingSymbol",
|
|
21992
|
+
"UnderlyingSymbol",
|
|
21840
21993
|
"Underlying Symbol"
|
|
21841
21994
|
];
|
|
21842
21995
|
function normalizeTicker(value) {
|
|
@@ -22063,58 +22216,44 @@ async function insertTradeBatch(conn, blockId, records, startIdx, batchSize) {
|
|
|
22063
22216
|
`;
|
|
22064
22217
|
await conn.run(sql, params);
|
|
22065
22218
|
}
|
|
22066
|
-
|
|
22067
|
-
|
|
22219
|
+
function formatDateForDb(date) {
|
|
22220
|
+
if (!date || isNaN(date.getTime())) return null;
|
|
22221
|
+
const year = date.getFullYear();
|
|
22222
|
+
const month = String(date.getMonth() + 1).padStart(2, "0");
|
|
22223
|
+
const day = String(date.getDate()).padStart(2, "0");
|
|
22224
|
+
return `${year}-${month}-${day}`;
|
|
22225
|
+
}
|
|
22226
|
+
async function insertReportingBatch(conn, blockId, trades, tickers, startIdx, batchSize) {
|
|
22227
|
+
const batch = trades.slice(startIdx, startIdx + batchSize);
|
|
22228
|
+
const batchTickers = tickers.slice(startIdx, startIdx + batchSize);
|
|
22068
22229
|
if (batch.length === 0) return;
|
|
22069
22230
|
const columnsPerRow = 15;
|
|
22070
22231
|
const placeholders = [];
|
|
22071
22232
|
const params = [];
|
|
22072
22233
|
for (let rowIdx = 0; rowIdx < batch.length; rowIdx++) {
|
|
22073
|
-
const
|
|
22234
|
+
const trade = batch[rowIdx];
|
|
22074
22235
|
const baseParam = rowIdx * columnsPerRow + 1;
|
|
22075
22236
|
const rowPlaceholders = Array.from(
|
|
22076
22237
|
{ length: columnsPerRow },
|
|
22077
22238
|
(_, i) => `$${baseParam + i}`
|
|
22078
22239
|
);
|
|
22079
22240
|
placeholders.push(`(${rowPlaceholders.join(", ")})`);
|
|
22080
|
-
const initialPremium = parseFloat(record["Initial Premium"]);
|
|
22081
|
-
const numContracts = parseInt(record["No. of Contracts"], 10);
|
|
22082
|
-
const pl = parseFloat(record["P/L"]);
|
|
22083
|
-
const closingPrice = parseFloat(record["Closing Price"]);
|
|
22084
|
-
const avgClosingCost = parseFloat(record["Avg. Closing Cost"]);
|
|
22085
|
-
const openingPrice = parseFloat(record["Opening Price"]);
|
|
22086
|
-
const ticker = resolveTickerFromCsvRow(record);
|
|
22087
22241
|
params.push(
|
|
22088
22242
|
blockId,
|
|
22089
|
-
|
|
22090
|
-
|
|
22091
|
-
|
|
22092
|
-
|
|
22093
|
-
|
|
22094
|
-
|
|
22095
|
-
|
|
22096
|
-
|
|
22097
|
-
|
|
22098
|
-
|
|
22099
|
-
|
|
22100
|
-
|
|
22101
|
-
|
|
22102
|
-
|
|
22103
|
-
// pl
|
|
22104
|
-
normalizeCsvDate(record["Date Closed"]),
|
|
22105
|
-
// date_closed
|
|
22106
|
-
record["Time Closed"] || null,
|
|
22107
|
-
// time_closed
|
|
22108
|
-
isNaN(closingPrice) ? null : closingPrice,
|
|
22109
|
-
// closing_price
|
|
22110
|
-
isNaN(avgClosingCost) ? null : avgClosingCost,
|
|
22111
|
-
// avg_closing_cost
|
|
22112
|
-
record["Reason For Close"] || null,
|
|
22113
|
-
// reason_for_close
|
|
22114
|
-
isNaN(openingPrice) ? null : openingPrice,
|
|
22115
|
-
// opening_price
|
|
22116
|
-
ticker
|
|
22117
|
-
// ticker
|
|
22243
|
+
formatDateForDb(trade.dateOpened),
|
|
22244
|
+
trade.timeOpened || null,
|
|
22245
|
+
trade.strategy || null,
|
|
22246
|
+
trade.legs || null,
|
|
22247
|
+
trade.initialPremium ?? null,
|
|
22248
|
+
trade.numContracts ?? 1,
|
|
22249
|
+
trade.pl ?? 0,
|
|
22250
|
+
formatDateForDb(trade.dateClosed),
|
|
22251
|
+
trade.timeClosed || null,
|
|
22252
|
+
trade.closingPrice ?? null,
|
|
22253
|
+
trade.avgClosingCost ?? null,
|
|
22254
|
+
trade.reasonForClose || null,
|
|
22255
|
+
trade.openingPrice ?? null,
|
|
22256
|
+
batchTickers[rowIdx]
|
|
22118
22257
|
);
|
|
22119
22258
|
}
|
|
22120
22259
|
const sql = `
|
|
@@ -22214,8 +22353,17 @@ async function syncBlockInternal(conn, blockId, blockPath) {
|
|
|
22214
22353
|
const reportingPath = path3.join(blockPath, optionalLogs.reportinglog);
|
|
22215
22354
|
const reportingContent = await fs3.readFile(reportingPath, "utf-8");
|
|
22216
22355
|
const reportingRecords = parseCSV2(reportingContent);
|
|
22217
|
-
|
|
22218
|
-
|
|
22356
|
+
const reportingTrades = [];
|
|
22357
|
+
const reportingTickers = [];
|
|
22358
|
+
for (const record of reportingRecords) {
|
|
22359
|
+
const trade = convertToReportingTrade(record);
|
|
22360
|
+
if (trade) {
|
|
22361
|
+
reportingTrades.push(trade);
|
|
22362
|
+
reportingTickers.push(resolveTickerFromCsvRow(record));
|
|
22363
|
+
}
|
|
22364
|
+
}
|
|
22365
|
+
for (let i = 0; i < reportingTrades.length; i += batchSize) {
|
|
22366
|
+
await insertReportingBatch(conn, blockId, reportingTrades, reportingTickers, i, batchSize);
|
|
22219
22367
|
}
|
|
22220
22368
|
}
|
|
22221
22369
|
const newMetadata = {
|