@adaptic/utils 0.0.926 → 0.0.927
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/index.cjs +43 -53
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +43 -53
- package/dist/index.mjs.map +1 -1
- package/dist/test.js +11 -14
- package/dist/test.js.map +1 -1
- package/dist/types/alpaca/client.d.ts.map +1 -1
- package/dist/types/alpaca/crypto/data.d.ts.map +1 -1
- package/dist/types/alpaca/crypto/orders.d.ts.map +1 -1
- package/dist/types/alpaca/index.d.ts.map +1 -1
- package/dist/types/alpaca/legacy/account.d.ts.map +1 -1
- package/dist/types/alpaca/legacy/positions.d.ts.map +1 -1
- package/dist/types/alpaca/market-data/bars.d.ts.map +1 -1
- package/dist/types/alpaca/market-data/news.d.ts.map +1 -1
- package/dist/types/alpaca/market-data/quotes.d.ts.map +1 -1
- package/dist/types/alpaca/market-data/trades.d.ts.map +1 -1
- package/dist/types/alpaca/options/data.d.ts +1 -1
- package/dist/types/alpaca/options/data.d.ts.map +1 -1
- package/dist/types/alpaca/options/orders.d.ts.map +1 -1
- package/dist/types/alpaca/streams/crypto-stream.d.ts.map +1 -1
- package/dist/types/alpaca/streams/option-stream.d.ts +2 -2
- package/dist/types/alpaca/streams/option-stream.d.ts.map +1 -1
- package/dist/types/alpaca/streams/stock-stream.d.ts.map +1 -1
- package/dist/types/alpaca/streams/stream-manager.d.ts.map +1 -1
- package/dist/types/alpaca/trading/smart-orders.d.ts.map +1 -1
- package/dist/types/alpaca-market-data-api.d.ts.map +1 -1
- package/dist/types/asset-allocation-algorithm.d.ts.map +1 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/market-time.d.ts.map +1 -1
- package/dist/types/massive.d.ts.map +1 -1
- package/dist/types/metrics-calcs.d.ts.map +1 -1
- package/dist/types/misc-utils.d.ts +2 -2
- package/dist/types/misc-utils.d.ts.map +1 -1
- package/dist/types/performance-metrics.d.ts.map +1 -1
- package/dist/types/price-utils.d.ts.map +1 -1
- package/dist/types/schemas/massive-schemas.d.ts +6 -6
- package/dist/types/utils/retry.d.ts +1 -10
- package/dist/types/utils/retry.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -783,13 +783,11 @@ let fs;
|
|
|
783
783
|
let path;
|
|
784
784
|
if (isNode) {
|
|
785
785
|
try {
|
|
786
|
-
/* eslint-disable @typescript-eslint/no-require-imports */
|
|
787
786
|
const readline = require("readline");
|
|
788
787
|
clearLine = readline.clearLine;
|
|
789
788
|
cursorTo = readline.cursorTo;
|
|
790
789
|
fs = require("fs");
|
|
791
790
|
path = require("path");
|
|
792
|
-
/* eslint-enable @typescript-eslint/no-require-imports */
|
|
793
791
|
}
|
|
794
792
|
catch {
|
|
795
793
|
// Silently degrade — all operations will be no-ops.
|
|
@@ -860,7 +858,7 @@ class DisplayManager {
|
|
|
860
858
|
/**
|
|
861
859
|
* Writes a log entry to a symbol-specific log file
|
|
862
860
|
*/
|
|
863
|
-
writeSymbolLog(symbol, date, logMessage,
|
|
861
|
+
writeSymbolLog(symbol, date, logMessage, _options) {
|
|
864
862
|
if (!fs || !path)
|
|
865
863
|
return;
|
|
866
864
|
try {
|
|
@@ -876,7 +874,7 @@ class DisplayManager {
|
|
|
876
874
|
const filename = `${symbol}-${year}-${month}-${day}.log`;
|
|
877
875
|
const filePath = path.join("logs", filename);
|
|
878
876
|
// Strip ANSI color codes from log message
|
|
879
|
-
const plainLogMessage = logMessage.replace(
|
|
877
|
+
const plainLogMessage = logMessage.replace(new RegExp(String.fromCharCode(27) + "\\[\\d+m", "g"), "");
|
|
880
878
|
// Write to file (append if exists, create if not)
|
|
881
879
|
fs.appendFileSync(filePath, plainLogMessage + "\n");
|
|
882
880
|
}
|
|
@@ -905,7 +903,7 @@ class DisplayManager {
|
|
|
905
903
|
const filename = `${source}-${year}-${month}-${day}.log`;
|
|
906
904
|
const filePath = path.join("logs", filename);
|
|
907
905
|
// Strip ANSI color codes from log message
|
|
908
|
-
const plainLogMessage = logMessage.replace(
|
|
906
|
+
const plainLogMessage = logMessage.replace(new RegExp(String.fromCharCode(27) + "\\[\\d+m", "g"), "");
|
|
909
907
|
// Write to file (append if exists, create if not)
|
|
910
908
|
fs.appendFileSync(filePath, plainLogMessage + "\n");
|
|
911
909
|
}
|
|
@@ -1461,7 +1459,7 @@ class MarketTimeUtil {
|
|
|
1461
1459
|
}
|
|
1462
1460
|
// In all other cases (during trading hours, before market open, holidays, weekends),
|
|
1463
1461
|
// we want the last completed trading day
|
|
1464
|
-
|
|
1462
|
+
const lastFullDate = this.getLastMarketDay(nowET);
|
|
1465
1463
|
// Set to midnight ET while preserving the date
|
|
1466
1464
|
return fromZonedTime(set(lastFullDate, { hours: 0, minutes: 0, seconds: 0, milliseconds: 0 }), this.timezone);
|
|
1467
1465
|
}
|
|
@@ -1601,7 +1599,6 @@ class MarketTimeUtil {
|
|
|
1601
1599
|
}
|
|
1602
1600
|
// Convert end date to specified timezone
|
|
1603
1601
|
const zonedEndDate = toZonedTime(end, this.timezone);
|
|
1604
|
-
let startDate;
|
|
1605
1602
|
let endDate;
|
|
1606
1603
|
const isCurrentMarketDay = this.isMarketDayZoned(zonedEndDate);
|
|
1607
1604
|
const isWithinHours = this.isWithinMarketHoursZoned(zonedEndDate);
|
|
@@ -1633,7 +1630,7 @@ class MarketTimeUtil {
|
|
|
1633
1630
|
// Now calculate the start date based on the period
|
|
1634
1631
|
const periodStartDate = this.calculatePeriodStartDate(endDate, period);
|
|
1635
1632
|
const { start: dayStart } = this.getDayBoundaries(periodStartDate);
|
|
1636
|
-
startDate = dayStart;
|
|
1633
|
+
const startDate = dayStart;
|
|
1637
1634
|
// Convert boundaries back to UTC for final output
|
|
1638
1635
|
const utcStart = fromZonedTime(startDate, this.timezone);
|
|
1639
1636
|
const utcEnd = fromZonedTime(endDate, this.timezone);
|
|
@@ -2500,7 +2497,7 @@ class AlpacaMarketDataAPI extends EventEmitter {
|
|
|
2500
2497
|
async getHistoricalBars(params) {
|
|
2501
2498
|
const symbols = params.symbols;
|
|
2502
2499
|
const symbolsStr = symbols.join(",");
|
|
2503
|
-
|
|
2500
|
+
const allBars = {};
|
|
2504
2501
|
let pageToken = null;
|
|
2505
2502
|
let hasMorePages = true;
|
|
2506
2503
|
let totalBarsCount = 0;
|
|
@@ -2814,7 +2811,7 @@ class AlpacaMarketDataAPI extends EventEmitter {
|
|
|
2814
2811
|
*/
|
|
2815
2812
|
async getLatestOptionsTrades(params) {
|
|
2816
2813
|
// Remove limit and page_token as they're not supported by this endpoint
|
|
2817
|
-
const { limit, page_token, ...requestParams } = params;
|
|
2814
|
+
const { limit: _limit, page_token: _page_token, ...requestParams } = params;
|
|
2818
2815
|
return this.makeRequest("/options/trades/latest", "GET", requestParams, "v1beta1");
|
|
2819
2816
|
}
|
|
2820
2817
|
/**
|
|
@@ -2826,7 +2823,7 @@ class AlpacaMarketDataAPI extends EventEmitter {
|
|
|
2826
2823
|
*/
|
|
2827
2824
|
async getLatestOptionsQuotes(params) {
|
|
2828
2825
|
// Remove limit and page_token as they're not supported by this endpoint
|
|
2829
|
-
const { limit, page_token, ...requestParams } = params;
|
|
2826
|
+
const { limit: _limit, page_token: _page_token, ...requestParams } = params;
|
|
2830
2827
|
return this.makeRequest("/options/quotes/latest", "GET", requestParams, "v1beta1");
|
|
2831
2828
|
}
|
|
2832
2829
|
/**
|
|
@@ -2840,7 +2837,7 @@ class AlpacaMarketDataAPI extends EventEmitter {
|
|
|
2840
2837
|
async getHistoricalOptionsBars(params) {
|
|
2841
2838
|
const symbols = params.symbols;
|
|
2842
2839
|
const symbolsStr = symbols.join(",");
|
|
2843
|
-
|
|
2840
|
+
const allBars = {};
|
|
2844
2841
|
let pageToken = null;
|
|
2845
2842
|
let hasMorePages = true;
|
|
2846
2843
|
let totalBarsCount = 0;
|
|
@@ -2924,7 +2921,7 @@ class AlpacaMarketDataAPI extends EventEmitter {
|
|
|
2924
2921
|
async getHistoricalOptionsTrades(params) {
|
|
2925
2922
|
const symbols = params.symbols;
|
|
2926
2923
|
const symbolsStr = symbols.join(",");
|
|
2927
|
-
|
|
2924
|
+
const allTrades = {};
|
|
2928
2925
|
let pageToken = null;
|
|
2929
2926
|
let hasMorePages = true;
|
|
2930
2927
|
let totalTradesCount = 0;
|
|
@@ -3007,7 +3004,7 @@ class AlpacaMarketDataAPI extends EventEmitter {
|
|
|
3007
3004
|
*/
|
|
3008
3005
|
async getOptionsSnapshot(params) {
|
|
3009
3006
|
// Remove limit and page_token as they may not be supported by this endpoint
|
|
3010
|
-
const { limit, page_token, ...requestParams } = params;
|
|
3007
|
+
const { limit: _limit, page_token: _page_token, ...requestParams } = params;
|
|
3011
3008
|
return this.makeRequest("/options/snapshots", "GET", requestParams, "v1beta1");
|
|
3012
3009
|
}
|
|
3013
3010
|
/**
|
|
@@ -5704,11 +5701,12 @@ async function closePosition$1(auth, symbolOrAssetId, params) {
|
|
|
5704
5701
|
throw new Error(`Position not found for ${symbolOrAssetId}`);
|
|
5705
5702
|
}
|
|
5706
5703
|
// Construct global Alpaca Auth for quote fetching
|
|
5707
|
-
const
|
|
5704
|
+
const alpacaAuthData = {
|
|
5708
5705
|
type: "LIVE",
|
|
5709
5706
|
alpacaApiKey: process.env.ALPACA_API_KEY,
|
|
5710
5707
|
alpacaApiSecret: process.env.ALPACA_API_SECRET || process.env.ALPACA_SECRET_KEY,
|
|
5711
5708
|
};
|
|
5709
|
+
const alpacaAuth = alpacaAuthData;
|
|
5712
5710
|
const quotesResponse = await getLatestQuotes$1(alpacaAuth, {
|
|
5713
5711
|
symbols: [symbolOrAssetId],
|
|
5714
5712
|
});
|
|
@@ -5911,11 +5909,12 @@ async function closeAllPositionsAfterHours$1(auth, params = { cancel_orders: tru
|
|
|
5911
5909
|
account: auth.adapticAccountId || "direct",
|
|
5912
5910
|
});
|
|
5913
5911
|
}
|
|
5914
|
-
const
|
|
5912
|
+
const alpacaAuthObj = {
|
|
5915
5913
|
type: "LIVE",
|
|
5916
5914
|
alpacaApiKey: process.env.ALPACA_API_KEY,
|
|
5917
5915
|
alpacaApiSecret: process.env.ALPACA_SECRET_KEY,
|
|
5918
5916
|
};
|
|
5917
|
+
const alpacaAuth = alpacaAuthObj;
|
|
5919
5918
|
const symbols = positions.map((position) => position.symbol);
|
|
5920
5919
|
const quotesResponse = await getLatestQuotes$1(alpacaAuth, { symbols });
|
|
5921
5920
|
for (const position of positions) {
|
|
@@ -5971,11 +5970,12 @@ async function fetchAccountDetails({ accountId, client, alpacaAccount, auth, })
|
|
|
5971
5970
|
let alpacaAccountObj = alpacaAccount ? alpacaAccount : null;
|
|
5972
5971
|
if (!alpacaAccountObj && auth) {
|
|
5973
5972
|
const validatedAuth = await validateAuth(auth);
|
|
5974
|
-
|
|
5973
|
+
const accountFromAuth = {
|
|
5975
5974
|
APIKey: validatedAuth.APIKey,
|
|
5976
5975
|
APISecret: validatedAuth.APISecret,
|
|
5977
5976
|
type: validatedAuth.type,
|
|
5978
5977
|
};
|
|
5978
|
+
alpacaAccountObj = accountFromAuth;
|
|
5979
5979
|
}
|
|
5980
5980
|
if (!alpacaAccountObj) {
|
|
5981
5981
|
try {
|
|
@@ -6220,7 +6220,7 @@ async function updateConfiguration(user, account, updatedConfig) {
|
|
|
6220
6220
|
throw new Error(`Allocation percentages must sum to 100%. Current total: ${totalAllocation}%`);
|
|
6221
6221
|
}
|
|
6222
6222
|
if (account.allocation) {
|
|
6223
|
-
|
|
6223
|
+
const allocUpdateData = {
|
|
6224
6224
|
id: account.allocation.id,
|
|
6225
6225
|
alpacaAccount: {
|
|
6226
6226
|
id: account.id,
|
|
@@ -6232,10 +6232,11 @@ async function updateConfiguration(user, account, updatedConfig) {
|
|
|
6232
6232
|
etfs: updatedConfig.allocation.etfs ?? 0,
|
|
6233
6233
|
forex: updatedConfig.allocation.forex ?? 0,
|
|
6234
6234
|
crypto: updatedConfig.allocation.crypto ?? 0,
|
|
6235
|
-
}
|
|
6235
|
+
};
|
|
6236
|
+
allocUpdatePromise = adaptic$1.allocation.update(allocUpdateData, client);
|
|
6236
6237
|
}
|
|
6237
6238
|
else {
|
|
6238
|
-
|
|
6239
|
+
const allocCreateData = {
|
|
6239
6240
|
stocks: updatedConfig.allocation.stocks ?? 0,
|
|
6240
6241
|
options: updatedConfig.allocation.options ?? 0,
|
|
6241
6242
|
futures: updatedConfig.allocation.futures ?? 0,
|
|
@@ -6246,10 +6247,11 @@ async function updateConfiguration(user, account, updatedConfig) {
|
|
|
6246
6247
|
id: account.id,
|
|
6247
6248
|
},
|
|
6248
6249
|
alpacaAccountId: account.id,
|
|
6249
|
-
}
|
|
6250
|
+
};
|
|
6251
|
+
allocUpdatePromise = adaptic$1.allocation.create(allocCreateData, client);
|
|
6250
6252
|
}
|
|
6251
6253
|
}
|
|
6252
|
-
const
|
|
6254
|
+
const accountUpdateData = {
|
|
6253
6255
|
id: account.id,
|
|
6254
6256
|
user: {
|
|
6255
6257
|
id: user.id,
|
|
@@ -6275,7 +6277,8 @@ async function updateConfiguration(user, account, updatedConfig) {
|
|
|
6275
6277
|
firstReducedTrailPercentage100: updatedConfig.firstReducedTrailPercentage100 ?? 0,
|
|
6276
6278
|
secondReducedTrailPercentage100: updatedConfig.secondReducedTrailPercentage100 ?? 0,
|
|
6277
6279
|
minimumPriceChangePercent100: updatedConfig.minimumPriceChangePercent100 ?? 0,
|
|
6278
|
-
}
|
|
6280
|
+
};
|
|
6281
|
+
const adapticUpdatePromise = adaptic$1.alpacaAccount.update(accountUpdateData, client);
|
|
6279
6282
|
const [alpacaResponse, updatedAlpacaAccount, updatedAllocation] = await Promise.all([
|
|
6280
6283
|
alpacaUpdatePromise,
|
|
6281
6284
|
adapticUpdatePromise,
|
|
@@ -7586,7 +7589,7 @@ const fetchTickerInfo = async (symbol, options) => {
|
|
|
7586
7589
|
if (results.share_class_shares_outstanding === undefined) {
|
|
7587
7590
|
results.share_class_shares_outstanding = null;
|
|
7588
7591
|
}
|
|
7589
|
-
|
|
7592
|
+
const tickerInfo = {
|
|
7590
7593
|
ticker: results.ticker,
|
|
7591
7594
|
type: results.type,
|
|
7592
7595
|
active: results.active,
|
|
@@ -7599,6 +7602,7 @@ const fetchTickerInfo = async (symbol, options) => {
|
|
|
7599
7602
|
primary_exchange: results.primary_exchange,
|
|
7600
7603
|
share_class_shares_outstanding: results.share_class_shares_outstanding,
|
|
7601
7604
|
};
|
|
7605
|
+
return tickerInfo;
|
|
7602
7606
|
}
|
|
7603
7607
|
catch (error) {
|
|
7604
7608
|
const errorMessage = error instanceof Error ? error.message : "Unknown error occurred";
|
|
@@ -7923,7 +7927,7 @@ const fetchGroupedDaily = async (date, options) => {
|
|
|
7923
7927
|
if (!MASSIVE_VALID_STATUSES.has(data.status)) {
|
|
7924
7928
|
throw new Error(`Massive.com API responded with status: ${data.status}`);
|
|
7925
7929
|
}
|
|
7926
|
-
|
|
7930
|
+
const groupedDaily = {
|
|
7927
7931
|
adjusted: data.adjusted,
|
|
7928
7932
|
queryCount: data.queryCount,
|
|
7929
7933
|
request_id: data.request_id,
|
|
@@ -7941,6 +7945,7 @@ const fetchGroupedDaily = async (date, options) => {
|
|
|
7941
7945
|
trades: result.n,
|
|
7942
7946
|
})),
|
|
7943
7947
|
};
|
|
7948
|
+
return groupedDaily;
|
|
7944
7949
|
}
|
|
7945
7950
|
catch (error) {
|
|
7946
7951
|
const errorMessage = error instanceof Error ? error.message : "Unknown error occurred";
|
|
@@ -8356,25 +8361,9 @@ const calculateFees = async (action, trade, alpacaAccount) => {
|
|
|
8356
8361
|
0;
|
|
8357
8362
|
switch (assetType) {
|
|
8358
8363
|
case "STOCK":
|
|
8359
|
-
|
|
8360
|
-
|
|
8361
|
-
|
|
8362
|
-
// regulatoryFee =
|
|
8363
|
-
// (tradeValue * FEE_CONFIG.REGULATORY_FEES_PERCENTAGE) / 100;
|
|
8364
|
-
// fee = commissionFee + regulatoryFee;
|
|
8365
|
-
// break;
|
|
8366
|
-
// case "OPTION" as enums.AssetType.OPTION:
|
|
8367
|
-
// perContractFee = qty * FEE_CONFIG.OPTIONS_PER_CONTRACT_FEE;
|
|
8368
|
-
// baseCommission = FEE_CONFIG.OPTIONS_BASE_COMMISSION;
|
|
8369
|
-
// fee = perContractFee + baseCommission;
|
|
8370
|
-
// break;
|
|
8371
|
-
// case "CRYPTOCURRENCY" as enums.AssetType.CRYPTOCURRENCY:
|
|
8372
|
-
// fee = (tradeValue * FEE_CONFIG.CRYPTO_TRANSACTION_PERCENTAGE) / 100;
|
|
8373
|
-
// break;
|
|
8374
|
-
// case "FUTURE" as enums.AssetType.FUTURE:
|
|
8375
|
-
// // Sum of all futures fees
|
|
8376
|
-
// fee = 0.85 + 0.85 + 0.25 + 0.02 + 0.01 + 0.3 + 0.01;
|
|
8377
|
-
// break;
|
|
8364
|
+
// Currently zero fees for stocks via Alpaca
|
|
8365
|
+
fee = 0;
|
|
8366
|
+
break;
|
|
8378
8367
|
default:
|
|
8379
8368
|
fee = 0;
|
|
8380
8369
|
break;
|
|
@@ -8948,7 +8937,7 @@ async function calculateExpenseRatio({ accountId, client, alpacaAccount, }) {
|
|
|
8948
8937
|
getLogger().warn("Missing account ID or client to calculate expense ratio.");
|
|
8949
8938
|
return "N/A";
|
|
8950
8939
|
}
|
|
8951
|
-
|
|
8940
|
+
const alpacaAccountId = accountId || (alpacaAccount && alpacaAccount.id) || "";
|
|
8952
8941
|
let accountDetails;
|
|
8953
8942
|
if (!alpacaAccountId) {
|
|
8954
8943
|
getLogger().warn("Invalid account ID.");
|
|
@@ -8988,7 +8977,7 @@ async function calculateExpenseRatio({ accountId, client, alpacaAccount, }) {
|
|
|
8988
8977
|
return `${expenseRatio.toFixed(2)}%`;
|
|
8989
8978
|
}
|
|
8990
8979
|
// Mock function to represent fetching expenses from your system
|
|
8991
|
-
async function getPortfolioExpensesFromYourSystem(
|
|
8980
|
+
async function getPortfolioExpensesFromYourSystem(_accountId) {
|
|
8992
8981
|
// Implement this function based on your data storage
|
|
8993
8982
|
return 0; // Placeholder
|
|
8994
8983
|
}
|
|
@@ -9004,7 +8993,7 @@ async function calculateLiquidityRatio({ accountId, client, alpacaAccount, }) {
|
|
|
9004
8993
|
getLogger().warn("Missing account ID or client to calculateLiquidityRatio.");
|
|
9005
8994
|
return "N/A";
|
|
9006
8995
|
}
|
|
9007
|
-
|
|
8996
|
+
const alpacaAccountId = accountId || (alpacaAccount && alpacaAccount.id) || "";
|
|
9008
8997
|
let accountDetails;
|
|
9009
8998
|
if (!alpacaAccountId) {
|
|
9010
8999
|
getLogger().warn("Invalid account ID.");
|
|
@@ -9704,7 +9693,7 @@ async function fetchPerformanceMetrics({ params, client, accountId, alpacaAccoun
|
|
|
9704
9693
|
const benchmarkSymbol = "SPY";
|
|
9705
9694
|
let benchmarkBars = [];
|
|
9706
9695
|
try {
|
|
9707
|
-
const { start, end } =
|
|
9696
|
+
const { start, end } = getStartAndEndTimestamps({
|
|
9708
9697
|
timezone: "America/New_York",
|
|
9709
9698
|
period: params?.period === "YTD" || params?.period === "1A"
|
|
9710
9699
|
? "1Y"
|
|
@@ -9749,7 +9738,7 @@ async function fetchPerformanceMetrics({ params, client, accountId, alpacaAccoun
|
|
|
9749
9738
|
alpacaAccount: alpacaAccountObj,
|
|
9750
9739
|
}),
|
|
9751
9740
|
getDividendYield(),
|
|
9752
|
-
calculateMaxDrawdown(portfolioHistory.equity),
|
|
9741
|
+
Promise.resolve(calculateMaxDrawdown(portfolioHistory.equity)),
|
|
9753
9742
|
]);
|
|
9754
9743
|
// Extract results with error handling for each metric
|
|
9755
9744
|
const result = { ...defaultMetrics };
|
|
@@ -9904,7 +9893,7 @@ function calculateFibonacciLevels(priceData, { lookbackPeriod = 20, retracementL
|
|
|
9904
9893
|
const swingLow = Math.min(...periodSlice.map((d) => d.low));
|
|
9905
9894
|
const priceRange = swingHigh - swingLow;
|
|
9906
9895
|
const trend = reverseDirection ? "downtrend" : "uptrend";
|
|
9907
|
-
|
|
9896
|
+
const levels = [];
|
|
9908
9897
|
if (priceRange > 0) {
|
|
9909
9898
|
// Calculate retracement levels
|
|
9910
9899
|
retracementLevels.forEach((level) => {
|
|
@@ -48577,7 +48566,8 @@ class AlpacaClient {
|
|
|
48577
48566
|
// Handle empty responses (e.g., DELETE requests)
|
|
48578
48567
|
const contentType = response.headers.get("content-type");
|
|
48579
48568
|
if (!contentType || !contentType.includes("application/json")) {
|
|
48580
|
-
|
|
48569
|
+
const emptyObj = {};
|
|
48570
|
+
return emptyObj;
|
|
48581
48571
|
}
|
|
48582
48572
|
return (await response.json());
|
|
48583
48573
|
}
|
|
@@ -56063,7 +56053,7 @@ async function getHistoricalOptionsBars(client, params) {
|
|
|
56063
56053
|
* Calculate implied volatility from option price (simplified approximation)
|
|
56064
56054
|
* For production use, consider using a proper Black-Scholes solver
|
|
56065
56055
|
*/
|
|
56066
|
-
function approximateImpliedVolatility(optionPrice, underlyingPrice, strike, daysToExpiration,
|
|
56056
|
+
function approximateImpliedVolatility(optionPrice, underlyingPrice, strike, daysToExpiration, _riskFreeRate = 0.05, isCall = true) {
|
|
56067
56057
|
// Simplified IV approximation using Brenner-Subrahmanyam formula
|
|
56068
56058
|
// IV ~ (optionPrice / underlyingPrice) * sqrt(2 * pi / T)
|
|
56069
56059
|
const T = daysToExpiration / 365;
|
|
@@ -61334,7 +61324,7 @@ class AssetAllocationEngine {
|
|
|
61334
61324
|
/**
|
|
61335
61325
|
* Apply user constraints and preferences
|
|
61336
61326
|
*/
|
|
61337
|
-
applyConstraints(allocations, preferences, constraints,
|
|
61327
|
+
applyConstraints(allocations, preferences, constraints, _characteristics) {
|
|
61338
61328
|
const constrained = new Map(allocations);
|
|
61339
61329
|
// Apply exclusions
|
|
61340
61330
|
if (preferences?.excludedAssetClasses) {
|