Code Monkey home page Code Monkey logo

schwab-api's Introduction

Schwab API

This is not an official API or even a stable recreation of a Charles Schwab API. Functionality may change with any updates made by Schwab. As of December 2023, this API continues to work as expected.

This package enables buying and selling securities programmatically on Charles Schwab. Currently, we use a headless browser to automate logging in in order to get authorization cookies. All other functionality is done through web requests made to Schwab's own API.

Features

  • Buying and Selling tickers
  • Get quotes for multiple tickers
  • Get order information
  • Get transaction history
  • Get tax lot info
  • Account and Position Information
  • Limit / Stop orders are possible using trade_v2 parameters
  • Multiple individual account support
  • MFA and TOTP authentication
  • Async compatibility
  • Web Request implementation (with the exception of authentication)

Live Demo

I am currently using this package to place trades on Schwab using my website here.

Screenshot

Contribution

I would absolutely love contributions; as someone new to open source, I'd appreciate help in setting up a reliable system for PRs as well :)

Getting Started

Installing

Install using pypi and then download and install the playwright binaries:

pip install schwab-api
python -m playwright install

Set up your account to use TOTP

In order to login to Schwab without having to go through SMS verification everytime, you'll need to create an authentication token (TOTP) and attach that to your Schwab account.

  1. Download a TOTP app like Google Authenticator.
  2. Go to my website and generate a TOTP key there by clicking 'Generate TOTP' and following the instructions. You should get a Symantec ID and a TOTP key/QR code.

Alternatively, you can do this programmatically:

from schwab_api import generate_totp

symantec_id, totp_secret = generate_totp()

print("Your symantec ID is: " + symantec_id)
print("Your TOTP secret is: " + totp_secret)
  1. Open Google Authenticator and click the + button to add a new account
  2. Either enter the TOTP key manually and scan the QR code from step 2.
  3. Log in to the Schwab security center
  4. Under Two-Step Verification, select Always at Login, and then select "Security Token" as your method.
  5. Enter the Symantec ID from step 2 into the Credential ID field.
  6. Enter the 6-digit code from Google Authenticator into the Security Code field.
  7. Done! Now keep your TOTP secret from step 2 handy as your SCHWAB_TOTP_SECRET in your .env file under the example directory.

Quickstart

You can run this code in a Colab Notebook here.

Here's some code that logs in, gets all account holdings, and makes a stock purchase:

from schwab_api import Schwab
import pprint

# Initialize our schwab instance
api = Schwab()

# Login using playwright
print("Logging into Schwab")
logged_in = api.login(
    username=username,
    password=password,
    totp_secret=totp_secret # Get this by generating TOTP at https://itsjafer.com/#/schwab
)

# Get information about a few tickers
quotes = api.quote_v2(["PFE", "AAPL"])
pprint.pprint(quotes)

# Get information about all accounts holdings
print("Getting account holdings information")
account_info = api.get_account_info()
pprint.pprint(account_info)

print("The following account numbers were found: " + str(account_info.keys()))

print("Placing a dry run trade for AAPL stock")
# Place a dry run trade for account 99999999
messages, success = api.trade_v2(
    ticker="AAPL", 
    side="Buy", #or Sell
    qty=1, 
    account_id=99999999, # Replace with your account number
    dry_run=True # If dry_run=True, we won't place the order, we'll just verify it.
)

print("The order verification was " + "successful" if success else "unsuccessful")
print("The order verification produced the following messages: ")
pprint.pprint(messages)

TODO

  • Currently, we use a headless browser to login to Schwab; in the future, we want to do this purely with requests.
  • Documentation of functionality

Development Guide

Want to extend functionality? Here's how to get started:

  1. After forking, install dependencies:
pip install .
playwright install && playwright install-deps
  1. Run the example script:
pip install . && python example/example.py
  1. Iterate on existing code:
  • Authentication largely exists in schwab_api/authentication.py and is done using Playwright.
  • Trading happens in schwab_api/schwab.py in two functions: trade and trade_v2 which use the legacy and new API respectively. Neither of these APIs are documented and were largely just reverse engineering through sniffing network requests in the UI.

Deployment

Bumping the version number in setup.py will automatically trigger a deployment that must be approved by itsjafer@.

schwab-api's People

Contributors

4rumprom avatar cnmuggle avatar gyias avatar itsjafer avatar lentissimo avatar maxxrk avatar mehere avatar qingqilei avatar taylorconor avatar tristanpenman avatar winesproof avatar

Stargazers

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

Watchers

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

schwab-api's Issues

Auto renew token

The token times out in about 2 mins "invalid_token"}']. In the TD API it would auto refresh that token.

Know anything on that?

thanks again

margin account orders hit and miss

Orders input sometimes and sometimes do not.

They are also hit or miss on selling

The middle account is a margin account and will not buy or sell.

The account after will always fail selling after the middle account fails.

Schwab 1 account ********: The order verification produced the following messages: ['This order may result in an oversold/overbought position in your account. Please check your position quantity and/or open orders.']
unsuccessful
Schwab 1 account ********: The order verification produced the following messages: ['No trades are currently allowed']
unsuccessful
Schwab 1 account ********: The order verification produced the following messages: ['']


Here is an example of it buying where the middle account fails.
It will buy after the middle account fails in this case.
Schwab 1 account ********: The order verification was successful
unsuccessful
Schwab 1 account ********: The order verification produced the following messages: ['No trades are currently allowed']
Schwab 1 account ********: The order verification was successful


A lot of the time they just all fail

Schwab 1 account ********: The order verification produced the following messages: ['']
unsuccessful
Schwab 1 account ********: The order verification produced the following messages: ['']
unsuccessful
Schwab 1 account ********: The order verification produced the following messages: ['']
unsuccessful
Schwab 1 account ********: The order verification produced the following messages: ['']
unsuccessful
Schwab 1 account ********: The order verification produced the following messages: ['']

Error: It looks like you are using Playwright Sync API inside the asyncio loop. Please use the Async API instead.

Hello,
I am working on implementing the schab-api package with my trading strategy, and have gotten the error:

"Error: It looks like you are using Playwright Sync API inside the asyncio loop. Please use the Async API instead."

After some investigation, it looks like there is an issue with using the schwab-api within spyder. Is there a workaround for this? I saw that there was a way to get things to run on google colab, but the solution does not work locally for either spyder or jupyter notebook.

totp secret

My totp secret quit working last week. I made a new one and that still doesnt work. Has there been a change with Schwab that this functionality changed? Debugging a bit it falls back to two factor authentication print out via sms.

Options not working anymore

I guess you must not see closed cases posts so repost.

I see the difference now. The options are what stopped working
quotes = api.quote_v2(["SPY 231219C00474000"])
does not work
quotes = api.quote_v2(["SPY"])
does work.

Did you change the format for options?

thanks

Login form name

Looks like Schwab pushed some changes on the front-end of their Login page:
https://www.schwab.com/public/schwab/nn/login/login.html?lang=en

The iframe seems to have been renamed to 'lmsSecondaryLogin'. The current code in schwab.py throws an error:

self.page.frame(name="loginIframe").fill("input[name=\"LoginId\"]", "")

Traceback (most recent call last):
  ...[snipped]...
  File "E:\...\schwab_api\schwab.py", line 101, in login
    self.page.frame(name="loginIframe").fill('input[name="LoginId"]', "")
AttributeError: 'NoneType' object has no attribute 'fill'

Changing all lines with

self.page.frame(name="loginIframe")

to

self.page.frame(name="lmsSecondaryLogin")

should do the trick

Nice work with this library so far. Hoping we'll get an official Schwab API some day...

order confirmation to buy or sell a symbol that's traded before today

The order confirmation doesn't work if I place an order to buy, say AAPL again the second time. It produces this message in the order verification

'Please Note: This account shows trading activity today for %SYMBOL%. Please '
'review Order Status to prevent a duplication of orders. (OE254)']

The order_confirmation produced this response:
{'Messages': [{'ApplicationCode': 'DO', 'Id': 309, 'ShortName': 'DO0309', 'SequenceNumber': 0, 'TypeCode': 4, 'OccuranceNumber': 0, 'SubstitutionParam1': 'Tradability', 'SubstitutionParam2': '', 'Message': 'Order Affirmation required. (DO309)'}], 'MessageCounts': {'BusinessReject': 1}, 'ReturnCode': 4, 'EtfMsgCode': ''}

Somehow, I believe url.order_confirmation has to be modified in schwab.py.

Edit:
I also tested trade_v2: if you have held some stocks, say, USFR, in your account and you are trying to issue a new market order to buy more, it'll result in the following verification message (unsuccessful):

Placing a market order trade for USFR stock
unsuccessful
The order verification produced the following messages:
['Your dividend instructions for this order differ from those of your existing '
'position in this security. Placing this order will change existing '
'instructions from "Yes" to "No" for your position - even if this order does '
'not fill. (OE585)',
'This account currently holds 40 shares of USFR. (AC109)',
'You are purchasing an Exchange Traded Fund which tracks an index, a '
'commodity or a basket of assets, but trades like a stock on an exchange. '
'Please read the prospectus carefully before investing. (DO856)',
'*It is your responsibility to choose the cost basis method appropriate to '
'your tax situation. Failure to select the proper cost basis method may cause '
'you to pay more tax than necessary. Schwab does not provide tax advice and '
'encourages you to consult with your tax professional. View <A '
'href="javascript:open('https://client.schwab.com/secure/cc/help/trade/stocks/tradestocks_verification?cmsid=P-2522495&lvl1=help&lvl2=trade#cost_basis',682,520,'YES')">Cost '
'Basis Reporting for additional information on <A '
'href="javascript:open('https://client.schwab.com/secure/cc/help/trade/stocks/tradestocks_verification?cmsid=P-2522495&lvl1=help&lvl2=trade#cost_basis',682,520,'YES')">cost '
'basis method choices and how Schwab reports adjusted cost basis '
'information to the IRS. (OE917)',
'Quote at the time of order verification: $50.25 Ask']

Response 413 error in get_account_info_v2()

Hi,
get_account_info returns info for the selected account, not all accounts.
So, I try to use get_account_info_v2, but the response is always 413.
Does anyone else meet this issue?

Playwright timeout when using Quickstart Code

Hello, and thank you for your work on the schwab-api! I have been using this for a long time without any issues when suddenly it started timing out. My login and secrets work correctly when I use the website (https://itsjafer.com/#/reversesplit), but when I use the same values in the Quickstart code (https://github.com/itsjafer/schwab-api#quickstart) I get the following output:

Logging into Schwab
Traceback (most recent call last):
  File "/Users/ndane/Documents/Github/auto-rsa/test.py", line 9, in <module>
    logged_in = api.login(
  File "/usr/local/lib/python3.10/site-packages/schwab_api/authentication.py", line 85, in login
    self.page.wait_for_load_state('networkidle')
  File "/usr/local/lib/python3.10/site-packages/playwright/sync_api/_generated.py", line 7371, in wait_for_load_state
    self._sync(self._impl_obj.wait_for_load_state(state=state, timeout=timeout))
  File "/usr/local/lib/python3.10/site-packages/playwright/_impl/_sync_base.py", line 89, in _sync
    return task.result()
  File "/usr/local/lib/python3.10/site-packages/playwright/_impl/_page.py", line 512, in wait_for_load_state
    return await self._main_frame.wait_for_load_state(**locals_to_params(locals()))
  File "/usr/local/lib/python3.10/site-packages/playwright/_impl/_frame.py", line 231, in wait_for_load_state
    return await self._wait_for_load_state_impl(state, timeout)
  File "/usr/local/lib/python3.10/site-packages/playwright/_impl/_frame.py", line 255, in _wait_for_load_state_impl
    await wait_helper.result()
playwright._impl._api_types.TimeoutError: Timeout 30000.0ms exceeded.
=========================== logs ===========================
"commit" event fired
"load" event fired
============================================================

I think it may be related to the issue (#13) but would appreciate a solution. Thank you!

TOTP login failing

My script stopped working today, trying to fall back to the SMS login method after a failed TOTP login attempt.

I printed the returned URL and got this output:

https://client.schwab.com/Login/SignOn/LoginProcess.aspx?ReturnURL=%2fAreas%2fTrade%2fAllInOne%2fIndex.aspx%3fShowUN%3dYES

It's been working well until two days ago, so I'm assuming there has been a change in Schwab's TOTP login procedure recently?

Locking My Account

Hi,

Thank you for all your working making this api.

Starting yesterday, I'm getting locked out of my account when I run a script. I'm not sure if this has to do with the recent addition of dotenv, but when using the dotenv code, I could not log in at all, so I removed it. Without dotenv, I logged in a number of times and tested my script, but the last two attempts required a call to Schwab in order to get back into the account.

Do you know of this problem and have a solution?

Thank you,

Phil

HTTP GET and POST request Data for VBA Excel.

Good afternoon Jafer.
I have been searching the whole internet for a way automate Excel with Charles Schwab.

Your method seems to be the only available option since Microsoft retired IE.

I have very little knowledge of Python, I dedicate most of my time to VBA because of the simple integration with Excel.

I am trying to import information from my Schwab’s account in to excel and trade stocks directly from excel.

(used to do it with Internet explorer).
Also imported most information with M code Table query’s
I have also done this for the TD Ameritrade, but they have an actual API.

On the description, you indicate you perform web requests to the Schwab own API.

I have attempted to go thru the code but have not seen how you send the GET and POST requests to the API.
I am looking for the structure of the Body and the request headers.
Do you have the actual GET or POST HTTP request that is sent to Charles Schwab’s?

Thanks
Victor

Stock Slices?

Hi.

I hope you are having a great 2022 so far.

I might have missed this; does the library support stock slices? If not, what would be needed to do so?

Thanks in advance.

Unable to login - Timeout error

I tried the script both on Colab and my local computer, and on both places, I ran into the following error:

(base) C:\Users\arsab\Desktop\Jupyter>python schwab.py
Logging into Schwab
Traceback (most recent call last):
  File "C:\Users\arsab\anaconda3\lib\site-packages\schwab_api\authentication.py", line 124, in login
    self.page.frame(name=login_frame).press("[placeholder=\"Password\"]", "Enter")
  File "C:\Users\arsab\anaconda3\lib\site-packages\playwright\_impl\_sync_base.py", line 79, in __exit__
    self._event.value
  File "C:\Users\arsab\anaconda3\lib\site-packages\playwright\_impl\_sync_base.py", line 59, in value
    raise exception
  File "C:\Users\arsab\anaconda3\lib\site-packages\playwright\_impl\_frame.py", line 208, in continuation
    event = await wait_helper.result()
playwright._impl._api_types.TimeoutError: Timeout 30000ms exceeded.
=========================== logs ===========================
waiting for navigation until 'load'
============================================================

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Users\arsab\Desktop\Jupyter\schwab.py", line 17, in <module>
    logged_in = api.login(
  File "C:\Users\arsab\anaconda3\lib\site-packages\schwab_api\authentication.py", line 126, in login
    raise Exception("Login was not successful; please check username and password")
Exception: Login was not successful; please check username and password

Error when placing order: This order cannot be accepted. Please ensure logged into correct account for order processing through Charles Schwab or TD Ameritrade

get account and position are both ok, but an error occurred when placing an order.
messages, success = api.trade_v2(
ticker="AAPL",
side="Buy", #or Sell
qty=1,
account_id=XXXX,
)

"orderMessages":
        [
            {
                "messageId": "DO3120",
                "message": "This order cannot be accepted. Please ensure logged into correct account for order processing through Charles Schwab or TD Ameritrade",
                "legNumber": 0,
                "disclaimerCode": "",
                "o2Code": "",
                "isCheckAffirm": "",
                "versionCode": "",
                "localizationCode": "US",
                "severity": "30",
                "renewal": false,
                "moduleShortName": "DO3120",
                "disclosureContent": "",
                "msgSubtnParam1": "",
                "msgSubtnParam2": "",
                "isTopLevel": false,
                "redirectMessage": null
            }
]

cant authenticate

Hi, I downloaded symantec VIP and told schwab about it. i dont understand where I get the topt token from

Allow session to be cached to disk

Thanks for your work on this library. I was so glad to find it!

I'm currently using the library in a few different ways - some smaller scripts, but also a long-running server. In both cases, it has been useful to cache the session data between runs, to avoid the login step. The way I've implemented this is to write the cookies and headers to a JSON file, and to read those before attempting to log in.

I've recently rebased my changes against @4rumprom's async branch, and you can see the diff here:
https://github.com/4rumprom/schwab-api/compare/Async...tristanpenman:schwab-api:cache-session?expand=1

If this is something that you would be interested in supporting, I can raise a PR once @4rumprom's changes are merged.

`get_account_info_v2` KeyError: costDetail

When getting account info using get_account_info_v2, sometimes the returned stock info has no costDetail fields (for example, the stock NXU for some reason). This causes an error when trying to build the position object.

For example, this is the position data for NXU when printed:
{ "quantity": 1, "quantityBeforeSplit": 1, "marginRequirement": 0, "percentageOfAccount": 0.63, "symbolDetail": { "symbol": "NXU", "cusip": "62956D204", "description": "NXU INC CLASS A", "quoteSymbol": "NXU", "defaultSymbol": "NXU", "schwabSecurityId": 95217935, "underlyingSchwabSecurityId": 0, "isLink": True, "isMarginable": True, "securityGroupCode": "COMNEQTY", "ruleSetSuffix": 0, "accountingRuleCode": 1, "positionType": 0, "securityType": 1, "symbolForDetailedQuotes": "NXU", }, "priceDetail": { "price": 2.66, "priceChange": 0, "priceChangePercent": 0, "priceDate": "12/28/2023", "isPriceRealTime": True, "marketValue": 2.66, "dayChange": 0, "dayChangePercent": 0, }, "reinvestDetail": {}, "marginDetail": { "pegAmount": 0, "nakedQuantity": 0, "nakedRequirementAmount": 0, "spreadQuantity": 0, "spreadRequirementAmount": 0, "strangleQuantity": 0, "strangleRequirementAmount": 0, "coverQuantity": 0, }, }

Which causes the below error:
Screenshot 2023-12-28 at 6 48 21 PM

This isn't happening with every stock, but if an account holds the problematic stock then it crashes

self.page.wait_for_load_state('networkidle') Causing Login Failure

Seems Schwab may have made a change about a month ago causing all instances of a wait for networkidle load state to fail. I've solved it in my own code by simply removing all self.page.wait_for_load_state('networkidle') lines, as they don't seem to be needed and it seems Playwright suggests the same generally.

Symantec ID not working anymore

Hello,
First let me thank you for this great package!
Login started to fail today and even logging into the app or web is not working stating security code is not valid. I called customer support and when they tried the Symantec Id I had or any new one generated by the script it is not working. Would it be possible for you to look into that? I mean is the vipaccess package not the latest version or its author might have addressed the issue in a newer version ?
Sorry if I'm making some assumptions here, my python knowledge is rather limited.

Michel

Error: "request entity too large"

As I mentioned in #16 (comment), I started getting "request entity too large" errors all over the place, but I first noticed it in trade_v2().

While debugging the error in an IPython session (embed() right after a failed post request), I found by accident that re-doing the post request after fiddling with self.headers worked- even if I didn't actually change the keys/values in self.headers, but merely assigned one of them to the same value that it already had! If I instead retried the request in an IPython session without fiddling with self.headers, it repeatedly failed with the "request entity too large" error. Go figure.

Since that didn't make sense, I inspected a few things with that successful request compared to the unsuccessful request prior to my IPython session, and I noticed that the successful one omitted the 'ADRUM_BT1' and 'ADRUM_BTa' cookies. So I added a few lines in the code prior to the post request to delete these cookies, and it worked. I ended up adding this before every request throughout the code since these errors occurred in a variety of places.

I would like to think there's a good explanation and/or better fix for this. Hopefully someone out there has some ideas.

Not Placing orders

When placing an order the following message is produced and it does not place the order. This happens whether buying or selling.

unsuccessful
[11:18 AM]
The order verification produced the following messages: ['message not found', 'Please note that the issuer of this security is deficient in meeting the Exchange\x92s continued listing requirements. You may want to consider doing further research before placing this order. (DO840)', 'Please Note: %SYMBOL% has a special maintenance requirement of %2%%. (AC157)']
[11:18 AM]
unsuccessful

Open Orders Support

Great project! Example code works great. Have you looked into how to implement retrieving account open orders?

Is there a way to pull ticker info like in the TD API?

In the TD API I was using I was pulling ticker info like this
call_quotes = TDSession.get_quotes(instruments=[callSymbol])

Then I could parse the results getting volume, bid/ask, etc. I am not seeing that listed anywhere for this API?

Trying to recreate my TD code that has been dialed in over 3 years and lost it all with the move to Schwab. Not cool.

thanks a lot

Selecting account for orders_v2

I was able to specify the account in orders_v2() by adding:
self.headers["schwab-client-account"] = account_id

The bigger issue I'm having is that the response doesn't seem to populate the RemainingQty (it's always zero in my attempts), so I had to figure out a much more convoluted and probably unreliable way to figure out how my orders executed.

quote function change?

I see it is now quotes = api.quote_v2?
But I get this message
(['{"errors":[{"id":"59667069-9c6f-052a-9d4e34795291","status":"500","title":"InternalServerError","details":"Server '
'Error - Error while getting quotes"}]}'],
False)

Not sure what changed but nothing is working for me now.
thanks

Can't place order - This account currently holds %1% shares of %SYMBOL%. (AC109)

I've been getting this error message when placing orders recently.

'message not found', 'This account currently holds %1% shares of %SYMBOL%. (AC109)'

I tried logging the responses, and the above message seemed to be coming from the verification response.

The confirmation response looked like this:

{'Messages': [{'ApplicationCode': 'DO', 'Id': 9008, 'ShortName': '', 'SequenceNumber': 0, 'TypeCode': 4, 'OccuranceNumber': 0, 'SubstitutionParam1': 'OrderId', 'SubstitutionParam2': '0', 'Message': 'STOP: A problem was detected which may have affected your order placement. <B>Please check the Order Status screen to confirm that your order has been received.</B> If your order appears, the transaction was successful. If you do not see your trade, please contact customer support for assistance.  (DO9008)'}], 'MessageCounts': {'BusinessReject': 1}, 'ReturnCode': 4, 'EtfMsgCode': ''}

I checked the order status just in case, but there were no orders placed.

Limit Orders/Stop-loss Support?

This project is great! Was wondering if there is any plan to add support for limit orders and stop-loss settings. Unless I am missing something, I only see the the possibility of placing market orders.

Playwright Sync API issue

Error: It looks like you are using Playwright Sync API inside the asyncio loop.
Please use the Async API instead.

How do I do that?

Login issue

image

It seems the user-agent passed along with the playwright identification is causing this page to show up, which in turn causes the identification to fail as of this morning.

A quick fix would be to update the user-agent string, however, a more robust solution is needed.

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.