Giter Club home page Giter Club logo

drive-wealth's Introduction

DriveWealth

Installation

Add this line to your application's Gemfile:

gem 'drive_wealth', github: 'stockflare/drive-wealth', tag: '0.1.0'

Usage

This Gem wraps all interactions with The DriveWealth API into a format that is convenient for our own internal APIs.

Once installed all DriveWealth actions are objects within the DriveWealth module. Each object is initialized with the parameters required for the DriveWealth call and has one call method to execute the communications with DriveWealth. All objects return the result of the DriveWealth interaction in a response attribute that supports to_h

It is expected that most Stockflare use cases will only use the response.payload as this is a parsed version of the DriveWealth response suitable for Stockflare and it is this output that is tested. For convenience the response.payload is delivered as a Hashie::Mash to allow for method based access, for instance you can can access the status of the call by using response.payload.status.

Additionally a response.raw is provided that contains the raw DriveWealth response. This is provided for development and debug purposes only. Upstream users should only rely on the response.payload and response.messages. This will allow us to deal with minor breaking changes in the DriveWealth API (which is currently in QA) without having to make code changes in upstream users.

All Error cases are handled by raising a subclass of Trading::Errors::DriveWealthException, this object exposes a number of attributes that can you can to_h to the consumer.

Configuration Values

Two attributes need to be set

DriveWealth.configure do |config|
  config.api_uri = ENV['DriveWealth_BASE_URI']
  config.api_key = ENV['DriveWealth_API_KEY']
end

Brokers

We current support the following broker symbols

{
  drive_wealth: 'DriveWealth'
}

Order Actions

{
  buy: 'buy',
  sell: 'sell',
  buy_to_cover: 'buyToCover',
  sell_short: 'sellShort'
}

Price Types

{
  market: 'market',
  limit: 'limit',
  stop_market: 'stopMarket',
  stop_limit: 'stopLimit'
}

Order Expirations

{
  day: 'day',
  gtc: 'gtc'
}

Note that the test user does not support type :gtc

DriveWealth::User::Link

Get a Users oAuth token

Example Call:

DriveWealth::User::Link.new(
  username: username,
  password: password,
  broker: broker
).call.response

Successful response:

{:raw=>
  {"appTypeID"=>28,
   "commissionRate"=>2.99,
   "loginState"=>1,
   "referralCode"=>"LTJVND",
   "sessionKey"=>
    "628f9e2b-6acb-4d6f-9fff-63c93d23d9d0.2016-04-28T09:03:21.908Z",
   "userID"=>"628f9e2b-6acb-4d6f-9fff-63c93d23d9d0",
   "wlpID"=>"DW",
   "accounts"=>
    [{"accountID"=>"628f9e2b-6acb-4d6f-9fff-63c93d23d9d0.1461255011955",
      "accountNo"=>"DPNL000006",
      "userID"=>"628f9e2b-6acb-4d6f-9fff-63c93d23d9d0",
      "accountType"=>1,
      "cash"=>10000,
      "currencyID"=>"USD",
      "defaultGoalID"=>"19e2709a-94f1-4bbd-9265-e5981d2b57f2",
      "freeTradeBalance"=>0,
      "goodFaithViolations"=>0,
      "ibID"=>"152b3a46-1bc4-4d1e-93a5-ca6f79110d14",
      "interestFree"=>false,
      "margin"=>1,
      "nickname"=>"Shane's Practice Account",
      "openedWhen"=>"2016-04-21T16:10:11Z",
      "goals"=>[],
      "orders"=>[],
      "patternDayTrades"=>0,
      "positions"=>[],
      "status"=>2,
      "tradingType"=>"C",
      "createdWhen"=>"2016-04-21T16:10:11.955Z",
      "bodMoneyMarket"=>10000,
      "bodEquityValue"=>0,
      "bodCashAvailForWith"=>10000,
      "bodCashAvailForTrading"=>10000,
      "bodUpdatedWhen"=>"2016-04-28T07:18:06.602Z",
      "rtCashAvailForTrading"=>10000.0,
      "rtCashAvailForWith"=>10000.0,
      "commissionSchedule"=>
       {"baseRate"=>2.99,
        "baseShares"=>239,
        "excessRate"=>0.0125,
        "fractionalRate"=>0.99},
      "accountMgmtType"=>0,
      "bodSmaBal"=>0,
      "bodExReq"=>0,
      "bodBpx"=>0,
      "bodTcashBal"=>0,
      "bodEquity"=>0,
      "bodHoReq"=>0,
      "bodMoneyMkt"=>0,
      "longOnly"=>true}],
   "instruments"=>[],
   "guest"=>false},
 :status=>200,
 :payload=>
  {"type"=>"success",
   "user_id"=>"628f9e2b-6acb-4d6f-9fff-63c93d23d9d0",
   "user_token"=>
    "628f9e2b-6acb-4d6f-9fff-63c93d23d9d0.2016-04-28T09:03:21.908Z"},
 :messages=>["success"]}

Link failure will raise a Trading::Errors::LoginException with the following attributes:

{ type: :error,
  code: 500,
  description: 'Could Not Login',
  messages: ['Check your username and password and try again.'] }

DriveWealth::User::Login

example call:

DriveWealth::User::Login.new(
  user_id: user_id,
  user_token: user_token
).call.response

Successful response without security question:

{:raw=>
  {"appTypeID"=>28,
   "appVersion"=>"0.1.9",
   "commissionRate"=>2.99,
   "heartbeatWhen"=>"2016-04-28T09:36:19.243Z",
   "ipAddress"=>"86.3.238.56",
   "loginState"=>1,
   "languageID"=>"en_US",
   "loginWhen"=>"2016-04-28T09:36:19.243Z",
   "osType"=>"Linux",
   "osVersion"=>"Ubuntu 64",
   "referralCode"=>"LTJVND",
   "scrRes"=>"1920x1080",
   "sessionKey"=>
    "628f9e2b-6acb-4d6f-9fff-63c93d23d9d0.2016-04-28T09:36:19.243Z",
   "userID"=>"628f9e2b-6acb-4d6f-9fff-63c93d23d9d0",
   "wlpID"=>"DW",
   "accounts"=>
    [{"accountID"=>"628f9e2b-6acb-4d6f-9fff-63c93d23d9d0.1461255011955",
      "accountNo"=>"DPNL000006",
      "userID"=>"628f9e2b-6acb-4d6f-9fff-63c93d23d9d0",
      "accountType"=>1,
      "cash"=>10000,
      "currencyID"=>"USD",
      "defaultGoalID"=>"19e2709a-94f1-4bbd-9265-e5981d2b57f2",
      "freeTradeBalance"=>0,
      "goodFaithViolations"=>0,
      "ibID"=>"152b3a46-1bc4-4d1e-93a5-ca6f79110d14",
      "interestFree"=>false,
      "margin"=>1,
      "nickname"=>"Shane's Practice Account",
      "openedWhen"=>"2016-04-21T16:10:11Z",
      "goals"=>[],
      "orders"=>[],
      "patternDayTrades"=>0,
      "positions"=>[],
      "status"=>2,
      "tradingType"=>"C",
      "createdWhen"=>"2016-04-21T16:10:11.955Z",
      "bodMoneyMarket"=>10000,
      "bodEquityValue"=>0,
      "bodCashAvailForWith"=>10000,
      "bodCashAvailForTrading"=>10000,
      "bodUpdatedWhen"=>"2016-04-28T07:18:06.602Z",
      "rtCashAvailForTrading"=>10000.0,
      "rtCashAvailForWith"=>10000.0,
      "accountMgmtType"=>0,
      "bodSmaBal"=>0,
      "bodExReq"=>0,
      "bodBpx"=>0,
      "bodTcashBal"=>0,
      "bodEquity"=>0,
      "bodHoReq"=>0,
      "bodMoneyMkt"=>0,
      "longOnly"=>true}],
   "instruments"=>[],
   "guest"=>false},
 :status=>200,
 :payload=>
  {"type"=>"success",
   "token"=>"628f9e2b-6acb-4d6f-9fff-63c93d23d9d0.2016-04-28T09:36:19.243Z",
   "accounts"=>
    [{"account_number"=>"DPNL000006",
      "name"=>"Shane's Practice Account",
      "cash"=>nil,
      "power"=>nil,
      "day_return"=>nil,
      "day_return_percent"=>nil,
      "total_return"=>nil,
      "total_return_percent"=>nil,
      "value"=>nil}]},
 :messages=>["success"]}

Security Questions are not supported in DriveWealth

Login failure will raise a Trading::Errors::LoginException with the following attributes:

{ type: :error,
  code: 500,
  description: 'Could Not Login',
  messages: ['Check your username and password and try again.'] }

DriveWealth::User::Verify

DriveWealth does not support security questions. A call to this endpoint will return results identical to DriveWealth::User::Login regardless of the security answer provided

Example Call

DriveWealth::User::Verify.new(
  token: <token from DriveWealth::User::Login>,
  answer: answer
).call.response

All success responses are identical to DriveWealth::User::Login

If the user provides a bad answer then the response will be a success asking another question.

A failure will raise a Trading::Errors::LoginException with the similar attributes:

{ type: :error,
  code: 500,
  description: 'Could Not Complete Your Request',
  messages: ['Your session has expired. Please try again'] }

DriveWealth::User::Account

Get the current financial state of an account

Example Call

DriveWealth::User::Account.new(
  token: <token from DriveWealth::User::Login>,
  account_number: account_number
).call.response

Example response

{:raw=>
  {"availableCash"=>1204.06,
   "buyingPower"=>2408.12,
   "dayAbsoluteReturn"=>78.42,
   "dayPercentReturn"=>3.25,
   "longMessages"=>nil,
   "shortMessage"=>"Account Overview successfully fetched",
   "status"=>"SUCCESS",
   "token"=>"3e40016b846f4d20a4b7102a1949f893",
   "totalAbsoluteReturn"=>14486.67,
   "totalPercentReturn"=>22.84,
   "totalValue"=>76489.23},
 :status=>200,
 :payload=>
  {"type"=>"success",
   "cash"=>1204.06,
   "power"=>2408.12,
   "day_return"=>78.42,
   "day_return_percent"=>3.25,
   "total_return"=>14486.67,
   "total_return_percent"=>22.84,
   "value"=>22.84,
   "token"=>"3e40016b846f4d20a4b7102a1949f893"},
 :messages=>["Account Overview successfully fetched"]}

A failure will raise a Trading::Errors::LoginException with the similar attributes:

{ type: :error,
  code: 500,
  description: 'Could Not Complete Your Request',
  messages: ['Your session has expired. Please try again'] }

DriveWealth::User::Logout

Example call:

DriveWealth::User::Logout.new(
  token: <token from previous login>
).call.response

Successful logout response

{ raw: { 'longMessages' => nil, 'shortMessage' => nil, 'status' => 'SUCCESS', 'token' => '765b7e4056334a27a9b65033b889878e' },
  status: 200,
  payload: { type: 'success', token: '765b7e4056334a27a9b65033b889878e', accounts: nil },
  messages: [] }

Failed Logout will raise a Trading::Errors::LoginException with similar attributes:

{ type: :error,
  code: 500,
  description: 'Could Not Complete Your Request',
  messages: ['Your session has expired. Please try again'] }

DriveWealth::User::Refresh

Used to stop a users token from expiring, does not send you a new token

Example Call:

DriveWealth::User::Refresh.new(
  token: token
).call.response

Response is identical to Trade::User::Login

Failed Logout will raise a Trading::Errors::LoginException with similar attributes:

{ type: :error,
  code: 500,
  description: 'Could Not Complete Your Request',
  messages: ['Your session has expired. Please try again'] }

DriveWealth::Position::Get

Example Call

DriveWealth::Positions::Get.new(
  token: token,
  account_number: account_number
).call.response

Successful response:

{ raw:   { 'currentPage' => 0,
           'longMessages' => nil,
           'positions' =>
    [{ 'costbasis' => 103.34,
       'holdingType' => 'LONG',
       'lastPrice' => 112.34,
       'quantity' => 1.0,
       'symbol' => 'AAPL',
       'symbolClass' => 'EQUITY_OR_ETF',
       'todayGainLossDollar' => 3.0,
       'todayGainLossPercentage' => 0.34,
       'totalGainLossDollar' => 9.0,
       'totalGainLossPercentage' => 1.2 },
      ...
     ],
           'shortMessage' => 'Position successfully fetched',
           'status' => 'SUCCESS',
           'token' => 'd3e72226aad646cea9e2d6177bd50953',
           'totalPages' => 1 },
  status: 200,
  payload:   { positions:     [{ quantity: 1, price: 103.34, ticker: 'AAPL', instrument_class: 'equity_or_etf', change: 9.0, holding: 'long' },
                               { quantity: -1, price: 103.34, ticker: 'IBM', instrument_class: 'equity_or_etf', change: 9.0, holding: 'short' },
                               { quantity: 1, price: 103.34, ticker: 'GE', instrument_class: 'equity_or_etf', change: 9.0, holding: 'short' },
                               { quantity: 1, price: 103.34, ticker: 'MSFT', instrument_class: 'equity_or_etf', change: 9.0, holding: 'long' }],
               pages: 1,
               page: 0,
               token: d3e72226aad646cea9e2d6177bd50953},
  messages: ['Position successfully fetched'] }

Failed Call will raise a Trading::Errors::PositionException with similar attributes:

{ type: :error,
  code: 500,
  description: 'Could Not Fetch Your Positions',
  messages:   ['The account foooooobaaarrrr is not valid or not active anymore.'] }

DriveWealth::Order::Preview

Example call:

DriveWealth::Order::Preview.new(
  token: token,
  account_number: account_number,
  order_action: :buy,
  quantity: 10,
  ticker: 'aapl',
  price_type: :market,
  expiration: :day,
  amount: 500,
).call.response

Successful response:

{ raw:   { 'ackWarningsList' => [],
           'longMessages' => nil,
           'orderDetails' =>
    { 'orderSymbol' => 'aapl',
      'orderAction' => 'Buy',
      'orderQuantity' => 10.0,
      'orderExpiration' => 'Day',
      'orderPrice' => 'Market',
      'orderValueLabel' => 'Estimated Cost',
      'orderMessage' => 'You are about to place a market order to buy AAPL',
      'lastPrice' => '19.0',
      'bidPrice' => '18.0',
      'askPrice' => '22.0',
      'timestamp' => 'Fri Feb 12 08:51:25 EST 2016',
      'estimatedOrderValue' => 25.0,
      'estimatedTotalValue' => 28.5,
      'buyingPower' => 1234.0,
      'longHoldings' => 12.0,
      'estimatedOrderCommission' => 3.5 },
           'orderId' => 1,
           'shortMessage' => nil,
           'status' => 'REVIEW_ORDER',
           'token' => '140784ef96214a5186041abebdfe038a',
           'warningsList' => [] },
  status: 200,
  payload:   { 'type' => 'review',
               'ticker' => 'aapl',
               'order_action' => :buy,
               'quantity' => 10,
               'expiration' => :day,
               'price_label' => 'Market',
               'value_label' => 'Estimated Cost',
               'message' => 'You are about to place a market order to buy AAPL',
               'last_price' => 19.0,
               'bid_price' => 18.0,
               'ask_price' => 22.0,
               'timestamp' => 1455285085,
               'buying_power' => 1234.0,
               'estimated_commission' => 3.5,
               'estimated_value' => 25.0,
               'estimated_total' => 28.5,
               'warnings' => [],
               'must_acknowledge' => [],
               'amount' => 500,
               'token' => '140784ef96214a5186041abebdfe038a' },
  messages: [] }

Any messages in payload.warnings must be displayed to the user.

any messages in payload.must_acknowledge must be shown to the user with check boxes that they must acknowledge

DriveWealth::Order::Place

Place an order previously reviewed by DriveWealth::Order::Preview

Example Call

DriveWealth::Order::Place.new(
  token: preview_token
).call.response

Example response

{ raw:   { 'broker' => 'your broker',
           'confirmationMessage' =>
    'Your order message 4049c988b1422d52217af9 to buy 10 shares of aapl at market price has been successfully transmitted to your broker at 12/02/16 1:19 PM EST.',
           'longMessages' => ['Transmitted succesfully to your broker'],
           'orderInfo' =>
    { 'universalOrderInfo' =>
      { 'action' => 'buy',
        'quantity' => '10',
        'symbol' => 'aapl',
        'price' => { 'type' => 'market' },
        'expiration' => 'day' },
      'action' => 'Buy',
      'quantity' => 10,
      'symbol' => 'aapl',
      'price' =>
      { 'type' => 'Market',
        'last' => 19.0,
        'bid' => 18.0,
        'ask' => 22.0,
        'timestamp' => '2016-02-12T18:19:20Z' },
      'expiration' => 'Good For The Day' },
           'orderNumber' => '4049c988b1422d52217af9',
           'shortMessage' => 'Order Successfully Submitted',
           'status' => 'SUCCESS',
           'timestamp' => '12/02/16 1:19 PM EST',
           'token' => 'dc2427db16d244e7967857cc140cf011' },
  status: 200,
  payload:   { 'type' => 'success',
               'ticker' => 'aapl',
               'order_action' => :buy,
               'quantity' => 10,
               'expiration' => :day,
               'price_label' => 'Market',
               'message' =>
    'Your order message 4049c988b1422d52217af9 to buy 10 shares of aapl at market price has been successfully transmitted to your broker at 12/02/16 1:19 PM EST.',
               'last_price' => 19.0,
               'bid_price' => 18.0,
               'ask_price' => 22.0,
               'price_timestamp' => 1_455_301_160,
               'timestamp' => 1_329_416_340,
               'order_number' => '4049c988b1422d52217af9',
               'token' => 'dc2427db16d244e7967857cc140cf011' },
  messages: ['Order Successfully Submitted'] }

Failed Call will raise a Trading::Errors::OrderException with similar attributes:

{:type=>:error,
 :code=>500,
 :broker_code=>600,
 :description=>"Could Not Complete Your Request",
 :messages=>["Your session has expired. Please try again"]}

DriveWealth::Order::Status

Get the status of all user orders or get the status of a single order

Example Call

DriveWealth::Order::Place.new(
  token: preview_token,
  account_number,
  order_number
).call.response

Omit the order_number to get the status of all orders for the account

Example response

{:raw=>
  {"accountNumber"=>"brkAcct1",
   "longMessages"=>nil,
   "orderStatusDetailsList"=>
    [{"groupOrderId"=>nil,
      "groupOrderType"=>"null",
      "groupOrders"=>[],
      "orderExpiration"=>"DAY",
      "orderLegs"=>
       [{"action"=>"BUY",
         "filledQuantity"=>0,
         "fills"=>[],
         "orderedQuantity"=>5000,
         "priceInfo"=>
          {"bracketLimitPrice"=>0.0,
           "conditionFollowPrice"=>nil,
           "conditionPrice"=>0.0,
           "conditionSymbol"=>nil,
           "conditionType"=>nil,
           "initialStopPrice"=>0.0,
           "limitPrice"=>0.0,
           "stopPrice"=>0.0,
           "trailPrice"=>0.0,
           "triggerPrice"=>0.0,
           "type"=>"MARKET"},
         "symbol"=>"CMG"}],
      "orderNumber"=>"123",
      "orderStatus"=>"OPEN",
      "orderType"=>"EQ"},
     {"groupOrderId"=>nil,
      "groupOrderType"=>"null",
      "groupOrders"=>[],
      "orderExpiration"=>"GTC",
      "orderLegs"=>
       [{"action"=>"SELL_SHORT",
         "filledQuantity"=>6000,
         "fills"=>
          [{"price"=>123.45,
            "quantity"=>6000,
            "timestamp"=>"01/01/15 12:34 PM EST"}],
         "orderedQuantity"=>10000,
         "priceInfo"=>
          {"bracketLimitPrice"=>0.0,
           "conditionFollowPrice"=>nil,
           "conditionPrice"=>0.0,
           "conditionSymbol"=>nil,
           "conditionType"=>nil,
           "initialStopPrice"=>0.0,
           "limitPrice"=>67.89,
           "stopPrice"=>123.45,
           "trailPrice"=>0.0,
           "triggerPrice"=>0.0,
           "type"=>"STOP_LIMIT"},
         "symbol"=>"MCD"}],
      "orderNumber"=>"456",
      "orderStatus"=>"PART_FILLED",
      "orderType"=>"EQ"}],
   "shortMessage"=>"Order statuses successfully fetched",
   "status"=>"SUCCESS",
   "token"=>"bba1c52b409245afb86919b9c3d7b898"},
 :status=>200,
 :payload=>
 {"type"=>"success",
  "orders"=>
   [{"ticker"=>"cmg",
     "order_action"=>:buy,
     "filled_quantity"=>0,
     "filled_price"=>0.0,
     "order_number"=>"123",
     "quantity"=>5000,
     "expiration"=>:day,
     "status"=>:open},
    {"ticker"=>"mcd",
     "order_action"=>:sell_short,
     "filled_quantity"=>6000,
     "filled_price"=>123.45,
     "order_number"=>"456",
     "quantity"=>10000,
     "expiration"=>:gtc,
     "status"=>:part_filled}],
  "token"=>"3384aeb24c2143f5b78ee3e1311a40eb"}

DriveWealth::Order::Cancel

Cancel an unfulfilled order. The payload is identical to DriveWealth::Order::Status in that it return the order status of the cancelled order

Example Call

DriveWealth::Order::Cancel.new(
  token: preview_token,
  account_number,
  order_number
).call.response

Example response

{:raw=>
  {"accountNumber"=>"brkAcct1",
   "longMessages"=>nil,
   "orderStatusDetailsList"=>
    [{"groupOrderId"=>nil,
      "groupOrderType"=>"null",
      "groupOrders"=>[],
      "orderExpiration"=>"GTC",
      "orderLegs"=>
       [{"action"=>"BUY",
         "filledQuantity"=>0,
         "fills"=>[],
         "orderedQuantity"=>275000,
         "priceInfo"=>
          {"bracketLimitPrice"=>0.0,
           "conditionFollowPrice"=>nil,
           "conditionPrice"=>0.0,
           "conditionSymbol"=>nil,
           "conditionType"=>nil,
           "initialStopPrice"=>0.0,
           "limitPrice"=>0.0,
           "stopPrice"=>0.0,
           "trailPrice"=>0.0,
           "triggerPrice"=>0.0,
           "type"=>"MARKET"},
         "symbol"=>"FTFY"}],
      "orderNumber"=>"456",
      "orderStatus"=>"PENDING_CANCEL",
      "orderType"=>"EQ"}],
   "shortMessage"=>"Order statuses successfully fetched",
   "status"=>"SUCCESS",
   "token"=>"d9c45bb6223f425c865ed7c88042ad1f"},
 :status=>200,
 :payload=>
  {"type"=>"success",
   "orders"=>
    [{"ticker"=>"ftfy",
      "order_action"=>:buy,
      "filled_quantity"=>0,
      "filled_price"=>0.0,
      "order_number"=>"456",
      "quantity"=>275000,
      "expiration"=>:gtc,
      "status"=>:pending_cancel}],
   "token"=>"d9c45bb6223f425c865ed7c88042ad1f"},
 :messages=>["Order statuses successfully fetched"]}



DriveWealth::Instrument::Details

Example Call

DriveWealth::Order::Cancel.new(
  token: preview_token,
  ticker: "aapl"
).call.response

Example response

{:raw=>
  {{"instrumentID"=>"a67422af-8504-43df-9e63-7361eb0bd99e",
    "name"=>"Apple, Inc.",
    "category"=>"Stock",
    "currencyID"=>"USD",
    "description"=>"Apple Inc. designs, manufactures, and markets mobile communication and media devices, personal computers, and portable digital music players worldwide.",
    "exchangeID"=>"XNAS",
    "limitStatus"=>0,
    "instrumentTypeID"=>6,
    "isLongOnly"=>true,
    "marginCurrencyID"=>"USD",
    "orderSizeMax"=>10000,
    "orderSizeMin"=>0.0001,
    "orderSizeStep"=>0.0001,
    "rateAsk"=>97.45,
    "rateBid"=>97.44,
    "rateHigh"=>99.12,
    "rateLow"=>97.1,
    "rateOpen"=>98.69,
    "ratePrecision"=>2,
    "symbol"=>"AAPL",
    "tags"=>["aapl", "sp500", "usa"],
    "tradeStatus"=>1,
    "tradingHours"=>"Mon-Fri: 9:30am - 4:00pm ET",
    "uom"=>"shares",
    "urlImage"=>"http://syscdn.drivewealth.net/images/symbols/aapl.png",
    "urlInvestor"=>"http://investor.apple.com/",
    "chaikinPgr"=>
     "{  \"Corrected PGR Value\":\"2\",  \"Financial Metrics\":\"2\",  \"Earnings Performance\":\"4\",  \"Price/Volume Activity\":\"3\",  \"Expert Opinions\":\"1\",  \"pgrSummaryText\":\"The Chaikin Power Gauge Rating for AAPL is Bearish due to very negative expert activity and poor financial metrics. The stock also has strong earnings performance.\"}",
    "sector"=>"Technology",
    "priorClose"=>97.34,
    "close"=>0,
    "lastTrade"=>97.34,
    "nameLower"=>"apple, inc.",
    "underlyingID"=>"0",
    "marketState"=>2,
    "minTic"=>0,
    "pipMultiplier"=>1,
    "tickerSymbol"=>"AAPL",
    "rebateSpread"=>0,
    "longOnly"=>true}=>nil},
 :status=>200,
 :payload=>
  {"type"=>"success",
   "broker_id"=>"a67422af-8504-43df-9e63-7361eb0bd99e",
   "ticker"=>"aapl",
   "last_price"=>97.34,
   "bid_price"=>97.44,
   "ask_price"=>97.45,
   "order_size_max"=>10000.0,
   "order_size_min"=>0.0001,
   "order_size_step"=>0.0001,
   "allow_fractional_shares"=>true,
   "timestamp"=>1465915138,
   "warnings"=>[],
   "must_acknowledge"=>[],
   "token"=>"628f9e2b-6acb-4d6f-9fff-63c93d23d9d0.2016-06-14T14:38:53.603Z"},
 :messages=>["success"]}

drive-wealth's People

Contributors

stratmm avatar

Watchers

Paweł avatar James Cloos avatar Shane Leonard avatar  avatar David Kelley avatar Jonathan Kelley avatar

drive-wealth's Issues

Add a license.txt

Nice gem – I stumbled upon MIT license mention in the gem.spec. I'd like to use the gem in one of my projects.

Would it be possible? Would you mind adding the license.txt – to make it simple here is a MIT placeholder text.

Either way you decide – great work and Stockflare looks like a really cool project!

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.