Skip to content

Commit

Permalink
Added Bollinger Bands to AlphaVantage API.
Browse files Browse the repository at this point in the history
Updated to support Robinhood's new authentication API.
Added support for Robinhood's multifactor authentication.
Made it optional to provide a password in the user constructor when creating a new Robinhood user.
  • Loading branch information
torreyleonard committed Dec 14, 2018
1 parent ae9c167 commit e934800
Show file tree
Hide file tree
Showing 34 changed files with 797 additions and 892 deletions.
3 changes: 2 additions & 1 deletion .gitignore
100644 → 100755
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
algotrader.iml
/node_modules/
/.idea/
/ignore/
/ignore/
.DS_Store
Empty file modified LICENSE.md
100644 → 100755
Empty file.
10 changes: 10 additions & 0 deletions README.md
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,16 @@ myUser.authenticate()
```
Personally, I either store user data as an array in a .json file, then require it into the class, (insecure) or ask for the user's credentials in the console. You should handle this sensitive data in a way that you're comfortable with.

**Note:** providing a password in the User constructor is optional. If it is not provided, you will be prompted via CLI.

##### MFA

Algotrader now supports multifactor authentication. So, if you have this enabled on your account (which is a good idea by the way), you'll be prompted to enter the six-digit code after login. If you run a trading script with this library automatically and have MFA enabled, it may be worth your while to utilize a telecom API (possible through Twilio?) to have the code programmatically entered into the CLI.

The MFA prompt will appear like so:

![Algotrader MFA Prompt](https://i.gyazo.com/11420983d69bf02a59026947513408ac.png)

#### Get a user's portfolio
There are a good amount of query functions that you can run on the user's portfolio. Using your [```User```](https://github.com/Ladinn/algotrader/blob/master/docs/ROBINHOOD.md#User) instance, you can grab the portfolio using ``` User.getPortfolio()``` which returns a new [```Portfolio```](https://github.com/Ladinn/algotrader/blob/master/docs/ROBINHOOD.md#Portfolio) object.
```js
Expand Down
Empty file modified docs/ALGORITHM.md
100644 → 100755
Empty file.
19 changes: 19 additions & 0 deletions docs/DATA.md
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ Further documentation can be found here: https://www.alphavantage.co/documentati
* [.stochf(symbol, interval, timePeriod, seriesType, fastKPeriod, fastDPeriod, fastDmaType)](#AlphaVantage+stochf) ⇒ <code>Promise.&lt;Array&gt;</code>
* [.rsi(symbol, interval, timePeriod, seriesType)](#AlphaVantage+rsi) ⇒ <code>Promise.&lt;Array&gt;</code>
* [.stochRSI(symbol, interval, timePeriod, seriesType, fastKPeriod, fastDPeriod, fastDmaType)](#AlphaVantage+stochRSI) ⇒ <code>Promise.&lt;Array&gt;</code>
* [.bbands(symbol, interval, timePeriod, seriesType, nbdevup, nbdevdn, matype)](#AlphaVantage+bbands) ⇒ <code>Promise.&lt;Array&gt;</code>

<a name="new_AlphaVantage_new"></a>

Expand Down Expand Up @@ -383,6 +384,24 @@ http://www.fmlabs.com/reference/default.htm?url=StochRSI.htm
| fastDPeriod | <code>Number</code> \| <code>Null</code> | |
| fastDmaType | <code>Number</code> \| <code>Null</code> | Integers 0 - 8 are accepted with the following mappings: 0 = Simple Moving Average (SMA), 1 = Exponential Moving Average (EMA), 2 = Weighted Moving Average (WMA), 3 = Double Exponential Moving Average (DEMA), 4 = Triple Exponential Moving Average (TEMA), 5 = Triangular Moving Average (TRIMA), 6 = T3 Moving Average, 7 = Kaufman Adaptive Moving Average (KAMA), 8 = MESA Adaptive Moving Average (MAMA). |

<a name="AlphaVantage+bbands"></a>

### alphaVantage.bbands(symbol, interval, timePeriod, seriesType, nbdevup, nbdevdn, matype) ⇒ <code>Promise.&lt;Array&gt;</code>
Returns an array of bollinger bands for the equity specified.
https://www.investopedia.com/articles/technical/04/030304.asp

**Kind**: instance method of [<code>AlphaVantage</code>](#AlphaVantage)

| Param | Type | Description |
| --- | --- | --- |
| symbol | <code>String</code> | |
| interval | <code>String</code> | Time interval between two consecutive data points in the time series. The following values are supported: 1min, 5min, 15min, 30min, 60min, daily, weekly, monthly |
| timePeriod | <code>Number</code> | Number of data points used to calculate each BBANDS value. Positive integers are accepted (e.g., time_period=60, time_period=200) |
| seriesType | <code>String</code> | The desired price type in the time series. Four types are supported: close, open, high, low |
| nbdevup | <code>Number</code> \| <code>Null</code> | The standard deviation multiplier of the upper band. Positive integers are accepted. By default, nbdevup=2. |
| nbdevdn | <code>Number</code> \| <code>Null</code> | The standard deviation multiplier of the lower band. Positive integers are accepted. By default, nbdevdn=2. |
| matype | <code>Number</code> \| <code>Null</code> | Moving average type of the time series. By default, matype=0. Integers 0 - 8 are accepted with the following mappings. 0 = Simple Moving Average (SMA), 1 = Exponential Moving Average (EMA), 2 = Weighted Moving Average (WMA), 3 = Double Exponential Moving Average (DEMA), 4 = Triple Exponential Moving Average (TEMA), 5 = Triangular Moving Average (TRIMA), 6 = T3 Moving Average, 7 = Kaufman Adaptive Moving Average (KAMA), 8 = MESA Adaptive Moving Average (MAMA). |

<a name="IEX"></a>

## IEX
Expand Down
Empty file modified docs/GLOBALS.md
100644 → 100755
Empty file.
173 changes: 161 additions & 12 deletions docs/ROBINHOOD.md
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -175,13 +175,19 @@ Represents a security traded on Robinhood.
* [.isStock()](#Instrument+isStock) ⇒ <code>Boolean</code>
* [.isETP()](#Instrument+isETP) ⇒ <code>Boolean</code>
* [.isADR()](#Instrument+isADR) ⇒ <code>Boolean</code>
* [.equals(otherInstrument)](#Instrument+equals) ⇒ <code>Boolean</code>
* _static_
* [.getAll()](#Instrument.getAll) ⇒ <code>Promise.&lt;Array&gt;</code>
* [.getBySymbol(symbol)](#Instrument.getBySymbol)[<code>Promise.&lt;Instrument&gt;</code>](#Instrument)
* [.getByID(id)](#Instrument.getByID)[<code>Promise.&lt;Instrument&gt;</code>](#Instrument)
* [.getByURL(instrumentURL)](#Instrument.getByURL)[<code>Promise.&lt;Instrument&gt;</code>](#Instrument)
* [.getTopMoving(direction)](#Instrument.getTopMoving)[<code>Promise.&lt;Instrument&gt;</code>](#Instrument)
* [.getByIdArray(ids)](#Instrument.getByIdArray) ⇒ <code>Promise.&lt;Array&gt;</code>
* [.getCategories()](#Instrument.getCategories) ⇒ <code>Array.&lt;String&gt;</code>
* [.getByCategory(category)](#Instrument.getByCategory) ⇒ <code>Promise.&lt;Array&gt;</code>
* [.getMostPopular()](#Instrument.getMostPopular) ⇒ <code>Promise.&lt;Array&gt;</code>
* [.getUpcomingEarnings()](#Instrument.getUpcomingEarnings) ⇒ <code>Promise.&lt;Array&gt;</code>
* [.getRecommendations(user)](#Instrument.getRecommendations) ⇒ <code>Promise.&lt;Array&gt;</code>

<a name="new_Instrument_new"></a>

Expand Down Expand Up @@ -326,6 +332,17 @@ Checks if the instrument is an American Depositary Receipt. Typically applies to
https://www.investopedia.com/terms/a/adr.asp

**Kind**: instance method of [<code>Instrument</code>](#Instrument)
<a name="Instrument+equals"></a>

### instrument.equals(otherInstrument) ⇒ <code>Boolean</code>
Check whether another instance of Instrument equals this instance.

**Kind**: instance method of [<code>Instrument</code>](#Instrument)

| Param | Type |
| --- | --- |
| otherInstrument | [<code>Instrument</code>](#Instrument) |

<a name="Instrument.getAll"></a>

### Instrument.getAll() ⇒ <code>Promise.&lt;Array&gt;</code>
Expand All @@ -344,6 +361,17 @@ Returns an instrument object for the specified symbol.
| --- | --- |
| symbol | <code>String</code> |

<a name="Instrument.getByID"></a>

### Instrument.getByID(id) ⇒ [<code>Promise.&lt;Instrument&gt;</code>](#Instrument)
Returns an instrument object for the specified Robinhood instrument ID.

**Kind**: static method of [<code>Instrument</code>](#Instrument)

| Param | Type |
| --- | --- |
| id | <code>String</code> |

<a name="Instrument.getByURL"></a>

### Instrument.getByURL(instrumentURL) ⇒ [<code>Promise.&lt;Instrument&gt;</code>](#Instrument)
Expand All @@ -366,6 +394,26 @@ Returns an array of Instruments for 10 of the top moving S&P 500 equities.
| --- | --- | --- |
| direction | <code>String</code> | Possible options: [up, down] |

<a name="Instrument.getByIdArray"></a>

### Instrument.getByIdArray(ids) ⇒ <code>Promise.&lt;Array&gt;</code>
Returns an array of instrument objects for the specified array of IDs.

Note: large arrays will take longer to process and are capped at 50 per request, so multiple
requests will be sent as the function iterates through the array.

**Kind**: static method of [<code>Instrument</code>](#Instrument)

| Param | Type |
| --- | --- |
| ids | <code>Array</code> |

<a name="Instrument.getCategories"></a>

### Instrument.getCategories() ⇒ <code>Array.&lt;String&gt;</code>
Returns an array of known categories that can be used with getByCategory(). This list is non-exhaustive.

**Kind**: static method of [<code>Instrument</code>](#Instrument)
<a name="Instrument.getByCategory"></a>

### Instrument.getByCategory(category) ⇒ <code>Promise.&lt;Array&gt;</code>
Expand All @@ -375,14 +423,31 @@ Returns an array of Instruments related to the given category.

| Param | Type | Description |
| --- | --- | --- |
| category | <code>String</code> | Possible options: [ technology, 100-most-popular, ... ] |
| category | <code>String</code> | For possible options see getCategories(). |

<a name="Instrument.getMostPopular"></a>

### Instrument.getMostPopular() ⇒ <code>Promise.&lt;Array&gt;</code>
Returns an array of Instruments for the top 100 most popular equities on Robinhood.

**Kind**: static method of [<code>Instrument</code>](#Instrument)
<a name="Instrument.getUpcomingEarnings"></a>

### Instrument.getUpcomingEarnings() ⇒ <code>Promise.&lt;Array&gt;</code>
Returns an array of Instruments that have upcoming earnings.

**Kind**: static method of [<code>Instrument</code>](#Instrument)
<a name="Instrument.getRecommendations"></a>

### Instrument.getRecommendations(user) ⇒ <code>Promise.&lt;Array&gt;</code>
Returns an array of instruments for stocks from Robinhood's recommendations for the given user.

**Kind**: static method of [<code>Instrument</code>](#Instrument)

| Param | Type |
| --- | --- |
| user | [<code>User</code>](#User) |

<a name="Market"></a>

## Market
Expand Down Expand Up @@ -763,6 +828,7 @@ Represents and executes an order for the given instrument.
* [new Order(user, object)](#new_Order_new)
* _instance_
* [.submit()](#Order+submit) ⇒ <code>Promise.&lt;Object&gt;</code>
* [.cancel()](#Order+cancel) ⇒ <code>Promise.&lt;Object&gt;</code>
* [.getResponse()](#Order+getResponse) ⇒ <code>Object</code> \| <code>Null</code>
* _static_
* [.getByOrderID(user, orderID)](#Order.getByOrderID)[<code>Promise.&lt;Order&gt;</code>](#Order)
Expand All @@ -784,6 +850,12 @@ Creates a new Order object.
### order.submit() ⇒ <code>Promise.&lt;Object&gt;</code>
Submits an order to Robinhood to be executed by the exchange.

**Kind**: instance method of [<code>Order</code>](#Order)
<a name="Order+cancel"></a>

### order.cancel() ⇒ <code>Promise.&lt;Object&gt;</code>
Attempts to cancel an order.

**Kind**: instance method of [<code>Order</code>](#Order)
<a name="Order+getResponse"></a>

Expand Down Expand Up @@ -822,7 +894,10 @@ Represents all of the user's holdings on Robinhood and allows for various querie
**Kind**: global class

* [Portfolio](#Portfolio)
* [new Portfolio(array)](#new_Portfolio_new)
* [new Portfolio(user, array)](#new_Portfolio_new)
* [.sellAll()](#Portfolio+sellAll) ⇒ <code>Promise.&lt;(Boolean\|Error)&gt;</code>
* [.setQuantity(symbol, targetQuantity)](#Portfolio+setQuantity)[<code>Promise.&lt;Order&gt;</code>](#Order)
* [.getStockValue()](#Portfolio+getStockValue) ⇒ <code>Promise.&lt;Number&gt;</code>
* [.getInstrumentArray()](#Portfolio+getInstrumentArray) ⇒ <code>Array</code>
* [.getSymbols()](#Portfolio+getSymbols) ⇒ <code>Array</code>
* [.getBuyPrice(symbol)](#Portfolio+getBuyPrice) ⇒ <code>Number</code>
Expand All @@ -844,14 +919,39 @@ Represents all of the user's holdings on Robinhood and allows for various querie

<a name="new_Portfolio_new"></a>

### new Portfolio(array)
### new Portfolio(user, array)
Creates a new Portfolio object.


| Param |
| --- |
| array |
| Param | Type |
| --- | --- |
| user | [<code>User</code>](#User) |
| array | <code>Array</code> |

<a name="Portfolio+sellAll"></a>

### portfolio.sellAll() ⇒ <code>Promise.&lt;(Boolean\|Error)&gt;</code>
Sells all positions in the user's portfolio at the market price.

**Kind**: instance method of [<code>Portfolio</code>](#Portfolio)
<a name="Portfolio+setQuantity"></a>

### portfolio.setQuantity(symbol, targetQuantity) ⇒ [<code>Promise.&lt;Order&gt;</code>](#Order)
Executes a new order to reduce or increase the user's position in the given symbol by the given amount.

**Kind**: instance method of [<code>Portfolio</code>](#Portfolio)

| Param | Type |
| --- | --- |
| symbol | <code>String</code> |
| targetQuantity | <code>Number</code> |

<a name="Portfolio+getStockValue"></a>

### portfolio.getStockValue() ⇒ <code>Promise.&lt;Number&gt;</code>
Returns the total market value of all stocks held by the user.

**Kind**: instance method of [<code>Portfolio</code>](#Portfolio)
<a name="Portfolio+getInstrumentArray"></a>

### portfolio.getInstrumentArray() ⇒ <code>Array</code>
Expand Down Expand Up @@ -1049,14 +1149,21 @@ Represents the user that is logged in while accessing the Robinhood API.

* [User](#User)
* [new User(username, password)](#new_User_new)
* [.authenticate()](#User+authenticate) ⇒ <code>Promise</code>
* [.authenticate()](#User+authenticate) ⇒ <code>Promise.&lt;Boolean&gt;</code>
* [.logout()](#User+logout) ⇒ <code>Promise.&lt;Boolean&gt;</code>
* [.getAccount()](#User+getAccount) ⇒ <code>Promise</code>
* [.getBalances()](#User+getBalances) ⇒ <code>Promise.&lt;Object&gt;</code>
* [.getBuyingPower()](#User+getBuyingPower) ⇒ <code>Promise</code>
* [.getUserInfo()](#User+getUserInfo) ⇒ <code>Promise.&lt;Object&gt;</code>
* [.getUID()](#User+getUID) ⇒ <code>Promise.&lt;String&gt;</code>
* [.getTaxInfo()](#User+getTaxInfo) ⇒ <code>Promise.&lt;Object&gt;</code>
* [.getDisclosureInfo()](#User+getDisclosureInfo) ⇒ <code>Promise.&lt;Object&gt;</code>
* [.getEmployerInfo()](#User+getEmployerInfo) ⇒ <code>Promise.&lt;Object&gt;</code>
* [.getInvestmentProfile()](#User+getInvestmentProfile) ⇒ <code>Promise.&lt;Object&gt;</code>
* [.getRecentDayTrades()](#User+getRecentDayTrades) ⇒ <code>Promise.&lt;Object&gt;</code>
* [.getRecentOrders()](#User+getRecentOrders) ⇒ <code>Promise.&lt;Array.&lt;Order&gt;&gt;</code>
* [.cancelOpenOrders()](#User+cancelOpenOrders) ⇒ <code>Promise</code>
* [.getRecentOptionOrders()](#User+getRecentOptionOrders) ⇒ <code>Promise.&lt;Array&gt;</code>
* [.getPortfolio()](#User+getPortfolio) ⇒ <code>Promise.&lt;Object&gt;</code>
* [.getLinkedBanks()](#User+getLinkedBanks) ⇒ <code>Promise.&lt;Object&gt;</code>
* [.addDeposit(bankID, amount, frequency)](#User+addDeposit) ⇒ <code>Promise.&lt;Object&gt;</code>
Expand All @@ -1069,28 +1176,52 @@ Represents the user that is logged in while accessing the Robinhood API.
Creates a new User object.


| Param | Type |
| --- | --- |
| username | <code>String</code> |
| password | <code>String</code> |
| Param | Type | Description |
| --- | --- | --- |
| username | <code>String</code> | |
| password | <code>String</code> | Optional. If not provided the user will be prompted via CLI. |

<a name="User+authenticate"></a>

### user.authenticate() ⇒ <code>Promise</code>
### user.authenticate() ⇒ <code>Promise.&lt;Boolean&gt;</code>
Authenticates a user using the inputted username and password.

**Kind**: instance method of [<code>User</code>](#User)
<a name="User+logout"></a>

### user.logout() ⇒ <code>Promise.&lt;Boolean&gt;</code>
Logout the user by expiring the authentication token.

**Kind**: instance method of [<code>User</code>](#User)
<a name="User+getAccount"></a>

### user.getAccount() ⇒ <code>Promise</code>
Returns vital information about balances and enabled features.

**Kind**: instance method of [<code>User</code>](#User)
<a name="User+getBalances"></a>

### user.getBalances() ⇒ <code>Promise.&lt;Object&gt;</code>
Returns an object containing details on the user's cash and marginbalance.

**Kind**: instance method of [<code>User</code>](#User)
<a name="User+getBuyingPower"></a>

### user.getBuyingPower() ⇒ <code>Promise</code>
Returns the amount of money available to be spent.

**Kind**: instance method of [<code>User</code>](#User)
<a name="User+getUserInfo"></a>

### user.getUserInfo() ⇒ <code>Promise.&lt;Object&gt;</code>
Returns information like username, first / last name, creation date, id, and more.

**Kind**: instance method of [<code>User</code>](#User)
<a name="User+getUID"></a>

### user.getUID() ⇒ <code>Promise.&lt;String&gt;</code>
Returns the user's unique ID.

**Kind**: instance method of [<code>User</code>](#User)
<a name="User+getTaxInfo"></a>

Expand Down Expand Up @@ -1121,6 +1252,24 @@ Returns the user's answers to basic questions regarding investment experiences.
### user.getRecentDayTrades() ⇒ <code>Promise.&lt;Object&gt;</code>
Returns arrays of recent option and equity day trades.

**Kind**: instance method of [<code>User</code>](#User)
<a name="User+getRecentOrders"></a>

### user.getRecentOrders() ⇒ <code>Promise.&lt;Array.&lt;Order&gt;&gt;</code>
Returns an array of recent orders.

**Kind**: instance method of [<code>User</code>](#User)
<a name="User+cancelOpenOrders"></a>

### user.cancelOpenOrders() ⇒ <code>Promise</code>
Cancels all open orders.

**Kind**: instance method of [<code>User</code>](#User)
<a name="User+getRecentOptionOrders"></a>

### user.getRecentOptionOrders() ⇒ <code>Promise.&lt;Array&gt;</code>
Returns an array of recent option orders.

**Kind**: instance method of [<code>User</code>](#User)
<a name="User+getPortfolio"></a>

Expand Down
Empty file modified examples/highest-open-interest.js
100644 → 100755
Empty file.
Empty file modified index.js
100644 → 100755
Empty file.
Empty file modified objects/algorithm/Backtest.js
100644 → 100755
Empty file.
Empty file modified objects/algorithm/PaperTrader.js
100644 → 100755
Empty file.
Empty file modified objects/algorithm/Scheduler.js
100644 → 100755
Empty file.
Empty file modified objects/broker/robinhood/Fundamentals.js
100644 → 100755
Empty file.
2 changes: 1 addition & 1 deletion objects/broker/robinhood/Instrument.js
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,7 @@ class Instrument extends Robinhood {
request({
uri: "https://analytics.robinhood.com/instruments/tag/for-you/",
headers: {
'Authorization': 'Token ' + user.getAuthToken()
'Authorization': 'Bearer ' + user.getAuthToken()
}
}, (error, response, body) => {
Robinhood.handleResponse(error, response, body, null, res => {
Expand Down
Empty file modified objects/broker/robinhood/Market.js
100644 → 100755
Empty file.
4 changes: 2 additions & 2 deletions objects/broker/robinhood/OptionInstrument.js
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ class OptionInstrument extends Robinhood {
else request({
uri: "https://api.robinhood.com/options/instruments/",
headers: {
'Authorization': 'Token ' + user.getAuthToken()
'Authorization': 'Bearer ' + user.getAuthToken()
}
}, (error, response, body) => {
return Robinhood.handleResponse(error, response, body, user.getAuthToken(), res => {
Expand All @@ -71,7 +71,7 @@ class OptionInstrument extends Robinhood {
request({
uri: url,
headers: {
'Authorization': 'Token ' + user.getAuthToken()
'Authorization': 'Bearer ' + user.getAuthToken()
}
}, (error, response, body) => {
return Robinhood.handleResponse(error, response, body, user.getAuthToken(), res => {
Expand Down
Loading

0 comments on commit e934800

Please sign in to comment.