questrade_api 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
 - data/.gitignore +4 -0
 - data/.rspec +2 -0
 - data/.travis.yml +3 -0
 - data/.yardopts +9 -0
 - data/Gemfile +15 -0
 - data/Guardfile +6 -0
 - data/{LICENSE.txt → LICENSE} +0 -0
 - data/README.md +31 -45
 - data/Rakefile +4 -0
 - data/lib/questrade_api/authorization.rb +94 -0
 - data/lib/questrade_api/client.rb +87 -0
 - data/lib/questrade_api/modules/util.rb +22 -0
 - data/lib/questrade_api/rest/account.rb +101 -0
 - data/lib/questrade_api/rest/activity.rb +58 -0
 - data/lib/questrade_api/rest/balance.rb +81 -0
 - data/lib/questrade_api/rest/base.rb +88 -0
 - data/lib/questrade_api/rest/execution.rb +59 -0
 - data/lib/questrade_api/rest/market.rb +42 -0
 - data/lib/questrade_api/rest/order.rb +58 -0
 - data/lib/questrade_api/rest/position.rb +48 -0
 - data/lib/questrade_api/rest/time.rb +26 -0
 - data/lib/questrade_api/version.rb +1 -1
 - data/questrade_api.gemspec +2 -3
 - data/spec/fixtures/json/accounts.json +21 -0
 - data/spec/fixtures/json/activities.json +36 -0
 - data/spec/fixtures/json/balances.json +55 -0
 - data/spec/fixtures/json/executions.json +46 -0
 - data/spec/fixtures/json/markets.json +34 -0
 - data/spec/fixtures/json/orders.json +49 -0
 - data/spec/fixtures/json/positions.json +17 -0
 - data/spec/fixtures/json/time.json +3 -0
 - data/spec/questrade_api/authorization_spec.rb +74 -0
 - data/spec/questrade_api/client_spec.rb +38 -0
 - data/spec/questrade_api/rest/account_spec.rb +88 -0
 - data/spec/questrade_api/rest/activity_spec.rb +70 -0
 - data/spec/questrade_api/rest/balance_spec.rb +34 -0
 - data/spec/questrade_api/rest/execution_spec.rb +80 -0
 - data/spec/questrade_api/rest/market_spec.rb +63 -0
 - data/spec/questrade_api/rest/order_spec.rb +95 -0
 - data/spec/questrade_api/rest/position_spec.rb +47 -0
 - data/spec/questrade_api/rest/time_spec.rb +34 -0
 - data/spec/spec_helper.rb +107 -0
 - data/spec/support/json_fixtures.rb +21 -0
 - metadata +61 -47
 
    
        checksums.yaml
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ---
         
     | 
| 
       2 
2 
     | 
    
         
             
            SHA1:
         
     | 
| 
       3 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       4 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: 49d2e66e9476e189911591ed7fac0b63134b2fce
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: c941e8f74073691030eaed6bd8066c1af859b88b
         
     | 
| 
       5 
5 
     | 
    
         
             
            SHA512:
         
     | 
| 
       6 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       7 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: 7895d0c76f3515bad23d095557f010f0d1d8528a660557335a7b05e2c3aeec99baa586f4f6685ee59f93c8dc2987fa56248ab29bc2c9246fc8066ae29302dd61
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: edf1116607c99e92f40e7618809eb5ee7d4995e2d5c651001ce3649f017892bcf04de3baf59ad467d358befcb27cdd1fd338e62d008dd8723557dd86123bc922
         
     | 
    
        data/.gitignore
    CHANGED
    
    
    
        data/.rspec
    ADDED
    
    
    
        data/.travis.yml
    ADDED
    
    
    
        data/.yardopts
    ADDED
    
    
    
        data/Gemfile
    CHANGED
    
    | 
         @@ -1,4 +1,19 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            source 'http://rubygems.org'
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
      
 3 
     | 
    
         
            +
            group :docs do
         
     | 
| 
      
 4 
     | 
    
         
            +
              gem 'yard'
         
     | 
| 
      
 5 
     | 
    
         
            +
              gem "redcarpet"
         
     | 
| 
      
 6 
     | 
    
         
            +
              gem 'github-markup'
         
     | 
| 
      
 7 
     | 
    
         
            +
            end
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
            group :test do
         
     | 
| 
      
 10 
     | 
    
         
            +
              gem 'guard'
         
     | 
| 
      
 11 
     | 
    
         
            +
              gem 'guard-rspec'
         
     | 
| 
      
 12 
     | 
    
         
            +
              gem 'bundler', '~> 1.14'
         
     | 
| 
      
 13 
     | 
    
         
            +
            end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
            gem 'rake'
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
       3 
17 
     | 
    
         
             
            # Specify your gem's dependencies in questrade_api.gemspec
         
     | 
| 
       4 
18 
     | 
    
         
             
            gemspec
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
    
        data/Guardfile
    ADDED
    
    | 
         @@ -0,0 +1,6 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            guard :rspec, cmd: 'bundle exec rspec' do
         
     | 
| 
      
 2 
     | 
    
         
            +
              watch(%r{^spec/.+_spec\.rb$})
         
     | 
| 
      
 3 
     | 
    
         
            +
              watch(%r{^lib/(.+)\.rb$})     { |m| "spec/lib/#{m[1]}_spec.rb" }
         
     | 
| 
      
 4 
     | 
    
         
            +
              watch(%r{^lib/questrade_api/rest/(.+)\.rb$})     { |m| "spec/questrade_api/rest/#{m[1]}_spec.rb" }
         
     | 
| 
      
 5 
     | 
    
         
            +
              watch('spec/spec_helper.rb')  { "spec" }
         
     | 
| 
      
 6 
     | 
    
         
            +
            end
         
     | 
    
        data/{LICENSE.txt → LICENSE}
    RENAMED
    
    | 
         
            File without changes
         
     | 
    
        data/README.md
    CHANGED
    
    | 
         @@ -1,37 +1,32 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            [](https://travis-ci.org/brunomeira/questrade_api) 
         
     | 
| 
      
 2 
     | 
    
         
            +
            [](https://codeclimate.com/github/brunomeira/questrade_api)
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
       1 
4 
     | 
    
         
             
            # QuestradeApi
         
     | 
| 
       2 
5 
     | 
    
         | 
| 
       3 
6 
     | 
    
         
             
            A Ruby interface to use the [Questrade API](http://www.questrade.com/api).
         
     | 
| 
       4 
7 
     | 
    
         | 
| 
       5 
8 
     | 
    
         
             
            ## Quick Start
         
     | 
| 
       6 
9 
     | 
    
         | 
| 
       7 
     | 
    
         
            -
             
     | 
| 
       8 
     | 
    
         
            -
             
     | 
| 
       9 
     | 
    
         
            -
            2. Add the following line to your Gemfile
         
     | 
| 
      
 10 
     | 
    
         
            +
            - Create a Questrade Demo Account on: <http://www.questrade.com/api/free-practice-account>
         
     | 
| 
      
 11 
     | 
    
         
            +
            - Add the following line to your Gemfile
         
     | 
| 
       10 
12 
     | 
    
         | 
| 
       11 
13 
     | 
    
         
             
            ```
         
     | 
| 
       12 
14 
     | 
    
         
             
            gem 'questrade_api'
         
     | 
| 
       13 
     | 
    
         
            -
             
     | 
| 
       14 
15 
     | 
    
         
             
            ```
         
     | 
| 
       15 
     | 
    
         
            -
             
     | 
| 
       16 
     | 
    
         
            -
            3. Run Bundle to install gem
         
     | 
| 
      
 16 
     | 
    
         
            +
            - Run Bundle to install gem
         
     | 
| 
       17 
17 
     | 
    
         | 
| 
       18 
18 
     | 
    
         
             
            ```
         
     | 
| 
       19 
19 
     | 
    
         
             
            $ bundle
         
     | 
| 
       20 
     | 
    
         
            -
             
     | 
| 
       21 
20 
     | 
    
         
             
            ```
         
     | 
| 
       22 
     | 
    
         
            -
             
     | 
| 
       23 
     | 
    
         
            -
             
     | 
| 
       24 
     | 
    
         
            -
             
     | 
| 
       25 
     | 
    
         
            -
            5. Copy the snippet of code below to your application, and replace the 'XXXX' token with the token generated on step 4.
         
     | 
| 
      
 21 
     | 
    
         
            +
            - Follow the tutorial on <http://www.questrade.com/api/documentation/getting-started> to generate a refresh token
         
     | 
| 
      
 22 
     | 
    
         
            +
            - Copy the snippet of code below to your application, and replace the 'XXXX' token with the token generated in the previous step.
         
     | 
| 
       26 
23 
     | 
    
         | 
| 
       27 
24 
     | 
    
         
             
            ```ruby
         
     | 
| 
       28 
25 
     | 
    
         
             
            # By default this API calls the practice(demo) endpoint.
         
     | 
| 
       29 
26 
     | 
    
         
             
            # Check our documentation to learn how to call the live endpoint.
         
     | 
| 
       30 
27 
     | 
    
         
             
            client = QuestradeApi::Client.new(refresh_token: 'XXXX')
         
     | 
| 
       31 
     | 
    
         
            -
             
     | 
| 
       32 
28 
     | 
    
         
             
            ```
         
     | 
| 
       33 
     | 
    
         
            -
             
     | 
| 
       34 
     | 
    
         
            -
            6. That's all you need to access the API. A few examples of what you can do with it:
         
     | 
| 
      
 29 
     | 
    
         
            +
            - That's all you need to access the API. A few examples of what you can do with it:
         
     | 
| 
       35 
30 
     | 
    
         | 
| 
       36 
31 
     | 
    
         
             
            ```ruby
         
     | 
| 
       37 
32 
     | 
    
         
             
            # Get Questrade's current server time
         
     | 
| 
         @@ -53,57 +48,48 @@ client.activities('account_id', startTime: DateTime.yesterday.to_s, endTime: Dat 
     | 
|
| 
       53 
48 
     | 
    
         
             
            # authorization can be any object that responds to url and access_token
         
     | 
| 
       54 
49 
     | 
    
         
             
            authorization = QuestradeApi::Authorization.new(access_token: 'access_token', api_server: 'url')
         
     | 
| 
       55 
50 
     | 
    
         
             
            accounts = QuestradeApi::REST::Account.all(accounts)
         
     | 
| 
       56 
     | 
    
         
            -
             
     | 
| 
       57 
51 
     | 
    
         
             
            ```
         
     | 
| 
       58 
     | 
    
         
            -
             
     | 
| 
       59 
     | 
    
         
            -
            For more advanced options, check out our [documentation](http://www.google.com).
         
     | 
| 
      
 52 
     | 
    
         
            +
            For more advanced options, check out our [documentation](http://www.rubydoc.info/gems/questrade_api).
         
     | 
| 
       60 
53 
     | 
    
         | 
| 
       61 
54 
     | 
    
         
             
            ## Current Status
         
     | 
| 
       62 
55 
     | 
    
         | 
| 
       63 
56 
     | 
    
         
             
            This Project is under development and some endpoints are still not accessible through the gem.
         
     | 
| 
       64 
57 
     | 
    
         
             
            Check the tables below for more details.
         
     | 
| 
       65 
58 
     | 
    
         | 
| 
       66 
     | 
    
         
            -
            <dl>
         
     | 
| 
       67 
     | 
    
         
            -
              <dt>LEGEND</dt>
         
     | 
| 
       68 
     | 
    
         
            -
             
     | 
| 
       69 
     | 
    
         
            -
              <dd>:green_heart: = Available</dd>
         
     | 
| 
       70 
     | 
    
         
            -
              <dd>:heart: = Not Available</dd>
         
     | 
| 
       71 
     | 
    
         
            -
            </dl>
         
     | 
| 
       72 
     | 
    
         
            -
             
     | 
| 
       73 
59 
     | 
    
         
             
            ### Account Calls
         
     | 
| 
       74 
60 
     | 
    
         | 
| 
       75 
61 
     | 
    
         
             
            | Endpoint                 | Development   | Documentation |
         
     | 
| 
       76 
62 
     | 
    
         
             
            | ---                      | ---           | ---           |
         
     | 
| 
       77 
     | 
    
         
            -
            | /time                    | 
     | 
| 
       78 
     | 
    
         
            -
            | /accounts                | 
     | 
| 
       79 
     | 
    
         
            -
            | /accounts/:id/positions  | 
     | 
| 
       80 
     | 
    
         
            -
            | /accounts/:id/balances   | 
     | 
| 
       81 
     | 
    
         
            -
            | /accounts/:id/executions | 
     | 
| 
       82 
     | 
    
         
            -
            | /accounts/:id/orders     | 
     | 
| 
       83 
     | 
    
         
            -
            | /accounts/:id/activities | 
     | 
| 
      
 63 
     | 
    
         
            +
            | /time                    |DONE           | DONE          |
         
     | 
| 
      
 64 
     | 
    
         
            +
            | /accounts                |DONE           | DONE          |
         
     | 
| 
      
 65 
     | 
    
         
            +
            | /accounts/:id/positions  |DONE           | DONE          |
         
     | 
| 
      
 66 
     | 
    
         
            +
            | /accounts/:id/balances   |DONE           | DONE          |
         
     | 
| 
      
 67 
     | 
    
         
            +
            | /accounts/:id/executions |DONE           | DONE          |
         
     | 
| 
      
 68 
     | 
    
         
            +
            | /accounts/:id/orders     |DONE           | DONE          |
         
     | 
| 
      
 69 
     | 
    
         
            +
            | /accounts/:id/activities |DONE           | DONE          |
         
     | 
| 
       84 
70 
     | 
    
         | 
| 
       85 
71 
     | 
    
         
             
            ### Market Calls
         
     | 
| 
       86 
72 
     | 
    
         | 
| 
       87 
73 
     | 
    
         
             
            | Endpoint                   | Development   | Documentation |
         
     | 
| 
       88 
74 
     | 
    
         
             
            | ---                        | ---           | ---           |
         
     | 
| 
       89 
     | 
    
         
            -
            | /symbols/:id               | 
     | 
| 
       90 
     | 
    
         
            -
            | /symbols/:search           | 
     | 
| 
       91 
     | 
    
         
            -
            | /symbols/:id/options       | 
     | 
| 
       92 
     | 
    
         
            -
            | /markets                   | 
     | 
| 
       93 
     | 
    
         
            -
            | /markets/quotes/:id        | 
     | 
| 
       94 
     | 
    
         
            -
            | /markets/quotes/options    | 
     | 
| 
       95 
     | 
    
         
            -
            | /markets/quotes/strategies | 
     | 
| 
       96 
     | 
    
         
            -
            | /markets/candles/:id       | 
     | 
| 
      
 75 
     | 
    
         
            +
            | /symbols/:id               |      |      |
         
     | 
| 
      
 76 
     | 
    
         
            +
            | /symbols/:search           |      |      |
         
     | 
| 
      
 77 
     | 
    
         
            +
            | /symbols/:id/options       |      |      |
         
     | 
| 
      
 78 
     | 
    
         
            +
            | /markets                   |DONE|      |
         
     | 
| 
      
 79 
     | 
    
         
            +
            | /markets/quotes/:id        |      |      |
         
     | 
| 
      
 80 
     | 
    
         
            +
            | /markets/quotes/options    |      |      |
         
     | 
| 
      
 81 
     | 
    
         
            +
            | /markets/quotes/strategies |      |      |
         
     | 
| 
      
 82 
     | 
    
         
            +
            | /markets/candles/:id       |      |      |
         
     | 
| 
       97 
83 
     | 
    
         | 
| 
       98 
84 
     | 
    
         
             
            ### Order Calls
         
     | 
| 
       99 
85 
     | 
    
         | 
| 
       100 
86 
     | 
    
         
             
            | Endpoint                          | Development   | Documentation |
         
     | 
| 
       101 
87 
     | 
    
         
             
            | ---                               | ---           | ---           |
         
     | 
| 
       102 
     | 
    
         
            -
            | POST accounts/:id/orders          | 
     | 
| 
       103 
     | 
    
         
            -
            | POST accounts/:id/orders/impact   | 
     | 
| 
       104 
     | 
    
         
            -
            | DELETE accounts/:id/orders        | 
     | 
| 
       105 
     | 
    
         
            -
            | POST accounts/:id/orders/brackets | 
     | 
| 
       106 
     | 
    
         
            -
            | POST accounts/:id/orders/strategy | 
     | 
| 
      
 88 
     | 
    
         
            +
            | POST accounts/:id/orders          |      |      |
         
     | 
| 
      
 89 
     | 
    
         
            +
            | POST accounts/:id/orders/impact   |      |      |
         
     | 
| 
      
 90 
     | 
    
         
            +
            | DELETE accounts/:id/orders        |      |      |
         
     | 
| 
      
 91 
     | 
    
         
            +
            | POST accounts/:id/orders/brackets |      |      |
         
     | 
| 
      
 92 
     | 
    
         
            +
            | POST accounts/:id/orders/strategy |      |      |
         
     | 
| 
       107 
93 
     | 
    
         | 
| 
       108 
94 
     | 
    
         
             
            ## Contributing
         
     | 
| 
       109 
95 
     | 
    
         | 
| 
         @@ -123,4 +109,4 @@ We are not responsible for any damages, capital losses, or any claim caused by t 
     | 
|
| 
       123 
109 
     | 
    
         | 
| 
       124 
110 
     | 
    
         
             
            USE IT AT YOUR OWN RISK.
         
     | 
| 
       125 
111 
     | 
    
         | 
| 
       126 
     | 
    
         
            -
            [LICENSE]: LICENSE 
     | 
| 
      
 112 
     | 
    
         
            +
            [LICENSE]: https://github.com/brunomeira/questrade_api/blob/master/LICENSE
         
     | 
    
        data/Rakefile
    CHANGED
    
    
| 
         @@ -0,0 +1,94 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'faraday'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'json'
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            require 'questrade_api/modules/util'
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            module QuestradeApi
         
     | 
| 
      
 7 
     | 
    
         
            +
              # @author Bruno Meira <goesmeira@gmail.com>
         
     | 
| 
      
 8 
     | 
    
         
            +
              class Authorization
         
     | 
| 
      
 9 
     | 
    
         
            +
                include QuestradeApi::Util
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                MODE = %i(live practice).freeze
         
     | 
| 
      
 12 
     | 
    
         
            +
                attr_reader :mode, :data, :connection
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                # Initialize an instance of QuestradeApi::Client.
         
     | 
| 
      
 15 
     | 
    
         
            +
                #
         
     | 
| 
      
 16 
     | 
    
         
            +
                # @note Only access_token, api_server, and refresh_token are needed for this gem.
         
     | 
| 
      
 17 
     | 
    
         
            +
                #
         
     | 
| 
      
 18 
     | 
    
         
            +
                # @param params [Hash] for Questrade authorization.
         
     | 
| 
      
 19 
     | 
    
         
            +
                # @option params [String] :access_token Access token used to access API.
         
     | 
| 
      
 20 
     | 
    
         
            +
                # @option params [String] :api_server Endpoint used to access API. Example: 'https://apiXX.iq.questrade.com/', where X is a number.
         
     | 
| 
      
 21 
     | 
    
         
            +
                # @option params [Integer] :expires_in How much time the access token is valid.
         
     | 
| 
      
 22 
     | 
    
         
            +
                # @option params [String] :refresh_token Token used to get a new access token.
         
     | 
| 
      
 23 
     | 
    
         
            +
                # @option params [String] :token_type Token type.
         
     | 
| 
      
 24 
     | 
    
         
            +
                #
         
     | 
| 
      
 25 
     | 
    
         
            +
                # @param mode [Symbol] accessed on Questrade, `:live` or `:practice`
         
     | 
| 
      
 26 
     | 
    
         
            +
                def initialize(params, mode = :practice)
         
     | 
| 
      
 27 
     | 
    
         
            +
                  raise 'Mode must be :live or :practice' unless MODE.include?(mode)
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                  @mode = mode
         
     | 
| 
      
 30 
     | 
    
         
            +
                  @connection = build_connection
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
                  build_data(params)
         
     | 
| 
      
 33 
     | 
    
         
            +
                end
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
                # Uses refresh_token to fetch a new valid access token.
         
     | 
| 
      
 36 
     | 
    
         
            +
                #
         
     | 
| 
      
 37 
     | 
    
         
            +
                # @note #data will be populated accordingly, if call is successful.
         
     | 
| 
      
 38 
     | 
    
         
            +
                #
         
     | 
| 
      
 39 
     | 
    
         
            +
                # @return The result of the call.
         
     | 
| 
      
 40 
     | 
    
         
            +
                def refresh_token
         
     | 
| 
      
 41 
     | 
    
         
            +
                  response = connection.get do |req|
         
     | 
| 
      
 42 
     | 
    
         
            +
                    req.params[:grant_type] = 'refresh_token'
         
     | 
| 
      
 43 
     | 
    
         
            +
                    req.params[:refresh_token] = data.refresh_token
         
     | 
| 
      
 44 
     | 
    
         
            +
                  end
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
                  if response.status == 200
         
     | 
| 
      
 47 
     | 
    
         
            +
                    raw_body = JSON.parse(response.body)
         
     | 
| 
      
 48 
     | 
    
         
            +
                    build_data(raw_body)
         
     | 
| 
      
 49 
     | 
    
         
            +
                  end
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
                  response
         
     | 
| 
      
 52 
     | 
    
         
            +
                end
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
                # Returns the authorized access token.
         
     | 
| 
      
 55 
     | 
    
         
            +
                def access_token
         
     | 
| 
      
 56 
     | 
    
         
            +
                  data.access_token
         
     | 
| 
      
 57 
     | 
    
         
            +
                end
         
     | 
| 
      
 58 
     | 
    
         
            +
             
     | 
| 
      
 59 
     | 
    
         
            +
                # Returns the server associated with the authorized access token.
         
     | 
| 
      
 60 
     | 
    
         
            +
                def url
         
     | 
| 
      
 61 
     | 
    
         
            +
                  data.api_server
         
     | 
| 
      
 62 
     | 
    
         
            +
                end
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
                # Checks if selected mode is live.
         
     | 
| 
      
 65 
     | 
    
         
            +
                #
         
     | 
| 
      
 66 
     | 
    
         
            +
                # @return [Boolean]
         
     | 
| 
      
 67 
     | 
    
         
            +
                def live?
         
     | 
| 
      
 68 
     | 
    
         
            +
                  mode == :live
         
     | 
| 
      
 69 
     | 
    
         
            +
                end
         
     | 
| 
      
 70 
     | 
    
         
            +
             
     | 
| 
      
 71 
     | 
    
         
            +
                private
         
     | 
| 
      
 72 
     | 
    
         
            +
             
     | 
| 
      
 73 
     | 
    
         
            +
                def login_url
         
     | 
| 
      
 74 
     | 
    
         
            +
                  if live?
         
     | 
| 
      
 75 
     | 
    
         
            +
                    'https://login.questrade.com/oauth2/token'
         
     | 
| 
      
 76 
     | 
    
         
            +
                  else
         
     | 
| 
      
 77 
     | 
    
         
            +
                    'https://practicelogin.questrade.com/oauth2/token'
         
     | 
| 
      
 78 
     | 
    
         
            +
                  end
         
     | 
| 
      
 79 
     | 
    
         
            +
                end
         
     | 
| 
      
 80 
     | 
    
         
            +
             
     | 
| 
      
 81 
     | 
    
         
            +
                def build_data(data)
         
     | 
| 
      
 82 
     | 
    
         
            +
                  hash = hash_to_snakecase(data)
         
     | 
| 
      
 83 
     | 
    
         
            +
                  @data = OpenStruct.new(hash)
         
     | 
| 
      
 84 
     | 
    
         
            +
                end
         
     | 
| 
      
 85 
     | 
    
         
            +
             
     | 
| 
      
 86 
     | 
    
         
            +
                def build_connection
         
     | 
| 
      
 87 
     | 
    
         
            +
                  Faraday.new(login_url) do |faraday|
         
     | 
| 
      
 88 
     | 
    
         
            +
                    faraday.response :logger
         
     | 
| 
      
 89 
     | 
    
         
            +
                    faraday.adapter Faraday.default_adapter
         
     | 
| 
      
 90 
     | 
    
         
            +
                    faraday.headers['Content-Type'] = 'application/json'
         
     | 
| 
      
 91 
     | 
    
         
            +
                  end
         
     | 
| 
      
 92 
     | 
    
         
            +
                end
         
     | 
| 
      
 93 
     | 
    
         
            +
              end
         
     | 
| 
      
 94 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,87 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'questrade_api/authorization'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'questrade_api/rest/time'
         
     | 
| 
      
 3 
     | 
    
         
            +
            require 'questrade_api/rest/account'
         
     | 
| 
      
 4 
     | 
    
         
            +
            require 'questrade_api/rest/balance'
         
     | 
| 
      
 5 
     | 
    
         
            +
            require 'questrade_api/rest/position'
         
     | 
| 
      
 6 
     | 
    
         
            +
            require 'questrade_api/rest/execution'
         
     | 
| 
      
 7 
     | 
    
         
            +
            require 'questrade_api/rest/activity'
         
     | 
| 
      
 8 
     | 
    
         
            +
            require 'questrade_api/rest/order'
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
            require 'questrade_api/rest/market'
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
            module QuestradeApi
         
     | 
| 
      
 13 
     | 
    
         
            +
              # @author Bruno Meira <goesmeira@gmail.com>
         
     | 
| 
      
 14 
     | 
    
         
            +
              class Client
         
     | 
| 
      
 15 
     | 
    
         
            +
                attr_reader :authorization
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                # @see QuestradeApi::Client#initialize for more details
         
     | 
| 
      
 18 
     | 
    
         
            +
                def initialize(params = {}, mode = :practice)
         
     | 
| 
      
 19 
     | 
    
         
            +
                  @authorization = QuestradeApi::Authorization.new(params, mode)
         
     | 
| 
      
 20 
     | 
    
         
            +
                  refresh_token if refresh_token?
         
     | 
| 
      
 21 
     | 
    
         
            +
                end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                # Fetches a new access_token. (see QuestradeApi::Authorization#refresh_token)
         
     | 
| 
      
 24 
     | 
    
         
            +
                def refresh_token
         
     | 
| 
      
 25 
     | 
    
         
            +
                  @authorization.refresh_token
         
     | 
| 
      
 26 
     | 
    
         
            +
                end
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
                # Fetch current server time.
         
     | 
| 
      
 29 
     | 
    
         
            +
                #
         
     | 
| 
      
 30 
     | 
    
         
            +
                # @return [DateTime] if no issues to call /time endpoint occurs.
         
     | 
| 
      
 31 
     | 
    
         
            +
                # @return [nil] if current server time cannot be fetched.
         
     | 
| 
      
 32 
     | 
    
         
            +
                def time
         
     | 
| 
      
 33 
     | 
    
         
            +
                  time = QuestradeApi::REST::Time.new(@authorization)
         
     | 
| 
      
 34 
     | 
    
         
            +
                  time.get
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
                  time.data && time.data.time
         
     | 
| 
      
 37 
     | 
    
         
            +
                end
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
                # Fetch all accounts associated with user.
         
     | 
| 
      
 40 
     | 
    
         
            +
                #
         
     | 
| 
      
 41 
     | 
    
         
            +
                # @return [Array<QuestradeApi::REST::Account>]
         
     | 
| 
      
 42 
     | 
    
         
            +
                def accounts
         
     | 
| 
      
 43 
     | 
    
         
            +
                  QuestradeApi::REST::Account.all(@authorization).accounts
         
     | 
| 
      
 44 
     | 
    
         
            +
                end
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
                # Fetch all positions associated with account.
         
     | 
| 
      
 47 
     | 
    
         
            +
                #
         
     | 
| 
      
 48 
     | 
    
         
            +
                # @param account_id [String] to which positions will be fetched.
         
     | 
| 
      
 49 
     | 
    
         
            +
                #
         
     | 
| 
      
 50 
     | 
    
         
            +
                # @return [Array<QuestradeApi::REST::Position>]
         
     | 
| 
      
 51 
     | 
    
         
            +
                def positions(account_id)
         
     | 
| 
      
 52 
     | 
    
         
            +
                  QuestradeApi::REST::Position.all(@authorization, account_id).positions
         
     | 
| 
      
 53 
     | 
    
         
            +
                end
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
                # Fetch all balances associated with account.
         
     | 
| 
      
 56 
     | 
    
         
            +
                #
         
     | 
| 
      
 57 
     | 
    
         
            +
                # @param account_id [String] to which balances will be fetched.
         
     | 
| 
      
 58 
     | 
    
         
            +
                #
         
     | 
| 
      
 59 
     | 
    
         
            +
                # @return [OpenStruct(per_currency_balances)]
         
     | 
| 
      
 60 
     | 
    
         
            +
                def balances(account_id)
         
     | 
| 
      
 61 
     | 
    
         
            +
                  QuestradeApi::REST::Balance.all(@authorization, account_id)
         
     | 
| 
      
 62 
     | 
    
         
            +
                end
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
                def executions(account_id, params = {})
         
     | 
| 
      
 65 
     | 
    
         
            +
                  QuestradeApi::REST::Execution.all(@authorization, account_id, params)
         
     | 
| 
      
 66 
     | 
    
         
            +
                end
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
                def activities(account_id, params = {})
         
     | 
| 
      
 69 
     | 
    
         
            +
                  QuestradeApi::REST::Activity.all(@authorization, account_id, params)
         
     | 
| 
      
 70 
     | 
    
         
            +
                end
         
     | 
| 
      
 71 
     | 
    
         
            +
             
     | 
| 
      
 72 
     | 
    
         
            +
                def orders(account_id, params = {})
         
     | 
| 
      
 73 
     | 
    
         
            +
                  QuestradeApi::REST::Activity.all(@authorization, account_id, params)
         
     | 
| 
      
 74 
     | 
    
         
            +
                end
         
     | 
| 
      
 75 
     | 
    
         
            +
             
     | 
| 
      
 76 
     | 
    
         
            +
                def markets
         
     | 
| 
      
 77 
     | 
    
         
            +
                  QuestradeApi::REST::Market.all(@authorization)
         
     | 
| 
      
 78 
     | 
    
         
            +
                end
         
     | 
| 
      
 79 
     | 
    
         
            +
             
     | 
| 
      
 80 
     | 
    
         
            +
                private
         
     | 
| 
      
 81 
     | 
    
         
            +
             
     | 
| 
      
 82 
     | 
    
         
            +
                def refresh_token?
         
     | 
| 
      
 83 
     | 
    
         
            +
                  data = @authorization.data
         
     | 
| 
      
 84 
     | 
    
         
            +
                  data.refresh_token && !data.api_server && !data.access_token
         
     | 
| 
      
 85 
     | 
    
         
            +
                end
         
     | 
| 
      
 86 
     | 
    
         
            +
              end
         
     | 
| 
      
 87 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,22 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module QuestradeApi
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Util
         
     | 
| 
      
 3 
     | 
    
         
            +
                private
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
                def hash_to_snakecase(hash)
         
     | 
| 
      
 6 
     | 
    
         
            +
                  values = hash.map do |k, v|
         
     | 
| 
      
 7 
     | 
    
         
            +
                    [underscore(k.to_s).to_sym, v]
         
     | 
| 
      
 8 
     | 
    
         
            +
                  end
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                  Hash[values]
         
     | 
| 
      
 11 
     | 
    
         
            +
                end
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                def underscore(camel_cased_word)
         
     | 
| 
      
 14 
     | 
    
         
            +
                  camel_cased_word
         
     | 
| 
      
 15 
     | 
    
         
            +
                    .gsub(/::/, '/')
         
     | 
| 
      
 16 
     | 
    
         
            +
                    .gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
         
     | 
| 
      
 17 
     | 
    
         
            +
                    .gsub(/([a-z\d])([A-Z])/, '\1_\2')
         
     | 
| 
      
 18 
     | 
    
         
            +
                    .tr('-', '_')
         
     | 
| 
      
 19 
     | 
    
         
            +
                    .downcase
         
     | 
| 
      
 20 
     | 
    
         
            +
                end
         
     | 
| 
      
 21 
     | 
    
         
            +
              end
         
     | 
| 
      
 22 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,101 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'questrade_api/modules/util'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            require 'questrade_api/rest/base'
         
     | 
| 
      
 4 
     | 
    
         
            +
            require 'questrade_api/rest/activity'
         
     | 
| 
      
 5 
     | 
    
         
            +
            require 'questrade_api/rest/position'
         
     | 
| 
      
 6 
     | 
    
         
            +
            require 'questrade_api/rest/balance'
         
     | 
| 
      
 7 
     | 
    
         
            +
            require 'questrade_api/rest/execution'
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
            module QuestradeApi
         
     | 
| 
      
 10 
     | 
    
         
            +
              module REST
         
     | 
| 
      
 11 
     | 
    
         
            +
                # @author Bruno Meira <goesmeira@gmail.com>
         
     | 
| 
      
 12 
     | 
    
         
            +
                class Account < QuestradeApi::REST::Base
         
     | 
| 
      
 13 
     | 
    
         
            +
                  attr_accessor :id, :user_id
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                  def initialize(authorization, params)
         
     | 
| 
      
 16 
     | 
    
         
            +
                    super(authorization)
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                    @id = params[:id]
         
     | 
| 
      
 19 
     | 
    
         
            +
                    @user_id = params[:user_id]
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                    @raw_body = params[:data]
         
     | 
| 
      
 22 
     | 
    
         
            +
                    build_data(params[:data]) if @raw_body
         
     | 
| 
      
 23 
     | 
    
         
            +
                  end
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                  #
         
     | 
| 
      
 26 
     | 
    
         
            +
                  # Fetch activities associated with account.
         
     | 
| 
      
 27 
     | 
    
         
            +
                  #
         
     | 
| 
      
 28 
     | 
    
         
            +
                  # @param see QuestradeApi::REST::Activity.all
         
     | 
| 
      
 29 
     | 
    
         
            +
                  #
         
     | 
| 
      
 30 
     | 
    
         
            +
                  # @return [OpenStruct(executions: [QuestradeApi::REST::Activity)]
         
     | 
| 
      
 31 
     | 
    
         
            +
                  def activities(params)
         
     | 
| 
      
 32 
     | 
    
         
            +
                    QuestradeApi::REST::Activity.all(authorization, id, params)
         
     | 
| 
      
 33 
     | 
    
         
            +
                  end
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
                  # Fetch executions associated with account.
         
     | 
| 
      
 36 
     | 
    
         
            +
                  #
         
     | 
| 
      
 37 
     | 
    
         
            +
                  # @param see QuestradeApi::REST::Execution.all
         
     | 
| 
      
 38 
     | 
    
         
            +
                  #
         
     | 
| 
      
 39 
     | 
    
         
            +
                  # @return [OpenStruct(executions: [QuestradeApi::REST::Execution)]
         
     | 
| 
      
 40 
     | 
    
         
            +
                  def executions(params)
         
     | 
| 
      
 41 
     | 
    
         
            +
                    QuestradeApi::REST::Execution.all(authorization, id, params)
         
     | 
| 
      
 42 
     | 
    
         
            +
                  end
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
                  # Fetch balances associated with account.
         
     | 
| 
      
 45 
     | 
    
         
            +
                  #
         
     | 
| 
      
 46 
     | 
    
         
            +
                  # @return [OpenStruct(per_currency_balances)]
         
     | 
| 
      
 47 
     | 
    
         
            +
                  def balances
         
     | 
| 
      
 48 
     | 
    
         
            +
                    QuestradeApi::REST::Balance.all(authorization, id)
         
     | 
| 
      
 49 
     | 
    
         
            +
                  end
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
                  # Fetch positions associated with account.
         
     | 
| 
      
 52 
     | 
    
         
            +
                  #
         
     | 
| 
      
 53 
     | 
    
         
            +
                  # @return [OpenStruct(positions: [QuestradeApi::REST::Position])]
         
     | 
| 
      
 54 
     | 
    
         
            +
                  def positions
         
     | 
| 
      
 55 
     | 
    
         
            +
                    QuestradeApi::REST::Position.all(authorization, id)
         
     | 
| 
      
 56 
     | 
    
         
            +
                  end
         
     | 
| 
      
 57 
     | 
    
         
            +
             
     | 
| 
      
 58 
     | 
    
         
            +
                  # Fetch accounts for specific authorized user.
         
     | 
| 
      
 59 
     | 
    
         
            +
                  #
         
     | 
| 
      
 60 
     | 
    
         
            +
                  # @param authorization is any object that
         
     | 
| 
      
 61 
     | 
    
         
            +
                  #   responds to #access_token and #url
         
     | 
| 
      
 62 
     | 
    
         
            +
                  #
         
     | 
| 
      
 63 
     | 
    
         
            +
                  # @return [OpenStruct(accounts: [QuestradeApi::REST::Account])] if call to server is successful
         
     | 
| 
      
 64 
     | 
    
         
            +
                  # @return [Faraday::Response] if call to server is not successful
         
     | 
| 
      
 65 
     | 
    
         
            +
                  def self.all(authorization)
         
     | 
| 
      
 66 
     | 
    
         
            +
                    response = super(access_token: authorization.access_token,
         
     | 
| 
      
 67 
     | 
    
         
            +
                                     endpoint: endpoint,
         
     | 
| 
      
 68 
     | 
    
         
            +
                                     url: authorization.url)
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
                    result = OpenStruct.new(accounts: [])
         
     | 
| 
      
 71 
     | 
    
         
            +
             
     | 
| 
      
 72 
     | 
    
         
            +
                    if response.status == 200
         
     | 
| 
      
 73 
     | 
    
         
            +
                      result.accounts = parse_accounts(authorization, response.body)
         
     | 
| 
      
 74 
     | 
    
         
            +
                      response = result
         
     | 
| 
      
 75 
     | 
    
         
            +
                    end
         
     | 
| 
      
 76 
     | 
    
         
            +
             
     | 
| 
      
 77 
     | 
    
         
            +
                    response
         
     | 
| 
      
 78 
     | 
    
         
            +
                  end
         
     | 
| 
      
 79 
     | 
    
         
            +
             
     | 
| 
      
 80 
     | 
    
         
            +
                  def self.endpoint
         
     | 
| 
      
 81 
     | 
    
         
            +
                    "#{BASE_ENDPOINT}/accounts"
         
     | 
| 
      
 82 
     | 
    
         
            +
                  end
         
     | 
| 
      
 83 
     | 
    
         
            +
             
     | 
| 
      
 84 
     | 
    
         
            +
                  def self.parse_accounts(authorization, body)
         
     | 
| 
      
 85 
     | 
    
         
            +
                    raw = JSON.parse(body)
         
     | 
| 
      
 86 
     | 
    
         
            +
                    clients = []
         
     | 
| 
      
 87 
     | 
    
         
            +
             
     | 
| 
      
 88 
     | 
    
         
            +
                    raw['accounts'].each do |client|
         
     | 
| 
      
 89 
     | 
    
         
            +
                      clients << new(authorization,
         
     | 
| 
      
 90 
     | 
    
         
            +
                                     id: client['number'],
         
     | 
| 
      
 91 
     | 
    
         
            +
                                     user_id: raw['userId'],
         
     | 
| 
      
 92 
     | 
    
         
            +
                                     data: client)
         
     | 
| 
      
 93 
     | 
    
         
            +
                    end
         
     | 
| 
      
 94 
     | 
    
         
            +
             
     | 
| 
      
 95 
     | 
    
         
            +
                    clients
         
     | 
| 
      
 96 
     | 
    
         
            +
                  end
         
     | 
| 
      
 97 
     | 
    
         
            +
             
     | 
| 
      
 98 
     | 
    
         
            +
                  private_class_method :parse_accounts
         
     | 
| 
      
 99 
     | 
    
         
            +
                end
         
     | 
| 
      
 100 
     | 
    
         
            +
              end
         
     | 
| 
      
 101 
     | 
    
         
            +
            end
         
     |