diff --git a/src/alpaca/exchange.ts b/src/alpaca/exchange.ts index 56748c5..2edca77 100644 --- a/src/alpaca/exchange.ts +++ b/src/alpaca/exchange.ts @@ -1,9 +1,26 @@ import Alpaca from '@alpacahq/alpaca-trade-api' +import { AlpacaPortfolioProvider } from './portfolio' +import { AlpacaQuoteProvider } from './quote' import { Exchange } from '../interface/exchange' +import { PortfolioProvider } from '../interface/portfolio' +import { QuoteProvider } from '../interface/quote' export class AlpacaExchange implements Exchange { readonly alpaca: Alpaca; + /** + * The portfolio provider for the exchange. + */ + readonly portfolioProvider: PortfolioProvider; + + /** + * The quote provider for the exchange. + */ + readonly quoteProvider: QuoteProvider; + + /** + * The name of the exchange. + */ readonly name: string; constructor(keyId: string, secretKey: string, paper: boolean) { @@ -13,6 +30,9 @@ export class AlpacaExchange implements Exchange { paper: paper }); + this.portfolioProvider = new AlpacaPortfolioProvider(this.alpaca); + this.quoteProvider = new AlpacaQuoteProvider(this.alpaca); + this.name = 'Alpaca'; } -} \ No newline at end of file +} diff --git a/src/alpaca/portfolio.ts b/src/alpaca/portfolio.ts new file mode 100644 index 0000000..f21102a --- /dev/null +++ b/src/alpaca/portfolio.ts @@ -0,0 +1,45 @@ +import Alpaca from '@alpacahq/alpaca-trade-api' +import { PortfolioProvider, Portfolio, Position } from '../interface/portfolio'; + +class AlpacaPosition { + asset_id!: string; + symbol!: string; + exchange!: string; + asset_class!: string; + avg_entry_price!: string; + qty!: string; + qty_available!: string; + side!: string; + market_value!: string; + cost_basis!: string; + unrealized_pl!: string; + unrealized_plpc!: string; + unrealized_intraday_pl!: string; + unrealized_intraday_plpc!: string; + current_price!: string; + lastday_price!: string; + change_today!: string; + asset_marginable!: string; +} + +export class AlpacaPortfolioProvider implements PortfolioProvider { + readonly alpaca: Alpaca; + + readonly fetchPortfolio = (): Promise => { + return (this.alpaca.getPositions() as Promise).then((positions) => { + return new Portfolio(positions.map((position) => { + return new Position( + position.symbol, + parseInt(position.qty, 10), + parseFloat(position.market_value), + parseFloat(position.cost_basis), + parseFloat(position.market_value) + ); + })); + }); + } + + constructor(alpaca: Alpaca) { + this.alpaca = alpaca; + } +} diff --git a/src/alpaca/quote.ts b/src/alpaca/quote.ts new file mode 100644 index 0000000..df8eab9 --- /dev/null +++ b/src/alpaca/quote.ts @@ -0,0 +1,25 @@ +import Alpaca from '@alpacahq/alpaca-trade-api' +import { QuoteProvider, Quote } from '../interface/quote'; + +export class AlpacaQuoteProvider implements QuoteProvider { + readonly alpaca: Alpaca; + + readonly fetchQuote = (symbol: string): Promise => { + return this.alpaca.getLatestQuote(symbol).then((quote) => { + return new Quote( + quote.Symbol, + quote.AskPrice, + quote.AskSize, + quote.BidPrice, + quote.BidSize, + new Date(Date.parse(quote.Timestamp)) + ); + }).catch((err) => { + return err; + }) + } + + constructor(alpaca: Alpaca) { + this.alpaca = alpaca; + } +} diff --git a/src/index.ts b/src/index.ts index 8679f1c..683b750 100644 --- a/src/index.ts +++ b/src/index.ts @@ -9,4 +9,4 @@ export { PortfolioProvider, Quote, QuoteProvider -} \ No newline at end of file +} diff --git a/src/interface/exchange.ts b/src/interface/exchange.ts index a396215..cb659fb 100644 --- a/src/interface/exchange.ts +++ b/src/interface/exchange.ts @@ -20,4 +20,4 @@ export interface Exchange { * The name of the exchange. */ readonly name: string; -} \ No newline at end of file +} diff --git a/src/interface/portfolio.ts b/src/interface/portfolio.ts index f65e153..1b06baa 100644 --- a/src/interface/portfolio.ts +++ b/src/interface/portfolio.ts @@ -3,67 +3,46 @@ */ export class Position { /** - * The price of the last trade made for this position. - */ - readonly lastTrade: number; - - /** - * The date and time of the last trade made for this position. - */ - readonly lastTradeTime: Date; - - /** - * The change in the position value. - */ - readonly change: number; - - /** - * The percentage change in the position value. - */ - readonly changePercent: number; - - /** - * The earnings per share of the position. - */ - readonly earningsPerShare: number; - - /** - * The market capitalization of the position. - */ - readonly marketCap: number; - - /** - * The symbol of the position. + * The symbol name of the asset */ readonly symbol: string; /** - * Represents a position in a portfolio. - * @constructor - * @param {number} lastTrade - The price of the last trade made for this position. - * @param {Date} lastTradeTime - The date and time of the last trade made for this position. - * @param {number} change - The change in the position value. - * @param {number} changePercent - The percentage change in the position value. - * @param {number} earningsPerShare - The earnings per share of the position. - * @param {number} marketCap - The market capitalization of the position. - * @param {string} symbol - The symbol of the position. + * The total number of shares, not including open orders */ - constructor( - lastTrade: number, - lastTradeTime: Date, - change: number, - changePercent: number, - earningsPerShare: number, - marketCap: number, - symbol: string - ) { - this.lastTrade = lastTrade; - this.lastTradeTime = lastTradeTime; - this.change = change; - this.changePercent = changePercent; - this.earningsPerShare = earningsPerShare; - this.marketCap = marketCap; + readonly quantity: number; + + /** + * The total dollar amount of the position + */ + readonly marketValue: number; + + /** + * The total cost basis + */ + readonly costBasis: number; + + /** + * The current asset price per share + */ + readonly pricePerShare: number; + + + /** + * Creates a new Portfolio object. + * @constructor + * @param {string} symbol - The symbol of the asset in the portfolio. + * @param {number} quantity - The quantity of the asset in the portfolio. + * @param {number} marketValue - The market value of the asset in the portfolio. + * @param {number} costBasis - The cost basis of the asset in the portfolio. + * @param {number} pricePerShare - The price per share of the asset in the portfolio. + */ + constructor(symbol: string, quantity: number, marketValue: number, costBasis: number, pricePerShare: number) { this.symbol = symbol; + this.quantity = quantity; + this.marketValue = marketValue; + this.costBasis = costBasis; + this.pricePerShare = pricePerShare; } } diff --git a/src/interface/quote.ts b/src/interface/quote.ts index 62b32e0..4449bb8 100644 --- a/src/interface/quote.ts +++ b/src/interface/quote.ts @@ -2,52 +2,20 @@ * Represents a stock quote. */ export class Quote { - /** - * The name of the company associated with this quote. - */ - readonly companyName: string; - - /** - * The earnings per share of a company. - */ - readonly earningsPerShare: number; - - /** - * The estimated earnings for a stock. - */ - readonly estimatedEarnings: number; - - /** - * The price of the last trade for the security. - */ - readonly lastTrade: number; - - /** - * The symbol of the financial instrument being quoted. - */ readonly symbol: string; + readonly askPrice: number; + readonly askSize: number; + readonly bidPrice: number; + readonly bidSize: number; + readonly timeStamp: Date; - /** - * Represents a quote for a particular stock. - * @constructor - * @param {string} companyName - The name of the company associated with the stock. - * @param {number} earningsPerShare - The earnings per share for the stock. - * @param {number} estimatedEarnings - The estimated earnings for the stock. - * @param {number} lastTrade - The last trade price for the stock. - * @param {string} symbol - The symbol for the stock. - */ - constructor( - companyName: string, - earningsPerShare: number, - estimatedEarnings: number, - lastTrade: number, - symbol: string - ) { - this.companyName = companyName; - this.earningsPerShare = earningsPerShare; - this.estimatedEarnings = estimatedEarnings; - this.lastTrade = lastTrade; + constructor(symbol: string, askPrice: number, askSize: number, bidPrice: number, bidSize: number, timeStamp: Date) { this.symbol = symbol; + this.askPrice = askPrice; + this.askSize = askSize; + this.bidPrice = bidPrice; + this.bidSize = bidSize; + this.timeStamp = timeStamp; } }