diff --git a/docs/ROBINHOOD.md b/docs/ROBINHOOD.md index 74941b3..0396a96 100755 --- a/docs/ROBINHOOD.md +++ b/docs/ROBINHOOD.md @@ -1432,6 +1432,7 @@ Represents the user that is logged in while accessing the Robinhood API. * [.cancelOpenOrders()](#User+cancelOpenOrders) ⇒ Promise * [.getOptionOrders()](#User+getOptionOrders) ⇒ Promise.<Array> * [.getPortfolio()](#User+getPortfolio) ⇒ Promise.<Object> + * [.getOptionPositions()](#User+getOptionPositions) ⇒ Promise.<any> * [.getHistoricals()](#User+getHistoricals) ⇒ Promise.<Object> * [.getLinkedBanks()](#User+getLinkedBanks) ⇒ Promise.<Object> * [.addDeposit(bankID, amount, frequency)](#User+addDeposit) ⇒ Promise.<Object> @@ -1621,6 +1622,13 @@ Returns an array of option orders. ### user.getPortfolio() ⇒ Promise.<Object> Returns a Portfolio object containing all open positions in a user's portfolio. +**Kind**: instance method of [User](#User) +**Author**: Torrey Leonard + + +### user.getOptionPositions() ⇒ Promise.<any> +Returns an array of options that the user holds. + **Kind**: instance method of [User](#User) **Author**: Torrey Leonard diff --git a/objects/broker/robinhood/OptionOrder.js b/objects/broker/robinhood/OptionOrder.js index 4a943df..1970e10 100755 --- a/objects/broker/robinhood/OptionOrder.js +++ b/objects/broker/robinhood/OptionOrder.js @@ -20,7 +20,8 @@ class OptionOrder extends Robinhood { * @property {String} type - market/limit. Note: market orders are not allowed if side = buy. * @property {Number} price * @property {String} timeInForce - gtc/gfd/ioc/opg - * @property {OptionInstrument} option + * @property {OptionInstrument|Null} option - Required if no legs are provided + * @property {Array|Null} legs - Required if no option is provided * @property {Number} quantity */ constructor(user, object) { @@ -29,15 +30,19 @@ class OptionOrder extends Robinhood { if (object.state === undefined && object.cancel_url === undefined) { // This should be a new order _validate(); this.executed = false; - this.form = { - account: this.url + "/accounts/" + this.user.getAccountNumber() + "/", - direction: object.side === 'buy' ? 'debit' : 'credit', - legs: [{ + let legs = null; + if (!object.legs) { + legs = [{ position_effect: object.side === "buy" ? "open" : "close", side: object.side, ratio_quantity: 1, option: object.option.instrumentURL - }], + }]; + } else legs = object.legs; + this.form = { + account: this.url + "/accounts/" + this.user.getAccountNumber() + "/", + direction: object.side === 'buy' ? 'debit' : 'credit', + legs: legs, price: object.price, time_in_force: object.timeInForce, trigger: 'immediate', @@ -64,7 +69,8 @@ class OptionOrder extends Robinhood { assert(typeof object.price === 'number', new Error("Object property 'price' must be a number")); assert(typeof object.timeInForce === 'string', new Error("Object property 'timeInForce' must be a string")); assert(['gfd', 'gtc', 'ioc', 'opg'].indexOf(object.timeInForce.toLowerCase()) !== -1, new Error("Object property 'timeInForce' must be either GFD, GTC, IOC, or OPG")); - assert(object.option instanceof OptionInstrument, new Error("Object property 'optionInstrument' must be an instance of the OptionInstrument class")); + assert(object.option instanceof OptionInstrument || typeof object.legs !== 'undefined', new Error("Object property 'optionInstrument' must be an instance of the OptionInstrument class")); + assert(Array.isArray(object.legs) || typeof object.option !== 'undefined', new Error("Object property 'legs' must be an array. Required parameter if 'option' is undefined")); assert(typeof object.quantity === 'number', new Error("Object property 'quantity' must be a number")) } } diff --git a/objects/broker/robinhood/User.js b/objects/broker/robinhood/User.js index 7d32422..3c8b4ec 100755 --- a/objects/broker/robinhood/User.js +++ b/objects/broker/robinhood/User.js @@ -4,6 +4,7 @@ const Instrument = require('./Instrument'); const Portfolio = require('./Portfolio'); const Order = require('./Order'); const OptionOrder = require('./OptionOrder'); +const OptionInstrument = require('./OptionInstrument'); const request = require('request'); const fs = require('fs'); @@ -584,6 +585,9 @@ class User extends Robinhood { uri: _this.url + "/accounts/" + _this.account + "/positions/", headers: { 'Authorization': 'Bearer ' + _this.token + }, + qs: { + nonzero: true } }, (error, response, body) => { Robinhood.handleResponse(error, response, body, _this.token, res => { @@ -605,6 +609,40 @@ class User extends Robinhood { }) } + /** + * Returns an array of options that the user holds. + * @author Torrey Leonard + * @returns {Promise} + */ + getOptionPositions() { + const _this = this; + return new Promise((resolve, reject) => { + request({ + uri: _this.url + "/options/positions/", + headers: { + 'Authorization': 'Bearer ' + _this.token + }, + qs: { + nonzero: 'True' + } + }, (error, response, body) => { + Robinhood.handleResponse(error, response, body, _this.token, res => { + if (!Array.isArray(res)) res = [res]; + let array = []; + async.forEachOf(res, (position, key, callback) => { + OptionInstrument.getByURL(_this, position.option).then(option => { + position.option = option; + array.push(position); + callback(); + }).catch(reject); + }, () => { + resolve(array); + }) + }, reject); + }) + }) + } + /** * Returns an object that can be used to create a chart, show total return, etc. * @author Torrey Leonard