Code Monkey home page Code Monkey logo

robinhood-node's Introduction

NodeJS Framework to make trades with the private Robinhood API. Using this API is not encouraged, since it's not officially available and it has been reverse engineered. See @Sanko's Unofficial Documentation for more information.

FYI Robinhood's Terms and Conditions

Features

  • Quote Data
  • Buy, Sell Orders
  • Daily Fundamentals
  • Daily, Weekly, Monthly Historicals

Tested on the latest versions of Node 6, 7 & 8.

Installation

$ npm install robinhood --save

Usage

To authenticate, you can either use your username and password to the Robinhood app or a previously authenticated Robinhood api token:

Robinhood API Auth Token

//A previously authenticated Robinhood API auth token

var credentials = {
    token: ''
};
var Robinhood = require('robinhood')(credentials, function(err, data){

    //Robinhood is connected and you may begin sending commands to the api.

    Robinhood.quote_data('GOOG', function(error, response, body) {
        if (error) {
            console.error(error);
            process.exit(1);
        }
        console.log(body);
    });

});

Username & Password

This type of login may have been deprecated in favor of the API Token above.

//The username and password you use to sign into the robinhood app.

var credentials = {
    username: '',
    password: ''
};

MFA code

var Robinhood = robinhood({
        username : '',
        password : ''
    }, (err, data) => {
        if(err) {
            console.log(err);
        } else {
            if (data && data.mfa_required) {
            var mfa_code = '123456'; // set mfa_code here

            Robinhood.set_mfa_code(mfa_code, () => {
                console.log(Robinhood.auth_token());
            });
            }
            else {
                console.log(Robinhood.auth_token());
            }
        }
    });

API

Before using these methods, make sure you have initialized Robinhood using the snippet above.

auth_token()

Get the current authenticated Robinhood api authentication token

var credentials = require("../credentials.js")();
var Robinhood = require('robinhood')(credentials, function(err, data){
    console.log(Robinhood.auth_token());
        //      <authenticated alphanumeric token>
}

expire_token()

Expire the current authenticated Robinhood api token (logout).

NOTE: After expiring a token you will need to reinstantiate the package with username & password in order to get a new token!

var credentials = require("../credentials.js")();
var Robinhood = require('robinhood')(credentials, function(err, data){
    Robinhood.expire_token(function(err, response, body){
        if(err){
            console.error(err);
        }else{
            console.log("Successfully logged out of Robinhood and expired token.");
            // NOTE: body is undefined on the callback
        }
    })
});

investment_profile(callback)

Get the current user's investment profile.

var credentials = require("../credentials.js")();
var Robinhood = require('robinhood')(credentials, function(err, data){
    Robinhood.investment_profile(function(err, response, body){
        if(err){
            console.error(err);
        }else{
            console.log("investment_profile");
            console.log(body);
                //    { annual_income: '25000_39999',
                //      investment_experience: 'no_investment_exp',
                //      updated_at: '2015-06-24T17:14:53.593009Z',
                //      risk_tolerance: 'low_risk_tolerance',
                //      total_net_worth: '0_24999',
                //      liquidity_needs: 'very_important_liq_need',
                //      investment_objective: 'income_invest_obj',
                //      source_of_funds: 'savings_personal_income',
                //      user: 'https://api.robinhood.com/user/',
                //      suitability_verified: true,
                //      tax_bracket: '',
                //      time_horizon: 'short_time_horizon',
                //      liquid_net_worth: '0_24999' }

        }
    })
});

instruments(symbol, callback)

var credentials = require("../credentials.js")();
var Robinhood = require('robinhood')(credentials, function(err, data){
    Robinhood.instruments('AAPL',function(err, response, body){
        if(err){
            console.error(err);
        }else{
            console.log("instruments");
            console.log(body);
            //    { previous: null,
            //      results:
            //       [ { min_tick_size: null,
            //           splits: 'https://api.robinhood.com/instruments/450dfc6d-5510-4d40-abfb-f633b7d9be3e/splits/',
            //           margin_initial_ratio: '0.5000',
            //           url: 'https://api.robinhood.com/instruments/450dfc6d-5510-4d40-abfb-f633b7d9be3e/',
            //           quote: 'https://api.robinhood.com/quotes/AAPL/',
            //           symbol: 'AAPL',
            //           bloomberg_unique: 'EQ0010169500001000',
            //           list_date: '1990-01-02',
            //           fundamentals: 'https://api.robinhood.com/fundamentals/AAPL/',
            //           state: 'active',
            //           day_trade_ratio: '0.2500',
            //           tradeable: true,
            //           maintenance_ratio: '0.2500',
            //           id: '450dfc6d-5510-4d40-abfb-f633b7d9be3e',
            //           market: 'https://api.robinhood.com/markets/XNAS/',
            //           name: 'Apple Inc. - Common Stock' } ],
            //      next: null }
        }
    })
});

Get the user's instruments for a specified stock.

quote_data(stock, callback) // Not authenticated

Get the user's quote data for a specified stock.

var Robinhood = require('robinhood')(credentials, function(err, data){
    Robinhood.quote_data('AAPL', function(err, response, body){
        if(err){
            console.error(err);
        }else{
            console.log("quote_data");
            console.log(body);
            //{
            //    results: [
            //        {
            //            ask_price: String, // Float number in a String, e.g. '735.7800'
            //            ask_size: Number, // Integer
            //            bid_price: String, // Float number in a String, e.g. '731.5000'
            //            bid_size: Number, // Integer
            //            last_trade_price: String, // Float number in a String, e.g. '726.3900'
            //            last_extended_hours_trade_price: String, // Float number in a String, e.g. '735.7500'
            //            previous_close: String, // Float number in a String, e.g. '743.6200'
            //            adjusted_previous_close: String, // Float number in a String, e.g. '743.6200'
            //            previous_close_date: String, // YYYY-MM-DD e.g. '2016-01-06'
            //            symbol: String, // e.g. 'AAPL'
            //            trading_halted: Boolean,
            //            updated_at: String, // YYYY-MM-DDTHH:MM:SS e.g. '2016-01-07T21:00:00Z'
            //        }
            //    ]
            //}
        }
    })
});

accounts(callback)

var Robinhood = require('robinhood')(credentials, function(err, data){
    Robinhood.accounts(function(err, response, body){
        if(err){
            console.error(err);
        }else{
            console.log("accounts");
            console.log(body);
            //{ previous: null,
            //  results:
            //   [ { deactivated: false,
            //       updated_at: '2016-03-11T20:37:15.971253Z',
            //       margin_balances: [Object],
            //       portfolio: 'https://api.robinhood.com/accounts/asdf/portfolio/',
            //       cash_balances: null,
            //       withdrawal_halted: false,
            //       cash_available_for_withdrawal: '692006.6600',
            //       type: 'margin',
            //       sma: '692006.6600',
            //       sweep_enabled: false,
            //       deposit_halted: false,
            //       buying_power: '692006.6600',
            //       user: 'https://api.robinhood.com/user/',
            //       max_ach_early_access_amount: '1000.00',
            //       cash_held_for_orders: '0.0000',
            //       only_position_closing_trades: false,
            //       url: 'https://api.robinhood.com/accounts/asdf/',
            //       positions: 'https://api.robinhood.com/accounts/asdf/positions/',
            //       created_at: '2015-06-17T14:53:36.928233Z',
            //       cash: '692006.6600',
            //       sma_held_for_orders: '0.0000',
            //       account_number: 'asdf',
            //       uncleared_deposits: '0.0000',
            //       unsettled_funds: '0.0000' } ],
            //  next: null }
        }
    })
});

Get the user's accounts.

user(callback)

Get the user information.

var Robinhood = require('robinhood')(credentials, function(err, data){
    Robinhood.user(function(err, response, body){
        if(err){
            console.error(err);
        }else{
            console.log("user");
            console.log(body);
        }
    })
});

dividends(callback)

Get the user's dividends information.

var Robinhood = require('robinhood')(credentials, function(err, data){
    Robinhood.dividends(function(err, response, body){
        if(err){
            console.error(err);
        }else{
            console.log("dividends");
            console.log(body);
        }
    })
});

earnings(option, callback)

Get the earnings information. Option should be one of:

let option = { range: X } // X is an integer between 1 and 21. This returns all
                          // expected earnings within a number of calendar days.

OR

let option = { instrument: URL } // URL is full instrument url.

OR

let option = { symbol: SYMBOL } // SYMBOL is a plain ol' ticker symbol.
var Robinhood = require('robinhood')(credentials, function(err, data){
    Robinhood.earnings(option, function(err, response, body){
        if(err){
            console.error(err);
        }else{
            console.log("earnings");
            console.log(body);
        }
    })
});

orders(options, callback)

Get the user's orders information.

Retreive a set of orders

Send options hash (optional) to limit to specific instrument and/or earliest date of orders.

// optional options hash.  If no hash is sent, all orders will be returned.
let options = {
    updated_at: '2017-08-25',
    instrument: 'https://api.robinhood.com/instruments/df6c09dc-bb4f-4495-8c59-f13e6eb3641f/'
}
var Robinhood = require('robinhood')(credentials, function(err, data){
    Robinhood.orders(options, function(err, response, body){
        if(err){
            console.error(err);
        }else{
            console.log("orders");
            console.log(body);
        }
    })
});

Retreive a particular order

Send the id of the order to retreive the data for a specific order.

let order_id = "string_identifier"; // e.g., id: 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa',
var Robinhood = require('robinhood')(credentials, function(err, data){
    Robinhood.orders(order_id, function(err, response, body){
        if(err){
            console.error(err);
        }else{
            console.log("order");
            console.log(body);
        }
    })
});

positions(callback)

Get the user's position information.

var Robinhood = require('robinhood')(credentials, function(err, data){
    Robinhood.positions(function(err, response, body){
        if (err){
            console.error(err);
        }else{
            console.log("positions");
            console.log(body);
        }
    });
});

nonzero_positions(callback)

Get the user's nonzero position information only.

var Robinhood = require('robinhood')(credentials, function(err, data){
    Robinhood.nonzero_positions(function(err, response, body){
        if (err){
            console.error(err);
        }else{
            console.log("positions");
            console.log(body);
        }
    });
});

place_buy_order(options, callback)

Place a buy order on a specified stock.

var Robinhood = require('robinhood')(credentials, function(err, data){
    var options = {
        type: 'limit',
        quantity: 1,
        bid_price: 1.00,
        instrument: {
            url: String,
            symbol: String
        }
        // // Optional:
        // trigger: String, // Defaults to "gfd" (Good For Day)
        // time: String,    // Defaults to "immediate"
        // type: String     // Defaults to "market"
    }
    Robinhood.place_buy_order(options, function(error, response, body){
        if(error){
            console.error(error);
        }else{
            console.log(body);
        }
    })
});

For the Optional ones, the values can be:

[Disclaimer: This is an unofficial API based on reverse engineering, and the following option values have not been confirmed]

trigger

A trade trigger is usually a market condition, such as a rise or fall in the price of an index or security.

Values can be:

  • gfd: Good For Day
  • gtc: Good Till Cancelled
  • oco: Order Cancels Other

time

The time in force for an order defines the length of time over which an order will continue working before it is canceled.

Values can be:

  • immediate : The order will be cancelled unless it is fulfilled immediately.
  • day : The order will be cancelled at the end of the trading day.

place_sell_order(options, callback)

Place a sell order on a specified stock.

var Robinhood = require('robinhood')(credentials, function(err, data){
    var options = {
        type: 'limit',
        quantity: 1,
        bid_price: 1.00,
        instrument: {
            url: String,
            symbol: String
        },
        // // Optional:
        // trigger: String, // Defaults to "gfd" (Good For Day)
        // time: String,    // Defaults to "immediate"
        // type: String     // Defaults to "market"
    }
    Robinhood.place_sell_order(options, function(error, response, body){
        if(error){
            console.error(error);
        }else{
            console.log(body);
        }
    })
});

For the Optional ones, the values can be:

[Disclaimer: This is an unofficial API based on reverse engineering, and the following option values have not been confirmed]

trigger

A trade trigger is usually a market condition, such as a rise or fall in the price of an index or security.

Values can be:

  • gfd: Good For Day
  • gtc: Good Till Cancelled
  • oco: Order Cancels Other

time

The time in force for an order defines the length of time over which an order will continue working before it is canceled.

Values can be:

  • immediate : The order will be cancelled unless it is fulfilled immediately.
  • day : The order will be cancelled at the end of the trading day.

fundamentals(symbol, callback)

Get fundamental data about a symbol.

Response

An object containing information about the symbol:

var Robinhood = require('robinhood')(credentials, function(err, data){
    Robinhood.fundamentals("SBPH", function(error, response, body){
        if(error){
            console.error(error);
        }else{
            console.log(body);
            //{                               // Example for SBPH
            //    average_volume: string,     // "14381.0215"
            //    description: string,        // "Spring Bank Pharmaceuticals, Inc. [...]"
            //    dividend_yield: string,     // "0.0000"
            //    high: string,               // "12.5300"
            //    high_52_weeks: string,      // "13.2500"
            //    instrument: string,         // "https://api.robinhood.com/instruments/42e07e3a-ca7a-4abc-8c23-de49cb657c62/"
            //    low: string,                // "11.8000"
            //    low_52_weeks: string,       // "7.6160"
            //    market_cap: string,         // "94799500.0000"
            //    open: string,               // "12.5300"
            //    pe_ratio: string,           // null (price/earnings ratio)
            //    volume: string              // "4119.0000"
            //}
        }
    })
});

cancel_order(order, callback)

Cancel an order with the order object

var Robinhood = require('robinhood')(credentials, function(err, data){
    //Get list of orders
    Robinhood.orders(function(error, response, body){
        if(error){
            console.error(error);
        }else{
            var orderToCancel = body.results[0];
            //Try to cancel the latest order
            Robinhood.cancel_order(orderToCancel, function(err, response, body){
                if(err){
                    //Error

                    console.error(err);     // { message: 'Order cannot be cancelled.', order: {Order} }
                }else{
                    //Success

                    console.log("Cancel Order Successful");
                    console.log(body)       //{}
                }
            })
        }
    })
})

Cancel an order by order id

var order_id = 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'
var Robinhood = require('robinhood')(credentials, function(err, data){
        Robinhood.cancel_order(order_id, function(err, response, body){
            if(err){
                //Error
                console.error(err);     // { message: 'Order cannot be cancelled.', order: {Order} }
            }else{
                //Success
                console.log("Cancel Order Successful");
                console.log(body)       //{}
            }
        })
})

watchlists(name, callback)

var Robinhood = require('robinhood')(credentials, function(err, data){
    Robinhood.watchlists(function(err, response, body){
        if(err){
            console.error(err);
        }else{
            console.log("got watchlists");
            console.log(body);

            //{ previous: null,
            //  results:
            //   [ { url: 'https://api.robinhood.com/watchlists/Default/',
            //       user: 'https://api.robinhood.com/user/',
            //      name: 'Default' } ],
            //  next: null }
        }
    })
});

create_watch_list(name, callback)

//Your account type must support multiple watchlists to use this endpoint otherwise will get { detail: 'Request was throttled.' } and watchlist is not created.
Robinhood.create_watch_list('Technology', function(err, response, body){
    if(err){
        console.error(err);
    }else{
        console.log("created watchlist");
        console.log(body);
    //    {
    //        "url": "https://api.robinhood.com/watchlists/Technology/",
    //        "user": "https://api.robinhood.com/user/",
    //        "name": "Technology"
    //    }

    }
})

sp500_up(callback)

var Robinhood = require('robinhood')(credentials, function(err, data){
    Robinhood.sp500_up(function(err, response, body){
        if(err){
            console.error(err);
        }else{
            console.log("sp500_up");
            console.log(body);
            //{ count: 10,
            //  next: null,
            //  previous: null,
            //  results:
            //   [ { instrument_url: 'https://api.robinhood.com/instruments/adbc3ce0-dd0d-4a7a-92e0-88c1f127cbcb/',
            //       symbol: 'NEM',
            //       updated_at: '2016-09-21T13:03:32.310184Z',
            //       price_movement: [{ market_hours_last_movement_pct: '7.55', market_hours_last_price: '41.0300' }],
            //       description: 'Newmont Mining Corp. is a gold producer, which is engaged in the acquisition, exploration and production of gold and copper properties in U.S., Australia, Peru, Indonesia, Ghana, Canada, New Zealand and Mexico. The company\'s operating segments include North America, South America, Asia Pacific and Africa. The North America segment consists of Nevada in the United States, La Herradura in Mexico and Hope Bay in Canada. The South America segment consists of Yanacocha and Conga in Peru. The Asia Pacific segment consists of Boddington in Australia, Batu Hijau in Indonesia and other smaller operations in Australia and New Zealand. The Africa segment consists of Ahafo and Akyem in Ghana. The company was founded by William Boyce Thompson on May 2, 1921 and is headquartered in Greenwood Village, CO.' },
            //     { instrument_url: 'https://api.robinhood.com/instruments/809adc21-ef75-4c3d-9c0e-5f9a167f235b/',
            //       symbol: 'ADBE',
            //       updated_at: '2016-09-21T13:01:31.748590Z',
            //       price_movement: [{ market_hours_last_movement_pct: '7.55', market_hours_last_price: '41.0300' }],
            //       description: 'Adobe Systems, Inc. provides digital marketing and digital media solutions. The company operates its business through three segments: Digital Media, Digital Marketing, and Print and Publishing. The Digital Media segment offers creative cloud services, which allow members to download and install the latest versions of products, such as Adobe Photoshop, Adobe Illustrator, Adobe Premiere Pro, Adobe Photoshop Lightroom and Adobe InDesign, as well as utilize other tools, such as Adobe Acrobat. This segment also offers other tools and services, including hobbyist products, such as Adobe Photoshop Elements and Adobe Premiere Elements, Adobe Digital Publishing Suite, Adobe PhoneGap, Adobe Typekit, as well as mobile apps, such as Adobe Photoshop Mix, Adobe Photoshop Sketch and Adobe Premiere Clip that run on tablets and mobile devices. The Digital Media serves professionals, including graphic designers, production artists, web designers and developers, user interface designers, videographers, motion graphic artists, prepress professionals, video game developers, mobile application developers, students and administrators. The Digital Marketing segment offers various solutions, including analytics, social marketing, targeting, media optimization, digital experience management and cross-channel campaign management, as well as premium video delivery and monetization. This segment also offers legacy enterprise software, such as Adobe Connect web conferencing platform and Adobe LiveCycle. The Print and Publishing segment offers legacy products and services for eLearning solutions, technical document publishing, web application development and high-end printing. Adobe Systems was founded by Charles M. Geschke and John E. Warnock in December 1982 and is headquartered in San Jose, CA.' }
            //    ]
            //}
        }
    })
});

sp500_down(callback)

var Robinhood = require('robinhood')(credentials, function(err, data){
    Robinhood.sp500_down(function(err, response, body){
        if(err){
            console.error(err);
        }else{
            console.log("sp500_down");
            console.log(body);
            //{ count: 10,
            //  next: null,
            //  previous: null,
            //  results:
            //   [ { instrument_url: 'https://api.robinhood.com/instruments/adbc3ce0-dd0d-4a7a-92e0-88c1f127cbcb/',
            //       symbol: 'NEM',
            //       updated_at: '2016-09-21T13:03:32.310184Z',
            //       price_movement: [{ market_hours_last_movement_pct: '-3.70', market_hours_last_price: '13.2800' }],
            //      description: 'Newmont Mining Corp. is a gold producer, which is engaged in the acquisition, exploration and production of gold and copper properties in U.S., Australia, Peru, Indonesia, Ghana, Canada, New Zealand and Mexico. The company\'s operating segments include North America, South America, Asia Pacific and Africa. The North America segment consists of Nevada in the United States, La Herradura in Mexico and Hope Bay in Canada. The South America segment consists of Yanacocha and Conga in Peru. The Asia Pacific segment consists of Boddington in Australia, Batu Hijau in Indonesia and other smaller operations in Australia and New Zealand. The Africa segment consists of Ahafo and Akyem in Ghana. The company was founded by William Boyce Thompson on May 2, 1921 and is headquartered in Greenwood Village, CO.' },
            //     { instrument_url: 'https://api.robinhood.com/instruments/809adc21-ef75-4c3d-9c0e-5f9a167f235b/',
            //       symbol: 'ADBE',
            //       updated_at: '2016-09-21T13:01:31.748590Z',
            //       price_movement: [{ market_hours_last_movement_pct: '-3.70', market_hours_last_price: '13.2800' }],
            //       description: 'Adobe Systems, Inc. provides digital marketing and digital media solutions. The company operates its business through three segments: Digital Media, Digital Marketing, and Print and Publishing. The Digital Media segment offers creative cloud services, which allow members to download and install the latest versions of products, such as Adobe Photoshop, Adobe Illustrator, Adobe Premiere Pro, Adobe Photoshop Lightroom and Adobe InDesign, as well as utilize other tools, such as Adobe Acrobat. This segment also offers other tools and services, including hobbyist products, such as Adobe Photoshop Elements and Adobe Premiere Elements, Adobe Digital Publishing Suite, Adobe PhoneGap, Adobe Typekit, as well as mobile apps, such as Adobe Photoshop Mix, Adobe Photoshop Sketch and Adobe Premiere Clip that run on tablets and mobile devices. The Digital Media serves professionals, including graphic designers, production artists, web designers and developers, user interface designers, videographers, motion graphic artists, prepress professionals, video game developers, mobile application developers, students and administrators. The Digital Marketing segment offers various solutions, including analytics, social marketing, targeting, media optimization, digital experience management and cross-channel campaign management, as well as premium video delivery and monetization. This segment also offers legacy enterprise software, such as Adobe Connect web conferencing platform and Adobe LiveCycle. The Print and Publishing segment offers legacy products and services for eLearning solutions, technical document publishing, web application development and high-end printing. Adobe Systems was founded by Charles M. Geschke and John E. Warnock in December 1982 and is headquartered in San Jose, CA.' }
            //    ]
            //}

        }
    })
});

splits(instrument, callback)

var Robinhood = require('robinhood')(credentials, function(err, data){

    Robinhood.splits("7a3a677d-1664-44a0-a94b-3bb3d64f9e20", function(err, response, body){
        if(err){
            console.error(err);
        }else{
            console.log("got splits");
            console.log(body);   //{ previous: null, results: [], next: null }
        }
    })
})

historicals(symbol, intv, span, callback)

var Robinhood = require('robinhood')(credentials, function(err, data){

    //{interval=5minute|10minute (required) span=week|day| }

    Robinhood.historicals("AAPL", '5minute', 'week', function(err, response, body){
        if(err){
            console.error(err);
        }else{
            console.log("got historicals");
            console.log(body);
            //
            //    { quote: 'https://api.robinhood.com/quotes/AAPL/',
            //      symbol: 'AAPL',
            //      interval: '5minute',
            //      span: 'week',
            //      bounds: 'regular',
            //      previous_close: null,
            //      historicals:
            //       [ { begins_at: '2016-09-15T13:30:00Z',
            //           open_price: '113.8300',
            //           close_price: '114.1700',
            //           high_price: '114.3500',
            //           low_price: '113.5600',
            //           volume: 3828122,
            //           session: 'reg',
            //           interpolated: false },
            //         { begins_at: '2016-09-15T13:35:00Z',
            //           open_price: '114.1600',
            //           close_price: '114.3800',
            //           high_price: '114.7300',
            //           low_price: '114.1600',
            //           volume: 2166098,
            //           session: 'reg',
            //           interpolated: false },
            //         ... 290 more items
            //      ]}
            //
        }
    })
})

url(url, callback)

url is used to get continued or paginated data from the API. Queries with long results return a reference to the next sete. Example -

next: 'https://api.robinhood.com/orders/?cursor=cD0yMD82LTA0LTAzKzkwJVNCNTclM0ExNC45MzYyKDYlMkIwoCUzqtAW' }

The url returned can be passed to the url method to continue getting the next set of results.

tag(tag, callback)

Retrieve Robinhood's new Tags: In 2018, Robinhood Web will expose more Social and Informational tools. You'll see how popular a security is with other Robinhood users, MorningStar ratings, etc.

Known tags:

  • 10 Most Popular Instruments: 10-most-popular
  • 100 Most Popular Instruments: 100-most-popular

Response sample:

{
   "slug":"10-most-popular",
   "name":"10 Most Popular",
   "description":"",
   "instruments":[
      "https://api.robinhood.com/instruments/6df56bd0-0bf2-44ab-8875-f94fd8526942/",
      "https://api.robinhood.com/instruments/50810c35-d215-4866-9758-0ada4ac79ffa/",
      "https://api.robinhood.com/instruments/450dfc6d-5510-4d40-abfb-f633b7d9be3e/",
      "https://api.robinhood.com/instruments/e39ed23a-7bd1-4587-b060-71988d9ef483/",
      "https://api.robinhood.com/instruments/1e513292-5926-4dc4-8c3d-4af6b5836704/",
      "https://api.robinhood.com/instruments/39ff611b-84e7-425b-bfb8-6fe2a983fcf3/",
      "https://api.robinhood.com/instruments/ebab2398-028d-4939-9f1d-13bf38f81c50/",
      "https://api.robinhood.com/instruments/940fc3f5-1db5-4fed-b452-f3a2e4562b5f/",
      "https://api.robinhood.com/instruments/c74a93bc-58f3-4ccb-b4e3-30c65e2f88c8/",
      "https://api.robinhood.com/instruments/fdf46795-2a81-4506-880f-514c8010c163/"
   ]
}

popularity(symbol, callback)

Get the popularity for a specified stock.

var credentials = require("../credentials.js")();
var Robinhood = require('robinhood')(credentials, function() {
    Robinhood.popularity('GOOG', function(error, response, body) {
        if (error) {
            console.error(error);
        } else {
            console.log(body);
            // {
            //    instrument: 'https://api.robinhood.com/instruments/943c5009-a0bb-4665-8cf4-a95dab5874e4/',
            //    num_open_positions: 16319
            // }
        }
    });
});

options_positions

Obtain list of options positions

var credentials = require("../credentials.js")();
var Robinhood = require('robinhood')(credentials, function() {
    Robinhood.options_positions((err, response, body) => {
        if (err) {
            console.error(err);
        } else {
            console.log(body);
        }
    });
});

// {
//   "created_at": "2018-10-12T17:05:18.195533Z",
//   "direction": "credit",
//   "intraday_quantity": "35.0000",
//   "average_open_price": "56.5143",
//   "chain": "https://api.robinhood.com/options/chains/103ce21e-4921-47ed-a263-e05d2d3d5e99/",
//   "updated_at": "2018-10-12T19:11:02.984831Z",
//   "symbol": "XLF",
//   "trade_value_multiplier": "100.0000",
//   "intraday_direction": "credit",
//   "strategy": "short_put",
//   "intraday_average_open_price": "56.5143",
//   "legs": [
//     {
//       "strike_price": "26.5000",
//       "option": "https://api.robinhood.com/options/instruments/fa512b6e-c121-4ff4-b8aa-9aa2974514b7/",
//       "expiration_date": "2018-10-19",
//       "option_type": "put",
//       "id": "214e0f90-4416-427a-b119-e1a96d8e9da7",
//       "position_type": "short",
//       "position": "https://api.robinhood.com/options/positions/e18fda89-6ff2-443f-af71-cd780e558049/",
//       "ratio_quantity": 1
//     }
//   ],
//   "id": "e4e6cabe-2328-42f3-b4d9-d78da695d2ec",
//   "quantity": "35.0000"
// }

options_orders

Obtain list of history of option orders

var credentials = require("../credentials.js")();
var Robinhood = require('robinhood')(credentials, function() {
    Robinhood.options_orders((err, response, body) => {
        if (err) {
            console.error(err);
        } else {
            console.log(body);
        }
    });
});

options_dates

Obtain list of options expirations for a ticker

var credentials = require("../credentials.js")();
var Robinhood = require('robinhood')(credentials, function() {
    Robinhood.options_positions("MSFT", (err, response, {tradable_chain_id, expiration_dates}) => {
        if (err) {
            console.error(err);
        } else {
            // Expiration dates is [<Date String>] ordered by asc date ([0] would be more recent than [1])
            Robinhood.options_available(tradable_chain_id, expiration_dates[0])
        }
    });
});

options_available

Obtain list of options expirations for a ticker

var credentials = require("../credentials.js")();
var Robinhood = require('robinhood')(credentials, function() {
    Robinhood.options_positions("MSFT", (err, response, {tradable_chain_id, expiration_dates}) => {
        if (err) {
            console.error(err);
        } else {
            // Expiration dates is an array of date strings ordered by asc date ([0] would be more recent than [1])
            // Tradable_chain_id respresents the options identifier for a ticker
            Robinhood.options_available(tradable_chain_id, expiration_dates[0])
        }
    });
});

news(symbol, callback)

Return news about a symbol.

get_currency_pairs

Get crypto - currency pairs

var credentials = require("../credentials.js")();
var Robinhood = require('robinhood')(credentials, function() {
    Robinhood.get_currency_pairs((err, response, body) => {
        if (err) {
            console.error(err);
        } else {
            console.log(body);
        }
    });
});

get_crypto

Get cryptocurrency quote information from symbol

var credentials = require("../credentials.js")();
var Robinhood = require('robinhood')(credentials, function() {
    Robinhood.get_crypto('DOGE', (err, response, body) => {
        if (err) {
            console.error(err);
        } else {
            console.log(body);
        }
    });
});

Documentation lacking sample response Feel like contributing? :)

Contributors

Alejandro U. Alvarez (@aurbano)


Related Projects


Even though this should be obvious: I am not affiliated in any way with Robinhood Financial LLC. I don't mean any harm or disruption in their service by providing this. Furthermore, I believe they are working on an amazing product, and hope that by publishing this NodeJS framework their users can benefit in even more ways from working with them.

Analytics

License

FOSSA Status

robinhood-node's People

Contributors

ahansson89 avatar aurbano avatar avelizmu avatar bdoooh avatar brandonros avatar busse avatar cdituri avatar chiefsmurph avatar dustinmoorenet avatar evanshortiss avatar fossabot avatar gbochenek avatar ialexryan avatar iiredalert avatar joshuajwilborn avatar jspenc72 avatar lordloh avatar mafischer avatar nodesocket avatar patrocinio avatar prmichaelsen avatar rememberlenny avatar rokadias avatar ryanhendricks avatar swimclan avatar ted7726 avatar uladkasach avatar vantreeseba avatar yura505 avatar z123 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

robinhood-node's Issues

How to instantiate?

The README.md shows:

rh = Robinhood(credentials);

Though seems like it should be:

Robinhood(credentials, function(error, broker) {
    if(error) {
        return callback(error);
    }

    callback(null, broker);
});

What is recommended?

oco order type?

The README makes mention of an oco order type. Has that been tested and if so is there an example of how to call that? Is it two consecutive orders or different parameters sent in one?

No error returned in callback

quote_data does not return error in callback.

let symbol = 'AAPL';
rh.quote_data(symbol, function(error, response, body) {
    // error does not seem to be set even though an error occurred
    // for example provided invalid login credentials
}

Automatically apply `.toUpper()` anywhere passing in a stock/symbol

Seems like the stock parameter in quote_data() is case-sensitive which it should not be.

โžœ  node quotes --stock AAPL
{ results:
   [ { ask_price: '96.9100',
       ask_size: 4100,
       bid_price: '96.9000',
       bid_size: 400,
       last_trade_price: '96.9100',
       last_extended_hours_trade_price: '96.8900',
       previous_close: '96.7600',
       adjusted_previous_close: '96.7600',
       previous_close_date: '2016-02-25',
       symbol: 'AAPL',
       trading_halted: false,
       updated_at: '2016-02-26T21:00:00Z' } ] }

StatusCode: 200
โžœ  node quotes --stock aapl
undefined

StatusCode: 400

Anybody else think we should automatically apply .toUpper() anywhere in this package we are passing in a stock/symbol?

Unable to login anymore

Seems like they changed mfa_code way to oauth2.

Currently this code fails

var credentials = require("../credentials.js")();
var Robinhood = require('robinhood')(credentials, function(){
    console.log(Robinhood.auth_token());
        //      <authenticated alphanumeric token>
}

Error is :

          throw new Error('token not found ' + JSON.stringify(httpResponse))
          ^

Error: token not found {"statusCode":404,"body":"<h1>Not Found</h1><p>The requested URL /api-token-auth/ was not found on this server.</p>","headers":{"date":"Thu, 20 Sep 2018 03:05:48 GMT","content-type":"text/html; charset=utf-8","content-length":"89","connection":"keep-alive","server":"nginx","vary":"Accept-Language, Cookie","x-robinhood-api-version":"1.246.7","content-language":"en-us"},"request":{"uri":{"protocol":"https:","slashes":true,"auth":null,"host":"api.robinhood.com","port":443,"hostname":"api.robinhood.com","hash":null,"search":null,"query":null,"pathname":"/api-token-auth/","path":"/api-token-auth/","href":"https://api.robinhood.com/api-token-auth/"},"method":"POST","headers":{"Accept":"*/*","Accept-Encoding":"gzip, deflate","Accept-Language":"en;q=1, fr;q=0.9, de;q=0.8, ja;q=0.7, nl;q=0.6, it;q=0.5","Content-Type":"application/x-www-form-urlencoded; charset=utf-8","Connection":"keep-alive","X-Robinhood-API-Version":"1.152.0","User-Agent":"Robinhood/5.32.0 (com.robinhood.release.Robinhood; build:3814; iOS 10.3.3)","content-length":41}}}

Error: "{ account: [ 'This field is required.' ] }"

Code being executed:

var Robinhood = require('../src/robinhood');

var options = {
    bid_price: "3.66",
    quantity: "1",
    instrument: {
        url: "https://api.robinhood.com/instruments/ff32040e-70d7-4357-9e97-edac4a8c2cdc/",
        symbol: "SID"
    }
}


var rh = Robinhood({username:'username', password:'password'}, function(){

    rh.place_buy_order(options, function(error, response, body){
        console.log(body);
    });

});

According to the docs and the things I've read, this is the correct way to authenticate, yet I still get the error "{ account: [ 'This field is required.' ] }" when I run the above code. Any ideas?

README.md is innaccurate with regard to order triggers & time

For awareness, these sections of the README.md are inaccurate:

https://github.com/aurbano/robinhood-node#trigger
https://github.com/aurbano/robinhood-node#time
https://github.com/aurbano/robinhood-node#trigger-1
https://github.com/aurbano/robinhood-node#time-1

What is described as triggers are actually time in force, and vice versa. There is a trigger of stop as well, and possibly on_close (on market close, need to test). There may also be other viable time values (fok, ioc...).

Most of this I am getting from: https://github.com/sanko/Finance-Robinhood/blob/master/lib/Finance/Robinhood/Order.pm

I am working on a README.md update to correct this which I will submit a PR for once I test all the options from the perl library above.

updated_at at the millisecond

Since prices for securities can change within the same second, is there any way to get the updated_at string at the millisecond?

I am getting price changes within the same updated_at time.

jg

Catch Authentication Errors

What is the correct way to catch errors on login? If someone enters incorrect credentials, the module throws an error, but I'm unable to catch them and the script crashes. Has anyone successfully done this?

Code being executed:

      try{
         var Robinhood = require('robinhood')({
              username : username,
              password : password
          }, function(result){
                console.log("Login callback", result);
            });
       } catch (e) {
            console.log("ERROR:",e);
       }
/opt/bitnami/apache2/htdocs/node_modules/robinhood/src/robinhood.js:141
          throw new Error(
          ^

Error: token not found {"statusCode":400,"body":{"detail":"Unable to log in with provided credentials."},"headers":{"date":"Fri, 14 Sep 2018 00:55:06 GMT","content-type":"application/json","content-length":"56","connection":"keep-alive","server":"nginx","content-language":"en-us","x-robinhood-api-version":"1.244.14","vary":"Accept-Language, Cookie","allow":"POST, OPTIONS"},"request":{"uri":{"protocol":"https:","slashes":true,"auth":null,"host":"api.robinhood.com","port":443,"hostname":"api.robinhood.com","hash":null,"search":null,"query":null,"pathname":"/oauth2/token/","path":"/oauth2/token/","href":"https://api.robinhood.com/oauth2/token/"},"method":"POST","headers":{"Accept":"*/*","Accept-Encoding":"gzip, deflate","Accept-Language":"en;q=1, fr;q=0.9, de;q=0.8, ja;q=0.7, nl;q=0.6, it;q=0.5","Content-Type":"application/x-www-form-urlencoded; charset=utf-8","Connection":"keep-alive","X-Robinhood-API-Version":"1.152.0","User-Agent":"Robinhood/5.32.0 (com.robinhood.release.Robinhood; build:3814; iOS 10.3.3)","content-length":134}}}
    at Request._callback (/opt/bitnami/apache2/htdocs/node_modules/robinhood/src/robinhood.js:141:17)
    at Request.self.callback (/opt/bitnami/apache2/htdocs/node_modules/request/request.js:185:22)
    at emitTwo (events.js:126:13)
    at Request.emit (events.js:214:7)
    at Request.<anonymous> (/opt/bitnami/apache2/htdocs/node_modules/request/request.js:1161:10)
    at emitOne (events.js:116:13)
    at Request.emit (events.js:211:7)
    at IncomingMessage.<anonymous> (/opt/bitnami/apache2/htdocs/node_modules/request/request.js:1083:12)
    at Object.onceWrapper (events.js:313:30)
    at emitNone (events.js:111:20)
    at IncomingMessage.emit (events.js:208:7)

stop_price: options.stop_price needed to enter a stop* order

To do a stop limit, stop loss, etc, _place_order() should have a stop_price field:

var _place_order = function(options, callback){
    return _request.post({
        uri: _endpoints.orders,
        form: {
          account: _private.account,
          instrument: options.instrument.url,
          price: options.bid_price,
          stop_price: options.stop_price,
          quantity: options.quantity,
          side: options.transaction,
          symbol: options.instrument.symbol.toUpperCase(),
          time_in_force: options.time || 'gfd',
          trigger: options.trigger || 'immediate',
          type: options.type || 'market'
        }
      }, callback);
  };

I've added it to my fork, successfully creating a stop loss order:

{ updated_at: '2016-05-02T02:47:08.291979Z',
       ref_id: null,
       time_in_force: 'gtc',
       fees: '0.00',
       cancel: 'https://api.robinhood.com/orders/71037bf1-a506-4fac-aa60-XXX/cancel/',
       id: '71037bf1-a506-4fac-aa60-XXX',
       cumulative_quantity: '0.00000',
       stop_price: '7.31000000',
       reject_reason: null,
       instrument: 'https://api.robinhood.com/instruments/3a47ca97-d5a2-4a55-9045-053a588894de/',
       state: 'queued',
       trigger: 'stop',
       type: 'market',
       last_transaction_at: '2016-05-02T02:47:08.235593Z',
       price: null,
       executions: [],
       account: 'https://api.robinhood.com/accounts/ABCD1234/',
       url: 'https://api.robinhood.com/orders/71037bf1-a506-4fac-aa60-XXX/',
       created_at: '2016-05-02T02:47:08.235593Z',
       side: 'sell',
       position: 'https://api.robinhood.com/accounts/ABCD1234/positions/3a47ca97-d5a2-4a55-9045-XXX/',
       average_price: null,
       quantity: '3.00000' }

I have verified this in the UI & am working on a pull request

Angular 6 & robinhood mass ERRORS :'(

Hey guys,
Just upgraded to Angular 6 using @angular/cli. After npm install robinhood --save and implementing it in the simplest way I get a bunch of errors:

import { Component } from '@angular/core';
import { robinhood } from 'robinhood';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.sass']
})
export class AppComponent {
  constructor() {
    console.log(robinhood)
  }
}
ERROR in ./node_modules/aws-sign2/index.js
Module not found: Error: Can't resolve 'crypto' in '/node_modules/aws-sign2'
ERROR in ./node_modules/aws4/aws4.js
Module not found: Error: Can't resolve 'crypto' in '/node_modules/aws4'
ERROR in ./node_modules/ecc-jsbn/index.js
Module not found: Error: Can't resolve 'crypto' in '/node_modules/ecc-jsbn'
ERROR in ./node_modules/http-signature/lib/signer.js
Module not found: Error: Can't resolve 'crypto' in '/node_modules/http-signature/lib'
ERROR in ./node_modules/http-signature/lib/verify.js
Module not found: Error: Can't resolve 'crypto' in '/node_modules/http-signature/lib'
ERROR in ./node_modules/oauth-sign/index.js
Module not found: Error: Can't resolve 'crypto' in '/node_modules/oauth-sign'
ERROR in ./node_modules/request/lib/oauth.js
Module not found: Error: Can't resolve 'crypto' in '/node_modules/request/lib'
ERROR in ./node_modules/request/lib/helpers.js
Module not found: Error: Can't resolve 'crypto' in '/node_modules/request/lib'
ERROR in ./node_modules/sshpk/lib/utils.js
Module not found: Error: Can't resolve 'crypto' in '/node_modules/sshpk/lib'
ERROR in ./node_modules/sshpk/lib/dhe.js
Module not found: Error: Can't resolve 'crypto' in '/node_modules/sshpk/lib'
ERROR in ./node_modules/sshpk/lib/identity.js
Module not found: Error: Can't resolve 'crypto' in '/node_modules/sshpk/lib'
ERROR in ./node_modules/sshpk/lib/private-key.js
Module not found: Error: Can't resolve 'crypto' in '/node_modules/sshpk/lib'
ERROR in ./node_modules/sshpk/lib/signature.js
Module not found: Error: Can't resolve 'crypto' in '/node_modules/sshpk/lib'
ERROR in ./node_modules/sshpk/lib/fingerprint.js
Module not found: Error: Can't resolve 'crypto' in '/node_modules/sshpk/lib'
ERROR in ./node_modules/sshpk/lib/key.js
Module not found: Error: Can't resolve 'crypto' in '/node_modules/sshpk/lib'
ERROR in ./node_modules/sshpk/lib/certificate.js
Module not found: Error: Can't resolve 'crypto' in '/node_modules/sshpk/lib'
ERROR in ./node_modules/sshpk/lib/formats/openssh-cert.js
Module not found: Error: Can't resolve 'crypto' in '/node_modules/sshpk/lib/formats'
ERROR in ./node_modules/sshpk/lib/formats/ssh-private.js
Module not found: Error: Can't resolve 'crypto' in '/node_modules/sshpk/lib/formats'
ERROR in ./node_modules/sshpk/lib/formats/pem.js
Module not found: Error: Can't resolve 'crypto' in '/node_modules/sshpk/lib/formats'
ERROR in ./node_modules/request/lib/har.js
Module not found: Error: Can't resolve 'fs' in '/node_modules/request/lib'
ERROR in ./node_modules/forever-agent/index.js
Module not found: Error: Can't resolve 'http' in '/node_modules/forever-agent'
ERROR in ./node_modules/http-signature/lib/signer.js
Module not found: Error: Can't resolve 'http' in '/node_modules/http-signature/lib'
ERROR in ./node_modules/request/request.js
Module not found: Error: Can't resolve 'http' in '/node_modules/request'
ERROR in ./node_modules/tunnel-agent/index.js
Module not found: Error: Can't resolve 'http' in '/node_modules/tunnel-agent'
ERROR in ./node_modules/forever-agent/index.js
Module not found: Error: Can't resolve 'https' in '/node_modules/forever-agent'
ERROR in ./node_modules/request/request.js
Module not found: Error: Can't resolve 'https' in '/node_modules/request'
ERROR in ./node_modules/tunnel-agent/index.js
Module not found: Error: Can't resolve 'https' in '/node_modules/tunnel-agent'
ERROR in ./node_modules/forever-agent/index.js
Module not found: Error: Can't resolve 'net' in '/node_modules/forever-agent'
ERROR in ./node_modules/tough-cookie/lib/cookie.js
Module not found: Error: Can't resolve 'net' in '/node_modules/tough-cookie/lib'
ERROR in ./node_modules/tunnel-agent/index.js
Module not found: Error: Can't resolve 'net' in '/node_modules/tunnel-agent'
ERROR in ./node_modules/mime-types/index.js
Module not found: Error: Can't resolve 'path' in '/node_modules/mime-types'
ERROR in ./node_modules/assert-plus/assert.js
Module not found: Error: Can't resolve 'stream' in '/node_modules/assert-plus'
ERROR in ./node_modules/combined-stream/lib/combined_stream.js
Module not found: Error: Can't resolve 'stream' in '/node_modules/combined-stream/lib'
ERROR in ./node_modules/delayed-stream/lib/delayed_stream.js
Module not found: Error: Can't resolve 'stream' in '/node_modules/delayed-stream/lib'
ERROR in ./node_modules/isstream/isstream.js
Module not found: Error: Can't resolve 'stream' in '/node_modules/isstream'
ERROR in ./node_modules/request/request.js
Module not found: Error: Can't resolve 'stream' in '/node_modules/request'
ERROR in ./node_modules/sshpk/lib/ed-compat.js
Module not found: Error: Can't resolve 'stream' in '/node_modules/sshpk/lib'
ERROR in ./node_modules/forever-agent/index.js
Module not found: Error: Can't resolve 'tls' in '/node_modules/forever-agent'
ERROR in ./node_modules/tunnel-agent/index.js
Module not found: Error: Can't resolve 'tls' in '/node_modules/tunnel-agent'
ERROR in ./node_modules/request/request.js
Module not found: Error: Can't resolve 'zlib' in '/node_modules/request'

Day Trades

Is there a way to find the current number of day trades and what they are?

Account numbers iOS App vs. JSON don't add up?

So here is a screenshot of the app vs the JSON output from the .accounts call. I can't figure out how to correlate these numbers. None of them seem to add up. ( I have a 2-1 margin 'gold' account ).

JSON

APP

Is the .accounts call supposed to return this type of information or am I missing something and should be calling a different method?

Thanks,

Margin (Gold) buying power for penny stocks.

Code being executed:

var Robinhood = require('robinhood')(credentials, function(){
    Robinhood.accounts(function(err, response, body){
        if(err){
            console.error(err);
        }else{
            console.log("accounts");

            // This returns the margin buying power
            console.log(body.results[0].margin_balances.unallocated_margin_cash);
         
        }
    })
});

Expected result

// Buying power for a specific stock

Actual behaviour

// The full buying power

Reproducing

// I know the account will always return the full margin buying power, but how do I get the margin buying power for a particular stock? Namely, penny stocks.

Get NASDAQ Composite quote

Any idea how to get a NASDAQ Composite quote?

I tried:

IXIC
.IXIC (Google) [https://www.google.com/finance?q=INDEXNASDAQ%3A.IXIC]
^IXIC (Yahoo) [http://finance.yahoo.com/q?uhb=uhb2&fr=uh3_finance_vert_gs&type=2button&s=%5EIXIC%2C]

Just not sure what Robinhood is using as the symbol.

Instruments method fails with no method "upper"

With the following code I get the error:

TypeError: Object GOOG has no method 'upper'
    at Object.RobinhoodWebApi.api.instruments (/Users/tomcaflisch/Sites/robinhood-riches/node_modules/robinhood/src/robinhood.js:116:29)
...
const Robinhood = require('robinhood');
const credentials = require('./credentials');

const trader = Robinhood(credentials, function() {
  trader.quote_data('NYMX', function(err, httpResponse, body) {
    if(err) {
      console.error(err);
      return;
    }
    console.log('Quote data = ', body);
  });

  trader.instruments('NYMX', function(err, httpResponse, body) {
    console.log('err = ', err);
    console.log('instruments = ', body);
  });
});

How to authenticate

I am having trouble authenticating a user. I have tried the following but the API is rejecting it:

Robinhood({username:'myusername', password:'mypassword'});

Any idea what I am doing wrong?

Top Ten Stocks

Hi I just started using this API. I want to test it out first before I implement anything.

Im trying to use top ten stocks tag function, am i calling this function correctly?


var Robinhood = require('robinhood')(credentials, function() {
    Robinhood.tag(TopTen,function(err, response, body){
        if(err){
            console.error(err);
        }else{
            console.log('top ten');
            console.log(body);
        }
    })
});

Getting an error.

Not Found

The requested URL /tags/tag/TopTen/ was not found on this server.

Also how are the requests being made and how many requests can you make per day?
Thanks

Update LICENSE file to MIT

The package.json says this project is MIT, but the repo contains a LICENSE file stating it is the GNU AFFERO GENERAL PUBLIC LICENSE.

Which is correct? Either the package.json needs to state SEE LICENSE IN LICENSE, or the LICENSE file should be MIT, right?

unable to place orders during extended hours

https://github.com/sanko/Robinhood/blob/master/Order.md

for pre-market and after hours, orders must include extended_hours: true or they will show up as "Queued" instead of "Placed"

one way to handle this is to always include that key pair for all orders.
another way to handle this is to use Object.assign (or object spread .. compatibility?) to include all passed in key pairs to Robinhood.place_buy_order(options) in the form data when making the request...

https://github.com/aurbano/robinhood-node/blob/master/src/robinhood.js#L313

How'd you reverse-engineer this?

Interested in hearing what process you took to develop this. Did you setup a MITM proxy from your mobile device and look at request data? What tool(s) did you find handy (like Charles?)? Any tips for those trying to reverse-engineer Robinhood API / send more PRs to help this one on setting up MITM proxy or whichever route you took (i.e. anything you had to do to get around the SSL pinning etc) :)

Add options functionality

Would be fantastic to add options functionality. Specifically:

  • get options order history
  • place 1 leg option orders
  • place multi-leg option orders

Need to call callback in init function

We need to call the init callback otherwise we can't wait for the login to finish. I have a fix, I just need the issue opened to reference it in the pull request.

Cancel an order by order id

It should be possible to cancel an order by specifying the order id, rather than needing the full order object.

The uri request https://api.robinhood.com/orders/<order_id>/cancel is easily buildable.

'Invalid Token' response

I am getting intermittent { detail: 'Invalid token' } responses from the API when making use of the .url method to get an instrument object from an instrument URL. Here is an example instrument URL that I am using that will fail with the above message intermittently:

https://api.robinhood.com/instruments/80cd401e-7b50-4372-8a1f-a8562971962a/

Could this be related to my login token with the API? I am making several consecutive calls to the API with my credentials and wonder if the expire is causing this to fail? Does the token need to be refreshed? The intermittent nature of this issue makes me think that time has something to do with it...

Buying Power doesn't match app

The app says my account's buying power is $2.41. Node is returning: buying_power: '0.0000',
Has anyone else run into this?

Inconsistent `body.results`, err at `/src/robinhood.js:147`

Code being executed:

$ node app.js 
Robinhood web app listening on port 5010!

Expected result

The data from the requested endpoint.

Actual behaviour

(node:10455) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): [object Object]
(node:10455) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 2): Error: getaddrinfo ENOTFOUND api.robinhood.com api.robinhood.com:443
/Users/alexanderpholland/robinhood-web-app/server/node_modules/robinhood/src/robinhood.js:147
if (body.results) {
^

TypeError: Cannot read property 'results' of undefined
at Request._callback (/Users/alexanderpholland/robinhood-web-app/server/node_modules/robinhood/src/robinhood.js:147:17)
at self.callback (/Users/alexanderpholland/robinhood-web-app/server/node_modules/request/request.js:186:22)
at emitOne (events.js:96:13)
at Request.emit (events.js:188:7)
at Request.onRequestError (/Users/alexanderpholland/robinhood-web-app/server/node_modules/request/request.js:878:8)
at emitOne (events.js:96:13)
at ClientRequest.emit (events.js:188:7)
at TLSSocket.socketErrorListener (_http_client.js:310:9)
at emitOne (events.js:96:13)
at TLSSocket.emit (events.js:188:7)

Reproducing

Call the /accounts endpoints.

// Please provide a bit of context for the code snippet, were you authenticated?

Was authenticated and using token to request.

Authentication Models

Does the RH API support OAuth or SAML SSO authentication methods? Or is sending a clear-text username and password the only way to authenticate an account? I couldnt find anything in their documentation but thought I would ask anyway.

Documentation: TypeError: Robinhood is not a function

// Below is an issue template, feel free to modify it

Code being executed:

var Robinhood = require('robinhood')(credentials, function(){

    //Robinhood is connected and you may begin sending commands to the api.

    Robinhood(null).quote_data('GOOG', function(error, response, body) {
        if (error) {
            console.error(error);
            process.exit(1);
        }
        console.log(body);
    });

});

Expected result

See GOOG's quote
// A little explanation, sample response JSON...

Actual behaviour

// Either the error you received, or the JSON that was returned
Eduardos-MBP:robinhood edu$ node robinhood.js
/Users/edu/github/robinhood/robinhood.js:12
Robinhood(null).quote_data('GOOG', function(error, response, body) {
^

TypeError: Robinhood is not a function
at /Users/edu/github/robinhood/robinhood.js:12:5
at /Users/edu/node_modules/robinhood/src/robinhood.js:86:18
at Request._callback (/Users/edu/node_modules/robinhood/src/robinhood.js:126:18)
at Request.self.callback (/Users/edu/node_modules/robinhood/node_modules/request/request.js:186:22)
at emitTwo (events.js:87:13)
at Request.emit (events.js:172:7)
at Request. (/Users/edu/node_modules/robinhood/node_modules/request/request.js:1081:10)
at emitOne (events.js:77:13)
at Request.emit (events.js:169:7)
at IncomingMessage. (/Users/edu/node_modules/robinhood/node_modules/request/request.js:1001:12)

Reproducing

// Please provide a bit of context for the code snippet, were you authenticated?
The line

Robinhood(null).quote_data('GOOG', function(error, response, body) {

should be

Robinhood.quote_data('GOOG', function(error, response, body) {

Possible values for order `type`

What are the possible values for the type option here?

{
    bid_price: Number,
    quantity: Number,
    instrument: {
        url: String,
        symbol: String
    },
    // Optional:
    trigger: String, // Defaults to "gfd" (Good For Day)
    time: String,    // Defaults to "immediate"
    // this one below โ†“
    type: String     // Defaults to "market"
   // this one ^^^
}

API Updates and Promise Support

I've used this wrapper to perform some simple interactions with the Robinhood API and have a few things on a wishlist that would improve developer experience (IMO). These changes would mean a breaking 2.0 change so it's not a small piece of work, but I'd like to hear your thoughts.

Response Structure

Presently, the library uses request format callbacks because under the covers it's wrapping using the request module. That means I need to check res.statusCode and body in my callback.

It would be great if the library instead gave me just what I want - the response body JSON or a structured error like this

api.positions((err, json) => {
  // just provided json and error (if defined), no need to check res.statusCode since 
  // the library verifies it is a 200 for me and just gives me json
})

This would work great with TypeScript since each response type could be defined for code completion and documentation and you'd also be able to declare robinhood types elsewhere as arguments throughout your code, like so:

function doSomethingWithPositions (p: RobinhoodPositions) {
  // I now have intellisense for p and know its structure
}

Promise Support

Having promise support would be great.

return Promise.props([
  positions: api.positions(),
  user: api.user()
])
  .then(results => {
    // results.user
    // results.positions
  })
  .catch(e => { // catch all errors })

Along with the usual Promise benefits, it would allow using async/await for cleaner code in newer node versions:

try {
  const positions = await api.positions()
  const user = await api.user()
} catch (e) {
  // catch all errors
}

Refined Error Checks

Currently all error handling is deferred to the developer, i.e I, as a developer, always need to check status codes but the library could easily do this:

api.positions((err, res, positions) => {
  if (err) {
    // Check error type, handle appropriately
    console.log('error making https call for permissions. could be a connectivity issue')
    console.log(err)
  } else if (res.statusCode !== 200) {
    // Handle status code type
    console.log('error response returned from robinhood')
    console.log(res.statusCode)
    console.log(body)
  } else {
    // Awesome, it worked
    console.log(positions)
  }
})

It would be great instead if the library checked the status code for me:

api.positions((err, positions) => {
  if (err) {
    // something happened, either non 200 status or connectivity issue
  } else {
      console.log(positions)
  }
})

We could extend it so specific error classes are used so developers can identify errors easily:

    if (err instanceof robinhood.RestApiError) {
      // used when the API returns non 200 status or unexpected response format
      // the error could have "res" from request attached if the developer need more info
    } else if (err instanceof robinhood.CommunicationError)  {
      // passed when "err" param in request callback was non null
      // the original error could be attached too for extra info
    } else {
      // generic/unknown error handling
    }

Example of how to authenticate?

Unfortunately, there is no example of how to authenticate with Robinhood.

I guess this would be the correct way of doing it?

Robinhood({
  username: 'username'
  password: 'password'
}).orders(function () {});

Thanks for your efforts!

`._set_account()` error - likely for new accounts

I just created an account today w/ Robinhood and it has not been approved yet. This may be the cause of the error.

Code being executed:


var credentials = require("./config/robinhood.json");
var Robinhood = require('robinhood')(credentials, function(){
    console.log(Robinhood.auth_token());
        //      <authenticated alphanumeric token>
});

Expected result

Expected result is to get the token, such as demonstrated in the example

Actual behaviour

Getting this error:

/var/www/git/Trading/workhorse/node_modules/robinhood/src/robinhood.js:149
          _private.account = body.results[0].url;
                                            ^

TypeError: Cannot read property 'url' of undefined
    at Request._callback (/var/www/git/Trading/workhorse/node_modules/robinhood/src/robinhood.js:149:45)
    at Request.self.callback (/var/www/git/Trading/workhorse/node_modules/request/request.js:186:22)
    at emitTwo (events.js:125:13)
    at Request.emit (events.js:213:7)
    at Request.<anonymous> (/var/www/git/Trading/workhorse/node_modules/request/request.js:1163:10)
    at emitOne (events.js:115:13)
    at Request.emit (events.js:210:7)
    at IncomingMessage.<anonymous> (/var/www/git/Trading/workhorse/node_modules/request/request.js:1085:12)
    at Object.onceWrapper (events.js:314:30)
    at emitNone (events.js:110:20)
    at IncomingMessage.emit (events.js:207:7)
    at endReadableNT (_stream_readable.js:1047:12)
    at _combinedTickCallback (internal/process/next_tick.js:102:11)
    at process._tickCallback (internal/process/next_tick.js:161:9)

and the data returned in the body parameter triggering the error above is

{ previous: null, results: [], next: null }

Typings for TypeScript

Would you be open to merging a PR to add a robinhood.d.ts file that enables typescript support? This could also benefit plain JS users since it would provide improved typeahead etc.

Rate limits?

AWESOME library @aurbano

Specifically talking about the quote_data method. Is there any sort of rate limiting so my IP doesn't get banned into oblivion? Is 60 requests a minute per SYMBOL reasonable?

I tried to do some due diligence, but I wasn't lucky in finding any documentation on any sort of rate limit.

Please and thank you!

Best,
Austin

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.