@discomedia/utils 1.0.63 → 1.0.64
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-frontend.cjs +31 -5
- package/dist/index-frontend.cjs.map +1 -1
- package/dist/index-frontend.mjs +31 -5
- package/dist/index-frontend.mjs.map +1 -1
- package/dist/index.cjs +310 -208
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +310 -208
- package/dist/index.mjs.map +1 -1
- package/dist/package.json +2 -2
- package/dist/test.js +310 -208
- package/dist/test.js.map +1 -1
- package/dist/types/alpaca-market-data-api.d.ts.map +1 -1
- package/dist/types/alpaca-trading-api.d.ts +8 -1
- package/dist/types/alpaca-trading-api.d.ts.map +1 -1
- package/dist/types/types/alpaca-types.d.ts +29 -0
- package/dist/types/types/alpaca-types.d.ts.map +1 -1
- package/dist/types-frontend/alpaca-market-data-api.d.ts.map +1 -1
- package/dist/types-frontend/alpaca-trading-api.d.ts +8 -1
- package/dist/types-frontend/alpaca-trading-api.d.ts.map +1 -1
- package/dist/types-frontend/types/alpaca-types.d.ts +29 -0
- package/dist/types-frontend/types/alpaca-types.d.ts.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -1616,7 +1616,7 @@ const safeJSON = (text) => {
|
|
|
1616
1616
|
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
|
1617
1617
|
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
1618
1618
|
|
|
1619
|
-
const VERSION = '6.
|
|
1619
|
+
const VERSION = '6.31.0'; // x-release-please-version
|
|
1620
1620
|
|
|
1621
1621
|
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
|
|
1622
1622
|
const isRunningInBrowser = () => {
|
|
@@ -4860,7 +4860,7 @@ class Speech extends APIResource {
|
|
|
4860
4860
|
* const speech = await client.audio.speech.create({
|
|
4861
4861
|
* input: 'input',
|
|
4862
4862
|
* model: 'string',
|
|
4863
|
-
* voice: '
|
|
4863
|
+
* voice: 'string',
|
|
4864
4864
|
* });
|
|
4865
4865
|
*
|
|
4866
4866
|
* const content = await speech.blob();
|
|
@@ -8141,7 +8141,7 @@ class Videos extends APIResource {
|
|
|
8141
8141
|
* Create a new video generation job from a prompt and optional reference assets.
|
|
8142
8142
|
*/
|
|
8143
8143
|
create(body, options) {
|
|
8144
|
-
return this._client.post('/videos',
|
|
8144
|
+
return this._client.post('/videos', multipartFormRequestOptions({ body, ...options }, this._client));
|
|
8145
8145
|
}
|
|
8146
8146
|
/**
|
|
8147
8147
|
* Fetch the latest metadata for a generated video.
|
|
@@ -8161,6 +8161,12 @@ class Videos extends APIResource {
|
|
|
8161
8161
|
delete(videoID, options) {
|
|
8162
8162
|
return this._client.delete(path `/videos/${videoID}`, options);
|
|
8163
8163
|
}
|
|
8164
|
+
/**
|
|
8165
|
+
* Create a character from an uploaded video.
|
|
8166
|
+
*/
|
|
8167
|
+
createCharacter(body, options) {
|
|
8168
|
+
return this._client.post('/videos/characters', multipartFormRequestOptions({ body, ...options }, this._client));
|
|
8169
|
+
}
|
|
8164
8170
|
/**
|
|
8165
8171
|
* Download the generated video bytes or a derived preview asset.
|
|
8166
8172
|
*
|
|
@@ -8174,6 +8180,25 @@ class Videos extends APIResource {
|
|
|
8174
8180
|
__binaryResponse: true,
|
|
8175
8181
|
});
|
|
8176
8182
|
}
|
|
8183
|
+
/**
|
|
8184
|
+
* Create a new video generation job by editing a source video or existing
|
|
8185
|
+
* generated video.
|
|
8186
|
+
*/
|
|
8187
|
+
edit(body, options) {
|
|
8188
|
+
return this._client.post('/videos/edits', multipartFormRequestOptions({ body, ...options }, this._client));
|
|
8189
|
+
}
|
|
8190
|
+
/**
|
|
8191
|
+
* Create an extension of a completed video.
|
|
8192
|
+
*/
|
|
8193
|
+
extend(body, options) {
|
|
8194
|
+
return this._client.post('/videos/extensions', multipartFormRequestOptions({ body, ...options }, this._client));
|
|
8195
|
+
}
|
|
8196
|
+
/**
|
|
8197
|
+
* Fetch a character.
|
|
8198
|
+
*/
|
|
8199
|
+
getCharacter(characterID, options) {
|
|
8200
|
+
return this._client.get(path `/videos/characters/${characterID}`, options);
|
|
8201
|
+
}
|
|
8177
8202
|
/**
|
|
8178
8203
|
* Create a remix of a completed video using a refreshed prompt.
|
|
8179
8204
|
*/
|
|
@@ -8455,8 +8480,9 @@ class OpenAI {
|
|
|
8455
8480
|
new URL(path)
|
|
8456
8481
|
: new URL(baseURL + (baseURL.endsWith('/') && path.startsWith('/') ? path.slice(1) : path));
|
|
8457
8482
|
const defaultQuery = this.defaultQuery();
|
|
8458
|
-
|
|
8459
|
-
|
|
8483
|
+
const pathQuery = Object.fromEntries(url.searchParams);
|
|
8484
|
+
if (!isEmptyObj$1(defaultQuery) || !isEmptyObj$1(pathQuery)) {
|
|
8485
|
+
query = { ...pathQuery, ...defaultQuery, ...query };
|
|
8460
8486
|
}
|
|
8461
8487
|
if (typeof query === 'object' && query && !Array.isArray(query)) {
|
|
8462
8488
|
url.search = this.stringifyQuery(query);
|
|
@@ -19039,7 +19065,7 @@ class AlpacaMarketDataAPI extends require$$0$3.EventEmitter {
|
|
|
19039
19065
|
*/
|
|
19040
19066
|
async getHistoricalBars(params) {
|
|
19041
19067
|
const symbols = params.symbols;
|
|
19042
|
-
symbols.join(',');
|
|
19068
|
+
const symbolsStr = symbols.join(',');
|
|
19043
19069
|
let allBars = {};
|
|
19044
19070
|
let pageToken = null;
|
|
19045
19071
|
let hasMorePages = true;
|
|
@@ -19050,7 +19076,7 @@ class AlpacaMarketDataAPI extends require$$0$3.EventEmitter {
|
|
|
19050
19076
|
symbols.forEach((symbol) => {
|
|
19051
19077
|
allBars[symbol] = [];
|
|
19052
19078
|
});
|
|
19053
|
-
log(`Starting
|
|
19079
|
+
log(`Starting ${params.timeframe}bars fetch for ${symbols.length} symbols (${symbolsStr}), ${params.start || 'no start'} to ${params.end || 'no end'})`, { symbol: symbolsStr });
|
|
19054
19080
|
while (hasMorePages) {
|
|
19055
19081
|
pageCount++;
|
|
19056
19082
|
const requestParams = {
|
|
@@ -19061,7 +19087,7 @@ class AlpacaMarketDataAPI extends require$$0$3.EventEmitter {
|
|
|
19061
19087
|
};
|
|
19062
19088
|
const response = await this.makeRequest('/stocks/bars', 'GET', requestParams);
|
|
19063
19089
|
if (!response.bars) {
|
|
19064
|
-
log(`No bars data found in response for ${symbols.length} symbols`, { type: 'warn' });
|
|
19090
|
+
log(`No bars data found in response for ${symbols.length} symbols`, { symbol: symbolsStr, type: 'warn' });
|
|
19065
19091
|
break;
|
|
19066
19092
|
}
|
|
19067
19093
|
// Track currency from first response
|
|
@@ -19095,7 +19121,7 @@ class AlpacaMarketDataAPI extends require$$0$3.EventEmitter {
|
|
|
19095
19121
|
const dateRangeStr = earliestTimestamp && latestTimestamp
|
|
19096
19122
|
? `${new Date(earliestTimestamp).toLocaleDateString('en-US', { timeZone: 'America/New_York' })} to ${new Date(latestTimestamp).toLocaleDateString('en-US', { timeZone: 'America/New_York' })}`
|
|
19097
19123
|
: 'unknown range';
|
|
19098
|
-
log(`Page ${pageCount}: Fetched ${pageBarsCount.toLocaleString()} bars (total: ${totalBarsCount.toLocaleString()}) for ${symbols.length} symbols, date range: ${dateRangeStr}${hasMorePages ? ', more pages available' : ', complete'}`, { type: 'debug' });
|
|
19124
|
+
log(`Page ${pageCount}: Fetched ${pageBarsCount.toLocaleString()} bars (total: ${totalBarsCount.toLocaleString()}) for ${symbols.length} symbols, date range: ${dateRangeStr}${hasMorePages ? ', more pages available' : ', complete'}`, { symbol: symbolsStr, type: 'debug' });
|
|
19099
19125
|
// Prevent infinite loops
|
|
19100
19126
|
if (pageCount > 1000) {
|
|
19101
19127
|
log(`Stopping pagination after ${pageCount} pages to prevent infinite loop`, { type: 'warn' });
|
|
@@ -19106,7 +19132,7 @@ class AlpacaMarketDataAPI extends require$$0$3.EventEmitter {
|
|
|
19106
19132
|
const symbolCounts = Object.entries(allBars)
|
|
19107
19133
|
.map(([symbol, bars]) => `${symbol}: ${bars.length}`)
|
|
19108
19134
|
.join(', ');
|
|
19109
|
-
log(
|
|
19135
|
+
log(`${params.timeframe} bars fetch complete: ${totalBarsCount.toLocaleString()} total bars across ${pageCount} pages for ${symbols.length} symbols (${symbolCounts})`, { symbol: symbolsStr });
|
|
19110
19136
|
return {
|
|
19111
19137
|
bars: allBars,
|
|
19112
19138
|
next_page_token: null, // Always null since we fetch all pages
|
|
@@ -19958,6 +19984,26 @@ class AlpacaMarketDataAPI extends require$$0$3.EventEmitter {
|
|
|
19958
19984
|
const marketDataAPI = AlpacaMarketDataAPI.getInstance();
|
|
19959
19985
|
|
|
19960
19986
|
const limitPriceSlippagePercent100 = 0.1; // 0.1%
|
|
19987
|
+
class AlpacaRequestError extends Error {
|
|
19988
|
+
method;
|
|
19989
|
+
status;
|
|
19990
|
+
url;
|
|
19991
|
+
responseCode;
|
|
19992
|
+
responseDetails;
|
|
19993
|
+
rawResponse;
|
|
19994
|
+
symbol;
|
|
19995
|
+
constructor(params) {
|
|
19996
|
+
super(params.message);
|
|
19997
|
+
this.name = 'AlpacaRequestError';
|
|
19998
|
+
this.method = params.method;
|
|
19999
|
+
this.status = params.status ?? null;
|
|
20000
|
+
this.url = params.url;
|
|
20001
|
+
this.responseCode = params.responseCode ?? null;
|
|
20002
|
+
this.responseDetails = params.responseDetails ?? null;
|
|
20003
|
+
this.rawResponse = params.rawResponse ?? null;
|
|
20004
|
+
this.symbol = params.symbol;
|
|
20005
|
+
}
|
|
20006
|
+
}
|
|
19961
20007
|
/**
|
|
19962
20008
|
Websocket example
|
|
19963
20009
|
const alpacaAPI = createAlpacaTradingAPI(credentials); // type AlpacaCredentials
|
|
@@ -20041,6 +20087,75 @@ class AlpacaTradingAPI {
|
|
|
20041
20087
|
roundPriceForAlpaca = (price) => {
|
|
20042
20088
|
return price >= 1 ? Math.round(price * 100) / 100 : Math.round(price * 10000) / 10000;
|
|
20043
20089
|
};
|
|
20090
|
+
isJsonObject(value) {
|
|
20091
|
+
return value !== null && !Array.isArray(value) && typeof value === 'object';
|
|
20092
|
+
}
|
|
20093
|
+
parseAlpacaAPIErrorResponse(rawResponse) {
|
|
20094
|
+
if (rawResponse.trim() === '') {
|
|
20095
|
+
return null;
|
|
20096
|
+
}
|
|
20097
|
+
try {
|
|
20098
|
+
const parsedValue = JSON.parse(rawResponse);
|
|
20099
|
+
if (!this.isJsonObject(parsedValue)) {
|
|
20100
|
+
return null;
|
|
20101
|
+
}
|
|
20102
|
+
const code = parsedValue['code'];
|
|
20103
|
+
const message = parsedValue['message'];
|
|
20104
|
+
const symbol = parsedValue['symbol'];
|
|
20105
|
+
if (typeof code !== 'number' || typeof message !== 'string') {
|
|
20106
|
+
return null;
|
|
20107
|
+
}
|
|
20108
|
+
if (symbol !== undefined && typeof symbol !== 'string') {
|
|
20109
|
+
return null;
|
|
20110
|
+
}
|
|
20111
|
+
return parsedValue;
|
|
20112
|
+
}
|
|
20113
|
+
catch {
|
|
20114
|
+
return null;
|
|
20115
|
+
}
|
|
20116
|
+
}
|
|
20117
|
+
formatJsonValueForLog(value) {
|
|
20118
|
+
if (value === undefined) {
|
|
20119
|
+
return 'undefined';
|
|
20120
|
+
}
|
|
20121
|
+
if (Array.isArray(value)) {
|
|
20122
|
+
return value.map((entry) => this.formatJsonValueForLog(entry)).join(', ');
|
|
20123
|
+
}
|
|
20124
|
+
if (value === null) {
|
|
20125
|
+
return 'null';
|
|
20126
|
+
}
|
|
20127
|
+
if (typeof value === 'object') {
|
|
20128
|
+
return JSON.stringify(value);
|
|
20129
|
+
}
|
|
20130
|
+
return `${value}`;
|
|
20131
|
+
}
|
|
20132
|
+
formatAlpacaAPIErrorDetails(errorResponse) {
|
|
20133
|
+
return Object.entries(errorResponse)
|
|
20134
|
+
.filter(([key]) => key !== 'code' && key !== 'message' && key !== 'symbol')
|
|
20135
|
+
.map(([key, value]) => `${key}=${this.formatJsonValueForLog(value)}`)
|
|
20136
|
+
.join(', ');
|
|
20137
|
+
}
|
|
20138
|
+
formatRequestAction(requestContext) {
|
|
20139
|
+
return requestContext?.action ? `${requestContext.action} failed` : 'Alpaca request failed';
|
|
20140
|
+
}
|
|
20141
|
+
buildAlpacaAPIErrorMessage(params) {
|
|
20142
|
+
const { requestContext, status, url, errorResponse, rawResponse } = params;
|
|
20143
|
+
const action = this.formatRequestAction(requestContext);
|
|
20144
|
+
const message = errorResponse?.message ?? (rawResponse || 'No error body returned');
|
|
20145
|
+
const responseCode = errorResponse?.code ? ` (code ${errorResponse.code})` : '';
|
|
20146
|
+
const detailSummary = errorResponse ? this.formatAlpacaAPIErrorDetails(errorResponse) : '';
|
|
20147
|
+
const detailText = detailSummary !== ''
|
|
20148
|
+
? ` Details: ${detailSummary}.`
|
|
20149
|
+
: rawResponse.trim() !== '' && errorResponse === null
|
|
20150
|
+
? ` Response: ${rawResponse}.`
|
|
20151
|
+
: '';
|
|
20152
|
+
return `${action}: Alpaca API ${status}${responseCode}: ${message}.${detailText} Url: ${url}`;
|
|
20153
|
+
}
|
|
20154
|
+
buildRequestExecutionErrorMessage(params) {
|
|
20155
|
+
const { requestContext, url, errorMessage } = params;
|
|
20156
|
+
const action = this.formatRequestAction(requestContext);
|
|
20157
|
+
return `${action}: ${errorMessage}. Url: ${url}`;
|
|
20158
|
+
}
|
|
20044
20159
|
handleAuthMessage(data) {
|
|
20045
20160
|
if (data.status === 'authorized') {
|
|
20046
20161
|
this.authenticated = true;
|
|
@@ -20268,7 +20383,7 @@ class AlpacaTradingAPI {
|
|
|
20268
20383
|
this.ws?.on('message', handleListenResponse);
|
|
20269
20384
|
});
|
|
20270
20385
|
}
|
|
20271
|
-
async makeRequest(endpoint, method = 'GET', body, queryString = '') {
|
|
20386
|
+
async makeRequest(endpoint, method = 'GET', body, queryString = '', requestContext) {
|
|
20272
20387
|
const url = `${this.apiBaseUrl}${endpoint}${queryString}`;
|
|
20273
20388
|
try {
|
|
20274
20389
|
const response = await fetch(url, {
|
|
@@ -20277,9 +20392,27 @@ class AlpacaTradingAPI {
|
|
|
20277
20392
|
body: body ? JSON.stringify(body) : undefined,
|
|
20278
20393
|
});
|
|
20279
20394
|
if (!response.ok) {
|
|
20280
|
-
const
|
|
20281
|
-
|
|
20282
|
-
|
|
20395
|
+
const rawResponse = await response.text();
|
|
20396
|
+
const errorResponse = this.parseAlpacaAPIErrorResponse(rawResponse);
|
|
20397
|
+
const symbol = requestContext?.symbol ?? errorResponse?.symbol;
|
|
20398
|
+
const error = new AlpacaRequestError({
|
|
20399
|
+
message: this.buildAlpacaAPIErrorMessage({
|
|
20400
|
+
requestContext,
|
|
20401
|
+
status: response.status,
|
|
20402
|
+
url,
|
|
20403
|
+
errorResponse,
|
|
20404
|
+
rawResponse,
|
|
20405
|
+
}),
|
|
20406
|
+
method,
|
|
20407
|
+
status: response.status,
|
|
20408
|
+
url,
|
|
20409
|
+
responseCode: errorResponse?.code ?? null,
|
|
20410
|
+
responseDetails: errorResponse,
|
|
20411
|
+
rawResponse,
|
|
20412
|
+
symbol,
|
|
20413
|
+
});
|
|
20414
|
+
this.log(error.message, { symbol, type: 'error' });
|
|
20415
|
+
throw error;
|
|
20283
20416
|
}
|
|
20284
20417
|
// Handle responses with no content (e.g., 204 No Content)
|
|
20285
20418
|
if (response.status === 204 || response.headers.get('content-length') === '0') {
|
|
@@ -20287,23 +20420,37 @@ class AlpacaTradingAPI {
|
|
|
20287
20420
|
}
|
|
20288
20421
|
const contentType = response.headers.get('content-type');
|
|
20289
20422
|
if (contentType && contentType.includes('application/json')) {
|
|
20290
|
-
return await response.json();
|
|
20423
|
+
return (await response.json());
|
|
20291
20424
|
}
|
|
20292
20425
|
// For non-JSON responses, return the text content
|
|
20293
20426
|
const textContent = await response.text();
|
|
20294
|
-
return textContent || null;
|
|
20427
|
+
return (textContent || null);
|
|
20295
20428
|
}
|
|
20296
|
-
catch (
|
|
20297
|
-
|
|
20298
|
-
|
|
20299
|
-
|
|
20300
|
-
|
|
20429
|
+
catch (error) {
|
|
20430
|
+
if (error instanceof AlpacaRequestError) {
|
|
20431
|
+
throw error;
|
|
20432
|
+
}
|
|
20433
|
+
const normalizedError = error instanceof Error ? error : new Error(`${error}`);
|
|
20434
|
+
const symbol = requestContext?.symbol;
|
|
20435
|
+
const requestError = new AlpacaRequestError({
|
|
20436
|
+
message: this.buildRequestExecutionErrorMessage({
|
|
20437
|
+
requestContext,
|
|
20438
|
+
url,
|
|
20439
|
+
errorMessage: normalizedError.message,
|
|
20440
|
+
}),
|
|
20441
|
+
method,
|
|
20442
|
+
url,
|
|
20443
|
+
rawResponse: null,
|
|
20444
|
+
symbol,
|
|
20301
20445
|
});
|
|
20302
|
-
|
|
20446
|
+
this.log(requestError.message, { symbol, type: 'error' });
|
|
20447
|
+
throw requestError;
|
|
20303
20448
|
}
|
|
20304
20449
|
}
|
|
20305
20450
|
async getPositions(assetClass) {
|
|
20306
|
-
const positions =
|
|
20451
|
+
const positions = await this.makeRequest('/positions', 'GET', undefined, '', {
|
|
20452
|
+
action: 'Get positions',
|
|
20453
|
+
});
|
|
20307
20454
|
if (assetClass) {
|
|
20308
20455
|
return positions.filter((position) => position.asset_class === assetClass);
|
|
20309
20456
|
}
|
|
@@ -20341,22 +20488,15 @@ class AlpacaTradingAPI {
|
|
|
20341
20488
|
if (params.side)
|
|
20342
20489
|
queryParams.append('side', params.side);
|
|
20343
20490
|
const endpoint = `/orders${queryParams.toString() ? `?${queryParams.toString()}` : ''}`;
|
|
20344
|
-
|
|
20345
|
-
|
|
20346
|
-
|
|
20347
|
-
|
|
20348
|
-
this.log(`Error getting orders: ${error}`, { type: 'error' });
|
|
20349
|
-
throw error;
|
|
20350
|
-
}
|
|
20491
|
+
return this.makeRequest(endpoint, 'GET', undefined, '', {
|
|
20492
|
+
action: 'Get orders',
|
|
20493
|
+
symbol: params.symbols?.join(','),
|
|
20494
|
+
});
|
|
20351
20495
|
}
|
|
20352
20496
|
async getAccountDetails() {
|
|
20353
|
-
|
|
20354
|
-
|
|
20355
|
-
}
|
|
20356
|
-
catch (error) {
|
|
20357
|
-
this.log(`Error getting account details: ${error}`, { type: 'error' });
|
|
20358
|
-
throw error;
|
|
20359
|
-
}
|
|
20497
|
+
return this.makeRequest('/account', 'GET', undefined, '', {
|
|
20498
|
+
action: 'Get account details',
|
|
20499
|
+
});
|
|
20360
20500
|
}
|
|
20361
20501
|
/**
|
|
20362
20502
|
* Create a trailing stop order
|
|
@@ -20374,27 +20514,21 @@ class AlpacaTradingAPI {
|
|
|
20374
20514
|
});
|
|
20375
20515
|
const body = {
|
|
20376
20516
|
symbol,
|
|
20377
|
-
qty: Math.abs(qty),
|
|
20517
|
+
qty: Math.abs(qty).toString(),
|
|
20378
20518
|
side,
|
|
20379
20519
|
position_intent,
|
|
20380
20520
|
order_class: 'simple',
|
|
20381
20521
|
type: 'trailing_stop',
|
|
20382
|
-
trail_percent: trailPercent100
|
|
20522
|
+
trail_percent: trailPercent100.toString(),
|
|
20383
20523
|
time_in_force: 'gtc',
|
|
20384
20524
|
};
|
|
20385
20525
|
if (client_order_id !== undefined) {
|
|
20386
20526
|
body.client_order_id = client_order_id;
|
|
20387
20527
|
}
|
|
20388
|
-
|
|
20389
|
-
|
|
20390
|
-
|
|
20391
|
-
|
|
20392
|
-
this.log(`Error creating trailing stop: ${error}`, {
|
|
20393
|
-
symbol,
|
|
20394
|
-
type: 'error',
|
|
20395
|
-
});
|
|
20396
|
-
throw error;
|
|
20397
|
-
}
|
|
20528
|
+
return this.makeRequest('/orders', 'POST', body, '', {
|
|
20529
|
+
action: 'Create trailing stop order',
|
|
20530
|
+
symbol,
|
|
20531
|
+
});
|
|
20398
20532
|
}
|
|
20399
20533
|
/**
|
|
20400
20534
|
* Create a stop order (stop or stop-limit)
|
|
@@ -20420,25 +20554,19 @@ class AlpacaTradingAPI {
|
|
|
20420
20554
|
position_intent,
|
|
20421
20555
|
order_class: 'simple',
|
|
20422
20556
|
type: isStopLimit ? 'stop_limit' : 'stop',
|
|
20423
|
-
stop_price: this.roundPriceForAlpaca(stopPrice),
|
|
20557
|
+
stop_price: this.roundPriceForAlpaca(stopPrice).toString(),
|
|
20424
20558
|
time_in_force: 'gtc',
|
|
20425
20559
|
};
|
|
20426
|
-
if (
|
|
20427
|
-
body.limit_price = this.roundPriceForAlpaca(limitPrice);
|
|
20560
|
+
if (limitPrice !== undefined) {
|
|
20561
|
+
body.limit_price = this.roundPriceForAlpaca(limitPrice).toString();
|
|
20428
20562
|
}
|
|
20429
20563
|
if (client_order_id !== undefined) {
|
|
20430
20564
|
body.client_order_id = client_order_id;
|
|
20431
20565
|
}
|
|
20432
|
-
|
|
20433
|
-
|
|
20434
|
-
|
|
20435
|
-
|
|
20436
|
-
this.log(`Error creating ${orderType} order: ${error}`, {
|
|
20437
|
-
symbol,
|
|
20438
|
-
type: 'error',
|
|
20439
|
-
});
|
|
20440
|
-
throw error;
|
|
20441
|
-
}
|
|
20566
|
+
return this.makeRequest('/orders', 'POST', body, '', {
|
|
20567
|
+
action: `Create ${orderType} order`,
|
|
20568
|
+
symbol,
|
|
20569
|
+
});
|
|
20442
20570
|
}
|
|
20443
20571
|
/**
|
|
20444
20572
|
* Create a market order
|
|
@@ -20464,13 +20592,10 @@ class AlpacaTradingAPI {
|
|
|
20464
20592
|
if (client_order_id !== undefined) {
|
|
20465
20593
|
body.client_order_id = client_order_id;
|
|
20466
20594
|
}
|
|
20467
|
-
|
|
20468
|
-
|
|
20469
|
-
|
|
20470
|
-
|
|
20471
|
-
this.log(`Error creating market order: ${error}`, { type: 'error' });
|
|
20472
|
-
throw error;
|
|
20473
|
-
}
|
|
20595
|
+
return this.makeRequest('/orders', 'POST', body, '', {
|
|
20596
|
+
action: 'Create market order',
|
|
20597
|
+
symbol,
|
|
20598
|
+
});
|
|
20474
20599
|
}
|
|
20475
20600
|
/**
|
|
20476
20601
|
* Create a Market on Open (MOO) order - executes in the opening auction
|
|
@@ -20504,13 +20629,10 @@ class AlpacaTradingAPI {
|
|
|
20504
20629
|
if (client_order_id !== undefined) {
|
|
20505
20630
|
body.client_order_id = client_order_id;
|
|
20506
20631
|
}
|
|
20507
|
-
|
|
20508
|
-
|
|
20509
|
-
|
|
20510
|
-
|
|
20511
|
-
this.log(`Error creating MOO order: ${error}`, { type: 'error' });
|
|
20512
|
-
throw error;
|
|
20513
|
-
}
|
|
20632
|
+
return this.makeRequest('/orders', 'POST', body, '', {
|
|
20633
|
+
action: 'Create market on open order',
|
|
20634
|
+
symbol,
|
|
20635
|
+
});
|
|
20514
20636
|
}
|
|
20515
20637
|
/**
|
|
20516
20638
|
* Create a Market on Close (MOC) order - executes in the closing auction
|
|
@@ -20544,13 +20666,10 @@ class AlpacaTradingAPI {
|
|
|
20544
20666
|
if (client_order_id !== undefined) {
|
|
20545
20667
|
body.client_order_id = client_order_id;
|
|
20546
20668
|
}
|
|
20547
|
-
|
|
20548
|
-
|
|
20549
|
-
|
|
20550
|
-
|
|
20551
|
-
this.log(`Error creating MOC order: ${error}`, { type: 'error' });
|
|
20552
|
-
throw error;
|
|
20553
|
-
}
|
|
20669
|
+
return this.makeRequest('/orders', 'POST', body, '', {
|
|
20670
|
+
action: 'Create market on close order',
|
|
20671
|
+
symbol,
|
|
20672
|
+
});
|
|
20554
20673
|
}
|
|
20555
20674
|
/**
|
|
20556
20675
|
* Create an OCO (One-Cancels-Other) order with take profit and stop loss
|
|
@@ -20576,32 +20695,29 @@ class AlpacaTradingAPI {
|
|
|
20576
20695
|
position_intent,
|
|
20577
20696
|
order_class: 'oco',
|
|
20578
20697
|
type: 'limit',
|
|
20579
|
-
limit_price: this.roundPriceForAlpaca(limitPrice),
|
|
20698
|
+
limit_price: this.roundPriceForAlpaca(limitPrice).toString(),
|
|
20580
20699
|
time_in_force: 'gtc',
|
|
20581
20700
|
take_profit: {
|
|
20582
|
-
limit_price: this.roundPriceForAlpaca(takeProfitPrice),
|
|
20701
|
+
limit_price: this.roundPriceForAlpaca(takeProfitPrice).toString(),
|
|
20583
20702
|
},
|
|
20584
20703
|
stop_loss: {
|
|
20585
|
-
stop_price: this.roundPriceForAlpaca(stopLossPrice),
|
|
20704
|
+
stop_price: this.roundPriceForAlpaca(stopLossPrice).toString(),
|
|
20586
20705
|
},
|
|
20587
20706
|
};
|
|
20588
20707
|
// If stop loss limit price is provided, create stop-limit order
|
|
20589
20708
|
if (stopLossLimitPrice !== undefined) {
|
|
20590
|
-
body.stop_loss
|
|
20709
|
+
body.stop_loss = {
|
|
20710
|
+
stop_price: this.roundPriceForAlpaca(stopLossPrice).toString(),
|
|
20711
|
+
limit_price: this.roundPriceForAlpaca(stopLossLimitPrice).toString(),
|
|
20712
|
+
};
|
|
20591
20713
|
}
|
|
20592
20714
|
if (client_order_id !== undefined) {
|
|
20593
20715
|
body.client_order_id = client_order_id;
|
|
20594
20716
|
}
|
|
20595
|
-
|
|
20596
|
-
|
|
20597
|
-
|
|
20598
|
-
|
|
20599
|
-
this.log(`Error creating OCO order: ${error}`, {
|
|
20600
|
-
symbol,
|
|
20601
|
-
type: 'error',
|
|
20602
|
-
});
|
|
20603
|
-
throw error;
|
|
20604
|
-
}
|
|
20717
|
+
return this.makeRequest('/orders', 'POST', body, '', {
|
|
20718
|
+
action: 'Create OCO order',
|
|
20719
|
+
symbol,
|
|
20720
|
+
});
|
|
20605
20721
|
}
|
|
20606
20722
|
/**
|
|
20607
20723
|
* Get the current trail percent for a symbol, assuming that it has an open position and a trailing stop order to close it. Because this relies on an orders request for one symbol, you can't do it too often.
|
|
@@ -20609,35 +20725,26 @@ class AlpacaTradingAPI {
|
|
|
20609
20725
|
* @returns the current trail percent
|
|
20610
20726
|
*/
|
|
20611
20727
|
async getCurrentTrailPercent(symbol) {
|
|
20612
|
-
|
|
20613
|
-
|
|
20614
|
-
|
|
20615
|
-
|
|
20728
|
+
const orders = await this.getOrders({
|
|
20729
|
+
status: 'open',
|
|
20730
|
+
symbols: [symbol],
|
|
20731
|
+
});
|
|
20732
|
+
const trailingStopOrder = orders.find((order) => order.type === 'trailing_stop' &&
|
|
20733
|
+
(order.position_intent === 'sell_to_close' || order.position_intent === 'buy_to_close'));
|
|
20734
|
+
if (!trailingStopOrder) {
|
|
20735
|
+
this.log(`No closing trailing stop order found for ${symbol}`, {
|
|
20736
|
+
symbol,
|
|
20616
20737
|
});
|
|
20617
|
-
|
|
20618
|
-
(order.position_intent === 'sell_to_close' || order.position_intent === 'buy_to_close'));
|
|
20619
|
-
if (!trailingStopOrder) {
|
|
20620
|
-
this.log(`No closing trailing stop order found for ${symbol}`, {
|
|
20621
|
-
symbol,
|
|
20622
|
-
});
|
|
20623
|
-
return null;
|
|
20624
|
-
}
|
|
20625
|
-
if (!trailingStopOrder.trail_percent) {
|
|
20626
|
-
this.log(`Trailing stop order found for ${symbol} but no trail_percent value`, {
|
|
20627
|
-
symbol,
|
|
20628
|
-
});
|
|
20629
|
-
return null;
|
|
20630
|
-
}
|
|
20631
|
-
const trailPercent = parseFloat(trailingStopOrder.trail_percent);
|
|
20632
|
-
return trailPercent;
|
|
20738
|
+
return null;
|
|
20633
20739
|
}
|
|
20634
|
-
|
|
20635
|
-
this.log(`
|
|
20740
|
+
if (!trailingStopOrder.trail_percent) {
|
|
20741
|
+
this.log(`Trailing stop order found for ${symbol} but no trail_percent value`, {
|
|
20636
20742
|
symbol,
|
|
20637
|
-
type: 'error',
|
|
20638
20743
|
});
|
|
20639
|
-
|
|
20744
|
+
return null;
|
|
20640
20745
|
}
|
|
20746
|
+
const trailPercent = parseFloat(trailingStopOrder.trail_percent);
|
|
20747
|
+
return trailPercent;
|
|
20641
20748
|
}
|
|
20642
20749
|
/**
|
|
20643
20750
|
* Update the trail percent for a trailing stop order
|
|
@@ -20669,18 +20776,10 @@ class AlpacaTradingAPI {
|
|
|
20669
20776
|
this.log(`Updating trailing stop for ${symbol} from ${currentTrailPercent}% to ${trailPercent100}%`, {
|
|
20670
20777
|
symbol,
|
|
20671
20778
|
});
|
|
20672
|
-
|
|
20673
|
-
|
|
20674
|
-
|
|
20675
|
-
|
|
20676
|
-
}
|
|
20677
|
-
catch (error) {
|
|
20678
|
-
this.log(`Error updating trailing stop: ${error}`, {
|
|
20679
|
-
symbol,
|
|
20680
|
-
type: 'error',
|
|
20681
|
-
});
|
|
20682
|
-
throw error;
|
|
20683
|
-
}
|
|
20779
|
+
await this.makeRequest(`/orders/${trailingStopOrder.id}`, 'PATCH', { trail: trailPercent100.toString() }, '', {
|
|
20780
|
+
action: 'Update trailing stop order',
|
|
20781
|
+
symbol,
|
|
20782
|
+
});
|
|
20684
20783
|
}
|
|
20685
20784
|
/**
|
|
20686
20785
|
* Cancel all open orders
|
|
@@ -20688,10 +20787,16 @@ class AlpacaTradingAPI {
|
|
|
20688
20787
|
async cancelAllOrders() {
|
|
20689
20788
|
this.log(`Canceling all open orders`);
|
|
20690
20789
|
try {
|
|
20691
|
-
await this.makeRequest('/orders', 'DELETE'
|
|
20790
|
+
await this.makeRequest('/orders', 'DELETE', undefined, '', {
|
|
20791
|
+
action: 'Cancel all open orders',
|
|
20792
|
+
});
|
|
20692
20793
|
}
|
|
20693
20794
|
catch (error) {
|
|
20694
|
-
|
|
20795
|
+
if (!(error instanceof AlpacaRequestError)) {
|
|
20796
|
+
this.log(`Error canceling all orders: ${error instanceof Error ? error.message : `${error}`}`, {
|
|
20797
|
+
type: 'error',
|
|
20798
|
+
});
|
|
20799
|
+
}
|
|
20695
20800
|
}
|
|
20696
20801
|
}
|
|
20697
20802
|
/**
|
|
@@ -20703,15 +20808,14 @@ class AlpacaTradingAPI {
|
|
|
20703
20808
|
async cancelOrder(orderId) {
|
|
20704
20809
|
this.log(`Attempting to cancel order ${orderId}`);
|
|
20705
20810
|
try {
|
|
20706
|
-
await this.makeRequest(`/orders/${orderId}`, 'DELETE'
|
|
20811
|
+
await this.makeRequest(`/orders/${orderId}`, 'DELETE', undefined, '', {
|
|
20812
|
+
action: `Cancel order ${orderId}`,
|
|
20813
|
+
});
|
|
20707
20814
|
this.log(`Successfully canceled order ${orderId}`);
|
|
20708
20815
|
}
|
|
20709
20816
|
catch (error) {
|
|
20710
20817
|
// If the error is a 422, it means the order is not cancelable
|
|
20711
|
-
if (error instanceof
|
|
20712
|
-
this.log(`Order ${orderId} is not cancelable`, {
|
|
20713
|
-
type: 'error',
|
|
20714
|
-
});
|
|
20818
|
+
if (error instanceof AlpacaRequestError && error.status === 422) {
|
|
20715
20819
|
throw new Error(`Order ${orderId} is not cancelable`);
|
|
20716
20820
|
}
|
|
20717
20821
|
// Re-throw other errors
|
|
@@ -20746,13 +20850,10 @@ class AlpacaTradingAPI {
|
|
|
20746
20850
|
if (client_order_id !== undefined) {
|
|
20747
20851
|
body.client_order_id = client_order_id;
|
|
20748
20852
|
}
|
|
20749
|
-
|
|
20750
|
-
|
|
20751
|
-
|
|
20752
|
-
|
|
20753
|
-
this.log(`Error creating limit order: ${error}`, { type: 'error' });
|
|
20754
|
-
throw error;
|
|
20755
|
-
}
|
|
20853
|
+
return this.makeRequest('/orders', 'POST', body, '', {
|
|
20854
|
+
action: 'Create limit order',
|
|
20855
|
+
symbol,
|
|
20856
|
+
});
|
|
20756
20857
|
}
|
|
20757
20858
|
/**
|
|
20758
20859
|
* Close all equities positions
|
|
@@ -20818,7 +20919,9 @@ class AlpacaTradingAPI {
|
|
|
20818
20919
|
}
|
|
20819
20920
|
}
|
|
20820
20921
|
else {
|
|
20821
|
-
await this.makeRequest('/positions', 'DELETE', undefined, options.cancel_orders ? '?cancel_orders=true' : ''
|
|
20922
|
+
await this.makeRequest('/positions', 'DELETE', undefined, options.cancel_orders ? '?cancel_orders=true' : '', {
|
|
20923
|
+
action: 'Close all positions',
|
|
20924
|
+
});
|
|
20822
20925
|
}
|
|
20823
20926
|
}
|
|
20824
20927
|
/**
|
|
@@ -20897,7 +21000,9 @@ class AlpacaTradingAPI {
|
|
|
20897
21000
|
queryParams.append('end', params.end);
|
|
20898
21001
|
if (params.date_end)
|
|
20899
21002
|
queryParams.append('date_end', params.date_end);
|
|
20900
|
-
const response = await this.makeRequest(`/account/portfolio/history?${queryParams.toString()}
|
|
21003
|
+
const response = await this.makeRequest(`/account/portfolio/history?${queryParams.toString()}`, 'GET', undefined, '', {
|
|
21004
|
+
action: 'Get portfolio history',
|
|
21005
|
+
});
|
|
20901
21006
|
return response;
|
|
20902
21007
|
}
|
|
20903
21008
|
/**
|
|
@@ -20988,7 +21093,10 @@ class AlpacaTradingAPI {
|
|
|
20988
21093
|
this.log(`Fetching option contracts for ${params.underlying_symbols.join(', ')}`, {
|
|
20989
21094
|
symbol: params.underlying_symbols.join(', '),
|
|
20990
21095
|
});
|
|
20991
|
-
const response =
|
|
21096
|
+
const response = await this.makeRequest(`/options/contracts?${queryParams.toString()}`, 'GET', undefined, '', {
|
|
21097
|
+
action: 'Get option contracts',
|
|
21098
|
+
symbol: params.underlying_symbols.join(', '),
|
|
21099
|
+
});
|
|
20992
21100
|
this.log(`Found ${response.option_contracts.length} option contracts`, {
|
|
20993
21101
|
symbol: params.underlying_symbols.join(', '),
|
|
20994
21102
|
});
|
|
@@ -21003,7 +21111,10 @@ class AlpacaTradingAPI {
|
|
|
21003
21111
|
this.log(`Fetching option contract details for ${symbolOrId}`, {
|
|
21004
21112
|
symbol: symbolOrId,
|
|
21005
21113
|
});
|
|
21006
|
-
const response =
|
|
21114
|
+
const response = await this.makeRequest(`/options/contracts/${symbolOrId}`, 'GET', undefined, '', {
|
|
21115
|
+
action: 'Get option contract details',
|
|
21116
|
+
symbol: symbolOrId,
|
|
21117
|
+
});
|
|
21007
21118
|
this.log(`Found option contract details for ${symbolOrId}: ${response.name}`, {
|
|
21008
21119
|
symbol: symbolOrId,
|
|
21009
21120
|
});
|
|
@@ -21021,10 +21132,10 @@ class AlpacaTradingAPI {
|
|
|
21021
21132
|
*/
|
|
21022
21133
|
async createOptionOrder(symbol, qty, side, position_intent, type, limitPrice) {
|
|
21023
21134
|
if (!Number.isInteger(qty) || qty <= 0) {
|
|
21024
|
-
this.log('Quantity must be a positive whole number for option orders', { type: 'error' });
|
|
21135
|
+
this.log('Quantity must be a positive whole number for option orders', { symbol, type: 'error' });
|
|
21025
21136
|
}
|
|
21026
21137
|
if (type === 'limit' && limitPrice === undefined) {
|
|
21027
|
-
this.log('Limit price is required for limit orders', { type: 'error' });
|
|
21138
|
+
this.log('Limit price is required for limit orders', { symbol, type: 'error' });
|
|
21028
21139
|
}
|
|
21029
21140
|
this.log(`Creating ${type} option order for ${symbol}: ${side} ${qty} contracts (${position_intent})${type === 'limit' ? ` at $${limitPrice?.toFixed(2)}` : ''}`, {
|
|
21030
21141
|
symbol,
|
|
@@ -21042,7 +21153,10 @@ class AlpacaTradingAPI {
|
|
|
21042
21153
|
if (type === 'limit' && limitPrice !== undefined) {
|
|
21043
21154
|
orderData.limit_price = this.roundPriceForAlpaca(limitPrice).toString();
|
|
21044
21155
|
}
|
|
21045
|
-
return this.makeRequest('/orders', 'POST', orderData
|
|
21156
|
+
return this.makeRequest('/orders', 'POST', orderData, '', {
|
|
21157
|
+
action: 'Create option order',
|
|
21158
|
+
symbol,
|
|
21159
|
+
});
|
|
21046
21160
|
}
|
|
21047
21161
|
/**
|
|
21048
21162
|
* Create a multi-leg option order
|
|
@@ -21053,16 +21167,19 @@ class AlpacaTradingAPI {
|
|
|
21053
21167
|
* @returns The created multi-leg order
|
|
21054
21168
|
*/
|
|
21055
21169
|
async createMultiLegOptionOrder(legs, qty, type, limitPrice) {
|
|
21170
|
+
const legSymbols = legs.map((leg) => leg.symbol).join(', ');
|
|
21056
21171
|
if (!Number.isInteger(qty) || qty <= 0) {
|
|
21057
|
-
this.log('Quantity must be a positive whole number for option orders', {
|
|
21172
|
+
this.log('Quantity must be a positive whole number for option orders', {
|
|
21173
|
+
symbol: legSymbols,
|
|
21174
|
+
type: 'error',
|
|
21175
|
+
});
|
|
21058
21176
|
}
|
|
21059
21177
|
if (type === 'limit' && limitPrice === undefined) {
|
|
21060
|
-
this.log('Limit price is required for limit orders', { type: 'error' });
|
|
21178
|
+
this.log('Limit price is required for limit orders', { symbol: legSymbols, type: 'error' });
|
|
21061
21179
|
}
|
|
21062
21180
|
if (legs.length < 2) {
|
|
21063
|
-
this.log('Multi-leg orders require at least 2 legs', { type: 'error' });
|
|
21181
|
+
this.log('Multi-leg orders require at least 2 legs', { symbol: legSymbols, type: 'error' });
|
|
21064
21182
|
}
|
|
21065
|
-
const legSymbols = legs.map((leg) => leg.symbol).join(', ');
|
|
21066
21183
|
this.log(`Creating multi-leg ${type} option order with ${legs.length} legs (${legSymbols})${type === 'limit' ? ` at $${limitPrice?.toFixed(2)}` : ''}`, {
|
|
21067
21184
|
symbol: legSymbols,
|
|
21068
21185
|
});
|
|
@@ -21076,7 +21193,10 @@ class AlpacaTradingAPI {
|
|
|
21076
21193
|
if (type === 'limit' && limitPrice !== undefined) {
|
|
21077
21194
|
orderData.limit_price = this.roundPriceForAlpaca(limitPrice).toString();
|
|
21078
21195
|
}
|
|
21079
|
-
return this.makeRequest('/orders', 'POST', orderData
|
|
21196
|
+
return this.makeRequest('/orders', 'POST', orderData, '', {
|
|
21197
|
+
action: 'Create multi-leg option order',
|
|
21198
|
+
symbol: legSymbols,
|
|
21199
|
+
});
|
|
21080
21200
|
}
|
|
21081
21201
|
/**
|
|
21082
21202
|
* Exercise an option contract
|
|
@@ -21087,7 +21207,10 @@ class AlpacaTradingAPI {
|
|
|
21087
21207
|
this.log(`Exercising option contract ${symbolOrContractId}`, {
|
|
21088
21208
|
symbol: symbolOrContractId,
|
|
21089
21209
|
});
|
|
21090
|
-
return this.makeRequest(`/positions/${symbolOrContractId}/exercise`, 'POST'
|
|
21210
|
+
return this.makeRequest(`/positions/${symbolOrContractId}/exercise`, 'POST', undefined, '', {
|
|
21211
|
+
action: 'Exercise option contract',
|
|
21212
|
+
symbol: symbolOrContractId,
|
|
21213
|
+
});
|
|
21091
21214
|
}
|
|
21092
21215
|
/**
|
|
21093
21216
|
* Get option positions
|
|
@@ -21123,7 +21246,9 @@ class AlpacaTradingAPI {
|
|
|
21123
21246
|
queryParams.append('date', date);
|
|
21124
21247
|
}
|
|
21125
21248
|
this.log(`Fetching option activities${activityType ? ` of type ${activityType}` : ''}${date ? ` for date ${date}` : ''}`);
|
|
21126
|
-
return this.makeRequest(`/account/activities?${queryParams.toString()}
|
|
21249
|
+
return this.makeRequest(`/account/activities?${queryParams.toString()}`, 'GET', undefined, '', {
|
|
21250
|
+
action: 'Get option activities',
|
|
21251
|
+
});
|
|
21127
21252
|
}
|
|
21128
21253
|
/**
|
|
21129
21254
|
* Create a long call spread (buy lower strike call, sell higher strike call)
|
|
@@ -21221,13 +21346,7 @@ class AlpacaTradingAPI {
|
|
|
21221
21346
|
position_intent: 'buy_to_open',
|
|
21222
21347
|
},
|
|
21223
21348
|
];
|
|
21224
|
-
|
|
21225
|
-
return await this.createMultiLegOptionOrder(legs, qty, 'limit', limitPrice);
|
|
21226
|
-
}
|
|
21227
|
-
catch (error) {
|
|
21228
|
-
this.log(`Error creating iron condor: ${error}`, { type: 'error' });
|
|
21229
|
-
throw error;
|
|
21230
|
-
}
|
|
21349
|
+
return this.createMultiLegOptionOrder(legs, qty, 'limit', limitPrice);
|
|
21231
21350
|
}
|
|
21232
21351
|
/**
|
|
21233
21352
|
* Create a covered call (sell call option against owned stock)
|
|
@@ -21243,13 +21362,7 @@ class AlpacaTradingAPI {
|
|
|
21243
21362
|
});
|
|
21244
21363
|
// For covered calls, we don't need to include the stock leg if we already own the shares
|
|
21245
21364
|
// We just create a simple sell order for the call option
|
|
21246
|
-
|
|
21247
|
-
return await this.createOptionOrder(callOptionSymbol, qty, 'sell', 'sell_to_open', 'limit', limitPrice);
|
|
21248
|
-
}
|
|
21249
|
-
catch (error) {
|
|
21250
|
-
this.log(`Error creating covered call: ${error}`, { type: 'error' });
|
|
21251
|
-
throw error;
|
|
21252
|
-
}
|
|
21365
|
+
return this.createOptionOrder(callOptionSymbol, qty, 'sell', 'sell_to_open', 'limit', limitPrice);
|
|
21253
21366
|
}
|
|
21254
21367
|
/**
|
|
21255
21368
|
* Roll an option position to a new expiration or strike
|
|
@@ -21284,13 +21397,7 @@ class AlpacaTradingAPI {
|
|
|
21284
21397
|
position_intent: openPositionIntent,
|
|
21285
21398
|
},
|
|
21286
21399
|
];
|
|
21287
|
-
|
|
21288
|
-
return await this.createMultiLegOptionOrder(legs, qty, 'limit', limitPrice);
|
|
21289
|
-
}
|
|
21290
|
-
catch (error) {
|
|
21291
|
-
this.log(`Error rolling option position: ${error}`, { type: 'error' });
|
|
21292
|
-
throw error;
|
|
21293
|
-
}
|
|
21400
|
+
return this.createMultiLegOptionOrder(legs, qty, 'limit', limitPrice);
|
|
21294
21401
|
}
|
|
21295
21402
|
/**
|
|
21296
21403
|
* Get option chain for a specific underlying symbol and expiration date
|
|
@@ -21314,10 +21421,12 @@ class AlpacaTradingAPI {
|
|
|
21314
21421
|
return response.option_contracts || [];
|
|
21315
21422
|
}
|
|
21316
21423
|
catch (error) {
|
|
21317
|
-
|
|
21318
|
-
|
|
21319
|
-
|
|
21320
|
-
|
|
21424
|
+
if (!(error instanceof AlpacaRequestError)) {
|
|
21425
|
+
this.log(`Failed to fetch option chain for ${underlyingSymbol}: ${error instanceof Error ? error.message : `${error}`}`, {
|
|
21426
|
+
type: 'error',
|
|
21427
|
+
symbol: underlyingSymbol,
|
|
21428
|
+
});
|
|
21429
|
+
}
|
|
21321
21430
|
return [];
|
|
21322
21431
|
}
|
|
21323
21432
|
}
|
|
@@ -21348,10 +21457,12 @@ class AlpacaTradingAPI {
|
|
|
21348
21457
|
return Array.from(expirationDates).sort();
|
|
21349
21458
|
}
|
|
21350
21459
|
catch (error) {
|
|
21351
|
-
|
|
21352
|
-
|
|
21353
|
-
|
|
21354
|
-
|
|
21460
|
+
if (!(error instanceof AlpacaRequestError)) {
|
|
21461
|
+
this.log(`Failed to fetch expiration dates for ${underlyingSymbol}: ${error instanceof Error ? error.message : `${error}`}`, {
|
|
21462
|
+
type: 'error',
|
|
21463
|
+
symbol: underlyingSymbol,
|
|
21464
|
+
});
|
|
21465
|
+
}
|
|
21355
21466
|
return [];
|
|
21356
21467
|
}
|
|
21357
21468
|
}
|
|
@@ -21410,7 +21521,10 @@ class AlpacaTradingAPI {
|
|
|
21410
21521
|
this.log(`Canceling open order for ${order.symbol}`, {
|
|
21411
21522
|
symbol: order.symbol,
|
|
21412
21523
|
});
|
|
21413
|
-
await this.makeRequest(`/orders/${order.id}`, 'DELETE'
|
|
21524
|
+
await this.makeRequest(`/orders/${order.id}`, 'DELETE', undefined, '', {
|
|
21525
|
+
action: `Cancel option order ${order.id}`,
|
|
21526
|
+
symbol: order.symbol,
|
|
21527
|
+
});
|
|
21414
21528
|
}
|
|
21415
21529
|
}
|
|
21416
21530
|
}
|
|
@@ -21433,13 +21547,7 @@ class AlpacaTradingAPI {
|
|
|
21433
21547
|
const quantityToClose = qty || parseInt(position.qty);
|
|
21434
21548
|
const side = position.side === 'long' ? 'sell' : 'buy';
|
|
21435
21549
|
const positionIntent = side === 'sell' ? 'sell_to_close' : 'buy_to_close';
|
|
21436
|
-
|
|
21437
|
-
return await this.createOptionOrder(symbol, quantityToClose, side, positionIntent, 'market');
|
|
21438
|
-
}
|
|
21439
|
-
catch (error) {
|
|
21440
|
-
this.log(`Error closing option position: ${error}`, { type: 'error' });
|
|
21441
|
-
throw error;
|
|
21442
|
-
}
|
|
21550
|
+
return this.createOptionOrder(symbol, quantityToClose, side, positionIntent, 'market');
|
|
21443
21551
|
}
|
|
21444
21552
|
/**
|
|
21445
21553
|
* Create a complete equities trade with optional stop loss and take profit
|
|
@@ -21574,16 +21682,10 @@ class AlpacaTradingAPI {
|
|
|
21574
21682
|
this.log(logMessage, {
|
|
21575
21683
|
symbol,
|
|
21576
21684
|
});
|
|
21577
|
-
|
|
21578
|
-
|
|
21579
|
-
|
|
21580
|
-
|
|
21581
|
-
this.log(`Error creating equities trade: ${error}`, {
|
|
21582
|
-
symbol,
|
|
21583
|
-
type: 'error',
|
|
21584
|
-
});
|
|
21585
|
-
throw error;
|
|
21586
|
-
}
|
|
21685
|
+
return this.makeRequest('/orders', 'POST', orderData, '', {
|
|
21686
|
+
action: 'Create equities trade',
|
|
21687
|
+
symbol,
|
|
21688
|
+
});
|
|
21587
21689
|
}
|
|
21588
21690
|
}
|
|
21589
21691
|
|