-
Notifications
You must be signed in to change notification settings - Fork 214
almost finished schwab, testing #742
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 1 commit
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
8ca2a12
almost finished, testing
grzesir cb64048
half finished schwab oauth
grzesir 0b7e879
Update copilot-instructions.md
grzesir 79848e8
Merge branch 'dev' into schwab-finish
grzesir fd9c019
Merge branch 'dev' into schwab-finish
grzesir 4ff9674
schwab fully working
grzesir 99a81cc
Update test_polygon.py
grzesir 141d787
fixed unit tests
grzesir 47a3870
fixed issue with it not letting you enter the token
grzesir 1f5f402
Update setup.py
grzesir File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,108 +1,212 @@ | ||
Schwab API Setup | ||
=============== | ||
Schwab | ||
====== | ||
|
||
Charles Schwab provides API access for automated trading and market data through its developer platform. This guide outlines how to set up your environment variables and complete the initial OAuth login process, which works seamlessly with any strategy once configured. | ||
Charles Schwab is a major US brokerage that now offers a modern Trader API for equities, options, and **futures *data* only (no trade endpoints yet)**. Lumibot supports Schwab for both live trading and data retrieval, using the official `schwab-py` library. | ||
|
||
.. note:: | ||
Schwab API access requires a developer account and application approval. You must apply for API access and set up your app in the Schwab Developer Portal. | ||
|
||
API Credentials | ||
--------------- | ||
|
||
To use Schwab with Lumibot, you need to set the following environment variables in your `.env` file: | ||
|
||
.. list-table:: Schwab API Credentials | ||
:widths: 30 50 20 | ||
:header-rows: 1 | ||
|
||
* - **Variable** | ||
- **Description** | ||
- **Example** | ||
* - `SCHWAB_API_KEY` | ||
- Your Schwab API key (Consumer Key) from the Developer Portal. | ||
- `abc123xyz` | ||
* - `SCHWAB_SECRET` | ||
- Your Schwab API secret. | ||
- `supersecret` | ||
* - `SCHWAB_ACCOUNT_NUMBER` | ||
- Your Schwab brokerage account number. | ||
- `12345678` | ||
* - `SCHWAB_REDIRECT_URI` | ||
- (Optional) OAuth2 callback URI (default: `https://127.0.0.1:8182`) | ||
- `https://yourdomain.com/callback` | ||
* - `TRADING_BROKER` | ||
- (Optional) Set to `schwab` to force Schwab as the broker. | ||
- `schwab` | ||
* - `SCHWAB_TOKEN_PATH` | ||
- (Optional) Path to store OAuth token.json (default: strategy dir). | ||
- `./token.json` | ||
|
||
Creating an App & Getting Keys | ||
------------------------------ | ||
|
||
1. Register on the `Schwab Developer Portal <https://developer.schwab.com/>`_. | ||
2. Go to **Dashboard → Apps → Create App**. | ||
3. Enter an app name and a **Callback URL** (must be HTTPS, ≤ 256 chars, matches exactly). | ||
4. Request the **Trader API** product, accept terms, and submit. | ||
5. Wait for manual approval (typically 1–3 business days). | ||
6. Once approved, copy your **API Key (Consumer Key)** and **API Secret** from the app details. | ||
|
||
OAuth2 Authentication Flow | ||
-------------------------- | ||
|
||
Before proceeding, ensure you have created a developer account at `developer.schwab.com <https://developer.schwab.com>`_ and registered an application to obtain your API credentials. | ||
|
||
Developer Account and Application Setup | ||
-------------------------------------- | ||
|
||
To use the Schwab API, you first need to create a developer account and register an application. This process will provide you with an **API Key** and **API Secret**, which are essential for authentication. | ||
|
||
1. **Create a Developer Account** | ||
|
||
- Visit `developer.schwab.com <https://developer.schwab.com>`_ and click **Sign Up**. | ||
- Follow the instructions to create your account. | ||
- Log in to access your dashboard. | ||
|
||
2. **Create and Configure an Application** | ||
|
||
- In your Schwab developer dashboard, navigate to the **Applications** section and click **Create Application**. | ||
- Fill in the required fields (app name, description, API Product, etc.). We recommend selecting **Accounts and Trading Production** unless you have a specific reason to choose otherwise. | ||
- Specify an **Order Limit** (the default is often 120 orders per minute). | ||
- Set your **Callback URL** to: | ||
|
||
``https://127.0.0.1:8182`` | ||
|
||
.. important:: | ||
Do not include a trailing slash. | ||
|
||
- Submit your application and wait for it to be approved (the status should eventually change to **Ready For Use**). | ||
- Once approved, retrieve your **API Key** and **API Secret** from the application details. | ||
|
||
Environment Variables Setup | ||
Schwab uses OAuth2 for authentication. The first time you run your strategy, a browser window will open for you to log in and approve access. A `token.json` file will be created in your strategy directory (or at `SCHWAB_TOKEN_PATH` if set). | ||
|
||
- **Access tokens** last 30 minutes; **refresh tokens** last 7 days. | ||
- The `schwab-py` library will auto-refresh tokens as needed. | ||
- If running on a server, run the login flow once locally and copy `token.json` to the server. | ||
- For headless/cloud environments, use the CLI/manual login helper (`schwab.auth.client_from_manual_flow`), which prints a URL to paste into any browser. | ||
- Keep `token.json` secure and out of version control. | ||
- If you delete or move `token.json`, you will need to re-authorize. | ||
|
||
.. warning:: | ||
If your refresh token expires (after 7 days without re-auth), you must repeat the browser login flow. | ||
|
||
**One-click cloud login (Replit · Render · any PaaS)** | ||
|
||
Deploy your bot and watch the logs. | ||
The first time Lumibot detects that `token.json` is missing, it prints a URL like: | ||
|
||
https://my-bot.repl.co/schwab-login | ||
|
||
1. Open that link once, sign in to Schwab, click **Allow**. | ||
2. You’ll see “✅ Schwab token saved”. | ||
3. Restart the service (or let Replit auto-restart). Done. | ||
|
||
As long as your bot checks Schwab at least once per day, the token | ||
auto-refreshes and you will *not* be asked to log in again. | ||
If the service is stopped for 7+ days, redeploy and repeat the link. | ||
|
||
(Optional) override the callback route with | ||
`SCHWAB_REDIRECT_URI=https://YOUR_DOMAIN/schwab-login`. | ||
|
||
Sandbox vs Production | ||
--------------------- | ||
|
||
Schwab offers a **Sandbox** environment for safe testing with synthetic accounts and data. | ||
|
||
- Enable Sandbox when creating your app, or promote your app later in the Developer Portal. | ||
- Use the same credentials; only the API base URL changes. | ||
- Use separate apps for production and sandbox to avoid confusion. | ||
|
||
Supported Assets & Order Types | ||
------------------------------ | ||
|
||
.. list-table:: Supported Asset Classes and Order Types | ||
:widths: 20 15 15 15 15 20 | ||
:header-rows: 1 | ||
|
||
* - **Asset** | ||
- **Market** | ||
- **Limit** | ||
- **Stop** | ||
- **Stop-Limit** | ||
- **Advanced (OCO/Bracket)** | ||
* - Stocks/ETFs | ||
- ✔ | ||
- ✔ | ||
- ✔ | ||
- ✔ | ||
- ✖ (not yet) | ||
* - Options | ||
- ✔ (buy/sell, open/close) | ||
- ✔ | ||
- — | ||
- — | ||
- ✖ (not yet) | ||
* - Futures | ||
- ✖ (quotes only) | ||
- ✖ | ||
- ✖ | ||
- ✖ | ||
- ✖ | ||
|
||
- Multi-leg/spread options and advanced orders are not yet implemented in Lumibot. | ||
- **Futures trading is not supported; only streaming quotes are available.** | ||
|
||
Market Data | ||
----------- | ||
|
||
- Real-time quotes, option chains, and historical bars (up to 15 years daily, 6 months intraday for equities/options). | ||
- **Level-I/II streaming quotes are available for equities, options, and futures; historical bars only for equities/ETFs.** | ||
- No extra entitlements required for individual developers. | ||
- Futures quotes available; historical futures bars not yet supported. | ||
|
||
Rate Limits & Token Expiry | ||
-------------------------- | ||
|
||
For Schwab API integration, you must set the following environment variables in your ``.env`` file (located in the same directory as your strategy). These variables allow your application to authenticate with Schwab's API seamlessly with any strategy you use. | ||
|
||
.. list-table:: Schwab Configuration | ||
:widths: 25 50 25 | ||
:header-rows: 1 | ||
|
||
* - **Variable** | ||
- **Description** | ||
- **Example** | ||
* - SCHWAB_API_KEY | ||
- Your Schwab API key obtained from the developer dashboard. | ||
- your_api_key_here | ||
* - SCHWAB_SECRET | ||
- Your Schwab API secret obtained from the developer dashboard. | ||
- your_api_secret_here | ||
* - SCHWAB_ACCOUNT_NUMBER | ||
- Your Schwab account number used for trading. | ||
- 123456789 | ||
- **~120 requests/minute** for data; **2–4 trade requests/sec**. | ||
- Exceeding limits returns HTTP 429 errors. | ||
- Error codes: `429-001` = rate, `429-005` = burst; back-off 60 seconds if hit. | ||
- Access tokens expire after 30 minutes; refresh tokens after 7 days. | ||
|
||
.. important:: | ||
|
||
Double-check that the API key, secret, and callback URL are entered exactly as specified on the Schwab developer portal to avoid authentication issues. | ||
Known Issues & Best Practices | ||
----------------------------- | ||
|
||
OAuth Process and Token Creation | ||
------------------------------- | ||
- Initial OAuth requires browser login every 7 days. | ||
- `token.json` must be unique per account/app. | ||
- Advanced orders (OCO/OTO/Bracket) not yet supported. | ||
- Callback URL must match exactly (including trailing slash). | ||
- Refresh tokens proactively (every 28–29 min) to avoid expiry. | ||
- Secure `token.json` (chmod 600) and rotate secrets regularly. | ||
- Use separate apps for sandbox and production. | ||
- **Attempting to place a futures order returns HTTP 400 “Unsupported instrument”.** | ||
- **No official docs for futures endpoints—implementation subject to change.** | ||
|
||
When you run your trading application for the first time, an OAuth flow will be initiated to securely log you into your Schwab account. During this process, you will see output in your terminal similar to: | ||
Example Strategy | ||
---------------- | ||
|
||
.. code-block:: text | ||
You can provide your Schwab credentials in several ways: | ||
- By creating a `.env` file in the same directory as your strategy (recommended for local development). | ||
- By setting them as secrets in Replit, or as environment variables in cloud platforms like Render. | ||
- By exporting them as environment variables in your shell. | ||
|
||
This is the browser-assisted login and token creation flow for | ||
schwab-py. This flow automatically opens the login page on your | ||
browser, captures the resulting OAuth callback, and creates a token | ||
using the result. The authorization URL is: | ||
**Example `.env` file:** | ||
|
||
https://api.schwabapi.com/v1/oauth/authorize?response_type=code&client_id=RfUVxotUc8p6CbeCwFmophgNZSat0TLv&redirect_uri=https%3A%2F%2F127.0.0.1%3A8182&state=6pYvtte5gHRZKXRyrQjkjHNIYuO2Ra | ||
.. code-block:: bash | ||
|
||
IMPORTANT: Your browser will give you a security warning about an | ||
invalid certificate prior to issuing the redirect. This is because | ||
schwab-py has started a server on your machine to receive the OAuth | ||
redirect using a self-signed SSL certificate. You can ignore that | ||
warning, but make sure to first check that the URL matches your | ||
callback URL (ignoring URL parameters). As a reminder, your callback URL | ||
is: | ||
# .env | ||
TRADING_BROKER=schwab | ||
SCHWAB_API_KEY=YOUR_APP_KEY | ||
SCHWAB_SECRET=YOUR_APP_SECRET | ||
SCHWAB_ACCOUNT_NUMBER=XXXXXXXX | ||
|
||
https://127.0.0.1:8182 | ||
Then, create your `main.py` (or `strategy.py`) file: | ||
|
||
See here to learn more about self-signed SSL certificates: | ||
https://schwab-py.readthedocs.io/en/latest/auth.html#ssl-errors | ||
.. code-block:: python | ||
|
||
If you encounter any issues, see here for troubleshooting: | ||
https://schwab-py.readthedocs.io/en/latest/auth.html#troubleshooting | ||
from lumibot.traders import Trader | ||
from lumibot.strategies.strategy import Strategy | ||
|
||
⸻ | ||
class MyStrategy(Strategy): | ||
def initialize(self): | ||
self.sleeptime = "1D" | ||
self.symbol = "SPY" | ||
|
||
Press ENTER to open the browser. Note you can call this method with interactive=False to skip this input. | ||
def on_trading_iteration(self): | ||
last = self.get_last_price(self.symbol) | ||
self.log_message(f"Last price for {self.symbol}: {last}") | ||
asset = self.create_asset(self.symbol) | ||
order = self.create_order(asset, 1, "buy") | ||
self.submit_order(order) | ||
|
||
After completing the OAuth flow: | ||
trader = Trader() | ||
strategy = MyStrategy() | ||
trader.add_strategy(strategy) | ||
trader.run_all() | ||
|
||
- A ``token.json`` file will be created and saved on your system. This file stores your login details (access tokens) so that you do not need to complete the OAuth process every time you run your application. | ||
- Ensure you keep this file secure, as it contains sensitive authentication details. | ||
Support & Contact | ||
----------------- | ||
|
||
Summary | ||
------ | ||
- Schwab Developer Portal: https://developer.schwab.com/ | ||
- API Documentation: https://schwab-py.readthedocs.io/ | ||
- Support: Developer Portal → Support → Create Ticket, or email api-development@schwab.com | ||
|
||
1. **Environment Variables**: Set ``SCHWAB_API_KEY``, ``SCHWAB_SECRET``, and ``SCHWAB_ACCOUNT_NUMBER`` in your ``.env`` file. | ||
2. **OAuth Flow**: On the first run, you'll complete a browser-assisted login process. A ``token.json`` file will be created to store your session tokens. | ||
3. **Callback URL**: Use ``https://127.0.0.1:8182`` exactly as specified when creating your application. | ||
.. note:: | ||
For advanced usage and troubleshooting, see the `schwab-py documentation <https://schwab-py.readthedocs.io/>`_ and the Lumibot source code for `Schwab` broker and `SchwabData` data source. | ||
|
||
.. important:: | ||
The example above shows what *our strategy* did in a sandbox environment; it is **not** investment advice. | ||
|
||
By following these steps, your Schwab API integration should be up and running with any trading strategy you choose to deploy. Happy trading! | ||
.. disclaimer:: | ||
This integration is for educational purposes only. Please consult with a financial advisor before using any trading strategy with real funds. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This comment was marked as resolved.
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.