├── .gitignore ├── config └── tdameritrade.php ├── src ├── Facades │ └── TdameritradeFacades.php ├── Api │ ├── Api.php │ ├── Accounts.php │ ├── Movers.php │ ├── Instruments.php │ ├── Market.php │ ├── Transactions.php │ ├── Options.php │ ├── Orders.php │ └── Price.php ├── TdameritradeServiceProvider.php └── Tdameritrade.php ├── tests ├── LaravelTest.php └── TdameritradeTest.php ├── .github └── workflows │ └── main.yml ├── phpunit.xml.dist ├── composer.json └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | /vendor 2 | -------------------------------------------------------------------------------- /config/tdameritrade.php: -------------------------------------------------------------------------------- 1 | env('TD_KEY'), 5 | 'callback' => env('TD_CALLBACK') 6 | ]; 7 | -------------------------------------------------------------------------------- /src/Facades/TdameritradeFacades.php: -------------------------------------------------------------------------------- 1 | client = $client; 17 | } 18 | 19 | public function client() 20 | { 21 | return $this->client; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /phpunit.xml.dist: -------------------------------------------------------------------------------- 1 | 2 | 12 | 13 | 14 | tests 15 | 16 | 17 | 18 | 19 | src/ 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /src/TdameritradeServiceProvider.php: -------------------------------------------------------------------------------- 1 | publishes([ 16 | __DIR__ . '/../config/tdameritrade.php' => config_path('tdameritrade.php') 17 | ]); 18 | } 19 | 20 | public function register() 21 | { 22 | $this->app->bind('tdameritrade', function () { 23 | return new Tdameritrade(); 24 | }); 25 | 26 | $this->mergeConfigFrom(__DIR__ . '/../config/tdameritrade.php', 'tdameritrade'); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/Api/Accounts.php: -------------------------------------------------------------------------------- 1 | client->getWithAuth('/accounts', [ 19 | 'query' => ['fields' => $fields] 20 | ]); 21 | } 22 | 23 | 24 | /** 25 | * get 26 | * Account balances, positions, and orders for a specific account. 27 | * @param string $account_id 28 | * @return void 29 | */ 30 | public function get(string $account_id) 31 | { 32 | return $this->client->getWithAuth('/accounts/' . $account_id); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/Api/Movers.php: -------------------------------------------------------------------------------- 1 | client->getWithAuth('/marketdata/' . $index . '/movers', [ 21 | 'query' => ['direction' => $direction, 'change' => $change] 22 | ]); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/Api/Instruments.php: -------------------------------------------------------------------------------- 1 | client->getWithAuth('/instruments', [ 20 | 'query' => ['symbol' => $ticker, "projection" => $projection] 21 | ]); 22 | } 23 | 24 | 25 | /** 26 | * get 27 | * Get an instrument by CUSIP 28 | * @param string $cusip 29 | * @return void 30 | */ 31 | public function get(string $cusip) 32 | { 33 | return $this->client->getWithAuth('/instruments/' . $cusip); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/Api/Market.php: -------------------------------------------------------------------------------- 1 | client->getWithAuth('/marketdata/hours', [ 20 | 'query' => ['markets' => implode(',', $markets)] 21 | ]); 22 | } 23 | return $this->client->getWithAuth('/marketdata/hours'); 24 | } 25 | 26 | 27 | /** 28 | * get 29 | * Retrieve market hours for specified single market 30 | * @param string $market 31 | * @return void Valid markets are EQUITY, OPTION, FUTURE, BOND, or FOREX 32 | */ 33 | public function get(string $market) 34 | { 35 | return $this->client->getWithAuth('/marketdata/' . $market . '/hours'); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mackensiealvarezz/tdameritrade-laravel", 3 | "description": "TD Ameritrade API Package For Laravel", 4 | "type": "library", 5 | "license": "MIT", 6 | "readme": "README.md", 7 | "authors": [{ 8 | "name": "Mackensie Alvarez", 9 | "email": "mackensiealvarez@gmail.com" 10 | }], 11 | "require": { 12 | "guzzlehttp/guzzle": "^6.5" 13 | }, 14 | "autoload": { 15 | "psr-4": { 16 | "Mackensiealvarezz\\Tdameritrade\\": "src/" 17 | } 18 | }, 19 | "autoload-dev": { 20 | "psr-4": { 21 | "Mackensiealvarezz\\Tdameritrade\\Tests\\": "tests/" 22 | } 23 | }, 24 | "extra": { 25 | "laravel": { 26 | "providers": [ 27 | "Mackensiealvarezz\\Tdameritrade\\TdameritradeServiceProvider" 28 | ], 29 | "aliases": { 30 | "Tdameritrade": "Mackensiealvarezz\\Tdameritrade\\Facades\\TdameritradeFacades" 31 | } 32 | } 33 | }, 34 | "require-dev": { 35 | "phpunit/phpunit": "^9.2", 36 | "orchestra/testbench": "^5.3" 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/Api/Transactions.php: -------------------------------------------------------------------------------- 1 | client->getWithAuth('/accounts/' . $account_id . '/transactions', [ 24 | 'query' => [ 25 | 'type' => $type, 26 | "symbol" => $symbol, 27 | 'startDate' => $startDate->format('Y-m-d'), 28 | 'endDate' => $endDate->format('Y-m-d') 29 | ] 30 | ]); 31 | } 32 | 33 | 34 | /** 35 | * get 36 | * Transaction for a specific account. 37 | * @param mixed $account_id 38 | * @param mixed $transaction_id 39 | * @return void 40 | */ 41 | public function get(string $account_id, string $transaction_id) 42 | { 43 | return $this->client->getWithAuth('/accounts/' . $account_id . '/transactions/' . $transaction_id); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/Api/Options.php: -------------------------------------------------------------------------------- 1 | client->getWithAuth('/accounts/marketdata/chains', [ 28 | 'query' => [ 29 | 'symbol' => $symbol, 30 | "strikeCount" => $strikeCount, 31 | 'contractType' => $contractType, 32 | 'includeQuotes' => $includeQuotes, 33 | 'strategy' => $strategy 34 | ] 35 | ]); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/Api/Orders.php: -------------------------------------------------------------------------------- 1 | client->getWithAuth('/orders', [ 24 | 'query' => [ 25 | 'fromEnteredTime' => $startDate->format('Y-m-d'), 26 | 'toEnteredTime' => $endDate->format('Y-m-d'), 27 | 'maxResults' => $maxResults, 28 | 'status' => $status, 29 | 'accountId' => $account_id 30 | ] 31 | ]); 32 | } 33 | 34 | /** 35 | * get 36 | * Get a specific order for a specific account. 37 | * @param string $account_id Account Number. 38 | * @param string $order_id Order ID 39 | * @return void 40 | */ 41 | public function get(string $account_id, string $order_id) 42 | { 43 | return $this->client->getWithAuth('/accounts/' . $account_id . '/orders/' . $order_id); 44 | } 45 | 46 | 47 | /** 48 | * place 49 | * Place an order for a specific account. 50 | * @param mixed $account_id Account ID 51 | * @param mixed $order Order 52 | * @return void 53 | */ 54 | public function place(string $account_id, array $order) 55 | { 56 | return $this->client->postWithAuth('/accounts/' . $account_id . '/orders', [ 57 | 'json' => $order 58 | ]); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/Api/Price.php: -------------------------------------------------------------------------------- 1 | $symbol, 37 | "endDate" => $endDate->format('Y-m-d'), 38 | 'startDate' => $startDate->format('Y-m-d'), 39 | 'periodType' => $periodType, 40 | 'period' => $period, 41 | 'frequencyType' => $frequencyType, 42 | 'frequency' => $frequency, 43 | 'needExtendedHoursData' => $needExtendedHoursData 44 | ]; 45 | $data = array_filter($data); 46 | return $this->client->getWithAuth('/marketdata/' . $symbol . '/pricehistory', [ 47 | 'query' => $data 48 | ]); 49 | } 50 | 51 | /** 52 | * quote 53 | * Get quote for a symbol 54 | * @param mixed $symbol 55 | * @return void 56 | */ 57 | public function quote(string $symbol) 58 | { 59 | return $this->client->getWithAuth('/marketdata/' . $symbol . '/quotes'); 60 | } 61 | 62 | /** 63 | * quotes 64 | * Get quote for one or more symbols 65 | * @param mixed $symbols 66 | * @return void 67 | */ 68 | public function quotes(array $symbols) 69 | { 70 | return $this->client->getWithAuth('/marketdata/quotes', [ 71 | 'query' => ['symbol' => implode(',', $symbols)] 72 | ]); 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /tests/TdameritradeTest.php: -------------------------------------------------------------------------------- 1 | assertEquals('access_token', $client->getAccessToken()); 24 | $this->assertEquals('refresh_token', $client->getRefreshToken()); 25 | } 26 | 27 | public function testReturnsOAuth() 28 | { 29 | 30 | Config::set('tdameritrade.callback', 'callback'); 31 | Config::set('tdameritrade.key', 'key'); 32 | $this->assertEquals(Tdameritrade::generateOAuth(), "https://auth.tdameritrade.com/auth?response_type=code&redirect_uri=" . config('tdameritrade.callback') . "&client_id=" . config('tdameritrade.key') . "%40AMER.OAUTHAP"); 33 | } 34 | 35 | public function testReturnsInstruments() 36 | { 37 | $client = new Tdameritrade('access_token', 'refresh_token'); 38 | $this->assertInstanceOf(Instruments::class, $client->instruments()); 39 | } 40 | 41 | public function testReturnsMakert() 42 | { 43 | $client = new Tdameritrade('access_token', 'refresh_token'); 44 | $this->assertInstanceOf(Market::class, $client->market()); 45 | } 46 | 47 | public function testReturnsMovers() 48 | { 49 | $client = new Tdameritrade('access_token', 'refresh_token'); 50 | $this->assertInstanceOf(Movers::class, $client->movers()); 51 | } 52 | 53 | public function testReturnsOrders() 54 | { 55 | $client = new Tdameritrade('access_token', 'refresh_token'); 56 | $this->assertInstanceOf(Orders::class, $client->orders()); 57 | } 58 | 59 | public function testReturnsPrice() 60 | { 61 | $client = new Tdameritrade('access_token', 'refresh_token'); 62 | $this->assertInstanceOf(Price::class, $client->price()); 63 | } 64 | 65 | public function testReturnsTransactions() 66 | { 67 | $client = new Tdameritrade('access_token', 'refresh_token'); 68 | $this->assertInstanceOf(Transactions::class, $client->transactions()); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![Continuous Integration](https://github.com/mackensiealvarezz/tdameritrade-laravel/workflows/Continuous%20Integration/badge.svg?branch=master) 2 | # TD Ameritrade API for Laravel 3 | 4 | This package is a wrapper for the TD Ameritrade API. You will need a [developer account](https://developer.tdameritrade.com/) to use this API. 5 | 6 | # Installing 7 | 8 | ## 1 . install the package via composer: 9 | ``` 10 | composer require mackensiealvarezz/tdameritrade-laravel 11 | ``` 12 | ## 2. Publish Config 13 | ``` 14 | php artisan vendor:publish 15 | ``` 16 | 17 | ## 3. Set ENV Variables 18 | Include these two variables inside of your .env 19 | ``` 20 | // .env 21 | TD_KEY="YOUR_KEY" 22 | TD_CALLBACK="CALLBACK" 23 | ``` 24 | 25 | ## 4. Include Package 26 | When using the package, don't forget to include It on top of the file 27 | 28 | use Mackensiealvarezz\Tdameritrade\Tdameritrade; 29 | 30 | # OAuth 31 | 32 | To use the API, the must have an access_token. You can easily create an access token using the redirect function. 33 | 34 | ## Creating OAuth URL 35 | To create a OAuth URL, you will need to use: 36 | 37 | Tdameritrade::redirectOAuth(); // will return string (url) 38 | **It is important that you create a callback route for the URL you set inside of the .env** 39 | 40 | ## Refresh Token 41 | To refresh the token and create another access_token. 42 | 43 | //Create client 44 | $client = new Tdameritrade('access_token', 'refresh_token'); 45 | //Refresh token 46 | $response = $client->refreshToken(); 47 | 48 | # Usage 49 | 50 | The package is written to use every class inside of **/src/api** as a function. 51 | 52 | ## Accounts 53 | 54 | ### List accounts 55 | 56 | This will return a list of all the accounts 57 | ``` 58 | //Create client 59 | $client = new Tdameritrade('access_token', 'refresh_token'); 60 | $accounts = $client->accounts()->list(); 61 | ``` 62 | 63 | ### Get account 64 | 65 | This will return all the information for one account. **Requires account_id** 66 | ``` 67 | //Create client 68 | $client = new Tdameritrade('access_token', 'refresh_token'); 69 | $accounts = $client->accounts()->get('account_id'); 70 | ``` 71 | 72 | ## Instruments 73 | 74 | ### Search 75 | 76 | This will return a list of tickers based on the symbol entered 77 | ``` 78 | //Create client 79 | $client = new Tdameritrade('access_token', 'refresh_token'); 80 | //Response 81 | $response = $client->instruments()->search('TESLA'); 82 | ``` 83 | 84 | ### Get 85 | 86 | This wil return one ticker information 87 | ``` 88 | //Create client 89 | $client = new Tdameritrade('access_token', 'refresh_token'); 90 | //Response 91 | $accounts = $client->instruments()->get('TSLA'); 92 | ``` 93 | 94 | ## Market Hours 95 | 96 | ### List 97 | 98 | This will return a list of all the different market hours 99 | ``` 100 | //Create client 101 | $client = new Tdameritrade('access_token', 'refresh_token'); 102 | //Response 103 | $response = $client->market()->list(); 104 | ``` 105 | 106 | ### Get 107 | 108 | This wil return one market information 109 | ``` 110 | //Create client 111 | $client = new Tdameritrade('access_token', 'refresh_token'); 112 | //Response 113 | $response = $client->market()->get('SPY.X'); 114 | ``` 115 | 116 | 117 | ## Movers 118 | 119 | ### Get 120 | 121 | This wil return a list of symbols that are moving 122 | ``` 123 | //Create client 124 | $client = new Tdameritrade('access_token', 'refresh_token'); 125 | //Response 126 | $response = $client->movers()->get('SPY.X', 'up', 'percent'); 127 | ``` 128 | 129 | ## Price 130 | 131 | ### History 132 | 133 | This will return a list of quotes for the ticker 134 | ``` 135 | //Create client 136 | $client = new Tdameritrade('access_token', 'refresh_token'); 137 | //Response 138 | $response = $client->price()->history('TSLA', Carbon::now(), Carbon::now()); 139 | ``` 140 | 141 | ### Get Quote 142 | 143 | This wil return the quote for one ticker 144 | ``` 145 | //Create client 146 | $client = new Tdameritrade('access_token', 'refresh_token'); 147 | //Response 148 | $response = $client->price()->quote('TSLA'); 149 | ``` 150 | 151 | ### Get Quotes 152 | 153 | This wil return the quote for multiple tickers 154 | ``` 155 | //Create client 156 | $client = new Tdameritrade('access_token', 'refresh_token'); 157 | //Response 158 | $response = $client->price()->quotes(['AAPL', 'FB']); 159 | ``` 160 | 161 | ## License 162 | 163 | 164 | The MIT License (MIT). Please see [MIT license](http://opensource.org/licenses/MIT) for more information. 165 | -------------------------------------------------------------------------------- /src/Tdameritrade.php: -------------------------------------------------------------------------------- 1 | access_token = $access_token; 37 | $this->refresh_token = $refresh_token; 38 | } 39 | 40 | public function getAccessToken() 41 | { 42 | return $this->access_token; 43 | } 44 | 45 | public function getRefreshToken() 46 | { 47 | return $this->refresh_token; 48 | } 49 | 50 | public static function generateOAuth() 51 | { 52 | return "https://auth.tdameritrade.com/auth?response_type=code&redirect_uri=" . config('tdameritrade.callback') . "&client_id=" . config('tdameritrade.key') . "%40AMER.OAUTHAP"; 53 | } 54 | 55 | public static function redirectOAuth() 56 | { 57 | return redirect(static::generateOAuth()); 58 | } 59 | 60 | public function refreshToken() 61 | { 62 | $body = [ 63 | 'grant_type' => "refresh_token", 64 | 'access_type' => 'offline', 65 | 'client_id' => config('tdameritrade.key'), 66 | 'refresh_token' => $this->refresh_token 67 | ]; 68 | 69 | return static::post('/oauth2/token', [ 70 | 'form_params' => $body 71 | ]); 72 | } 73 | 74 | public static function createAccessToken(string $code = null) 75 | { 76 | $body = [ 77 | 'grant_type' => 'authorization_code', 78 | 'access_type' => 'offline', 79 | 'client_id' => config('tdameritrade.key'), 80 | 'redirect_uri' => config('tdameritrade.callback'), 81 | 'code' => $code 82 | ]; 83 | 84 | return static::post('/oauth2/token', [ 85 | 'form_params' => $body 86 | ]); 87 | } 88 | 89 | public static function post(string $path, array $data = []) 90 | { 91 | $client = new Client([ 92 | 'base_uri' => SELF::BASE_URL 93 | ]); 94 | 95 | try { 96 | $res = $client->request('post', SELF::API_VER . $path, $data); 97 | return json_decode($res->getBody(), true); 98 | } catch (GuzzleException $e) { 99 | throw new Exception($e->getMessage()); 100 | } 101 | } 102 | 103 | public function postWithAuth(string $path, array $data = []) 104 | { 105 | $client = new Client([ 106 | 'base_uri' => SELF::BASE_URL, 107 | 'headers' => ['Authorization' => 'Bearer ' . $this->access_token] 108 | ]); 109 | 110 | try { 111 | $res = $client->request('post', SELF::API_VER . $path, $data); 112 | return json_decode($res->getBody(), true); 113 | } catch (GuzzleException $e) { 114 | throw new Exception($e->getMessage()); 115 | } 116 | } 117 | 118 | public function getWithAuth(string $path, array $data = []) 119 | { 120 | $client = new Client([ 121 | 'base_uri' => SELF::BASE_URL, 122 | 'headers' => ['Authorization' => 'Bearer ' . $this->access_token] 123 | ]); 124 | 125 | try { 126 | $res = $client->request('get', SELF::API_VER . $path, $data); 127 | return json_decode($res->getBody(), true); 128 | } catch (GuzzleException $e) { 129 | throw new Exception($e->getMessage()); 130 | } 131 | } 132 | 133 | public function __call($method, $parameters) 134 | { 135 | $class = static::getNamespace() . ucfirst($method); 136 | return new $class($this); 137 | } 138 | 139 | 140 | public static function getNamespace() 141 | { 142 | return __NAMESPACE__ . '\\Api\\'; 143 | } 144 | } 145 | --------------------------------------------------------------------------------