Thinkorswim autotrading

Any update on hooking up with Thinkorswim for autotrading?

maybe just TD Ameritrade regular trading platform if Thinkorswim is not compatable?

ToS does not provide any programatically access to necessary data, like orders, order status events, account positions etc through their scripting language.

Their new API must be investigated, but that is for end user (account holders) only, so a client side plugin / app is inevitable.

Would be great to add TD (ToS) at least to PlatformTransmit service, I will work on that.

3 Likes

Any update to above? Is the platformTransmit service working with Ameritrade now? Please advise.

I have python code for algorithmic trading via Ameritrade’s retail API. There institutional side has API access as well, but is much more difficult to obtain access. Using the retail API I’m able to place any type of trade, query positions and balances, etc. It shouldn’t be too difficult for C2 to enable this feature at least for retail accounts. Institutional is a different story. Also, I’d be happy to share the code with anyone interested, just drop me a line.
Tony Roylance

Yes, obviously we would love to work with Ameritrade. The problem is that Ameritrade would not obviously love to work with Collective2.

More specifically: we are unable to connect to Ameritrade’s API, even on behalf of its customers, without AMTD’s permission.

For what it’s worth, we’ve been hocking them for about 15 years, and so far the response has been (I paraphrase): “Go away.” But it’s a new decade, and so who knows.

Thanks.

Matthew

P.S. We will continue to pursue this, and I promise to let you know when we have success.

4 Likes

Too bad. Somehow I imagine that if the Schwab purchase goes through they won’t be any different.

Talking to the Ameritrade institutional API guy he said his job is safe for the time being because Schwab’s API isn’t nearly as robust. Hopefully, they’ll play nice with C2. Thanks for the update Matthew!
Tony

1 Like

love to take a look at the code you have with TD API… tried to use other python tool like ibridgepy. doesn’t work as expected

Sorry for the delay, working on tons of other projects. This will get you started. The orders are on an excel sheet that contains ticker/quantity/type of order/price (if not market). I’ll upload more code as I find it. Feel free to use it. Hopefully this is ok with Matthew.
Tony Roylance

# -*- coding: utf-8 -*-
"""
Created on December 9, 2019
Author: Tony Roylance
Algorithmic Trading App
"""
import requests
from tdlogin import account_id
from tdaccesstoken import access_token
import time
import xlwings as xw
import runpy

app = xw.App(visible=False)
wb = xw.Book(r'c:/python373/ordersheet_full.xlsx')
sheet = wb.sheets['orders']

runoap=input('Run tdoauthproc? In the console on the lower right enter "y" or "n" and press enter')
if runoap == 'y':
    runpy.run_module(mod_name='tdoauth_proc_selenium')

rownum = 2
while (sheet.range('A'+str(rownum)).value != None):
    ticker = sheet.range('A'+str(rownum)).value
    qty = sheet.range('B'+str(rownum)).value
    stopprice = sheet.range('C'+str(rownum)).value
    ordertype = sheet.range('D'+str(rownum)).value
    
    #print(str(value))
    #print(rownum)   
    print('ticker'+str(rownum-1)+' = '+str(ticker))
    print('quantity'+str(rownum-1)+' = '+str(qty))
    print('stopprice'+str(rownum-1)+' = '+str(stopprice))
    print('ordertype'+str(rownum-1)+' = '+str(ordertype))
    rownum += 1
    
    if ticker is not None:
        header = {'Authorization': "Bearer {}".format(access_token),
                  "Content-Type":"application/json"}

    
        endpoint = r"https://api.tdameritrade.com/v1/accounts/{}/orders".format(account_id)
    
        payload = {'orderType':'STOP',
                   'session':'NORMAL',
                   'duration':'DAY',
                   'orderStrategyType':'SINGLE',
                   'stopPrice':stopprice,
                   'orderLegCollection':[{'instruction':ordertype,'quantity':qty,'instrument':{'symbol':ticker,'assetType':'EQUITY'}}]}
        content = requests.post(url = endpoint, json = payload, headers = header)
    
        content.status_code
        print(content)
        status="ticker = {} Quantity = {} Ordertype = {}"
        print(status.format(ticker,qty,ordertype))

        #runpy.run_module(mod_name='tdplaceatrade')
        time.sleep(2)
    
app.kill()

print(xw.apps)

1 Like

This will get you a ticker quote from TDA

# -*- coding: utf-8 -*-
"""
Created on Mon Jul 15 18:20:26 2019

@author: Tony Roylance
"""

import runpy
import pprint
import requests
from tdlogin import account_id

from datetime import date
import time
import requests

import xlwings as xw
app = xw.App(visible=False)
wb = xw.Book(r'C:/python373/ordersheet.xlsx')

#from openpyxl import load_workbook
#wb=load_workbook(filename='c:\\python373\\ordersheet.xlsx',data_only=True)
#sheet=wb.sheets('00001')

#ticker1=sheet['A2'].value

tdoa = input('run tdoa? type "y" or n in console: ')
if tdoa=='y':
    runpy.run_module(mod_name='tdoauthproc_xlwings')

print('Type Ticker symbol(s) for recent close data IN CAPS')
ticker=input()

today = date.today()
from tdaccesstoken import access_token
header = {'Authorization': 'Bearer {}'.format(access_token), 'Content-Type':'application/json'}

#endpoint = r"https://api.tdameritrade.com/v1/marketdata/{}/quotes".format(ticker)

endpoint = r"https://api.tdameritrade.com/v1/marketdata/{}/quotes".format(ticker1)

response = requests.get(url = endpoint, headers = header)

parsed_response = response.json()

#pprint.pprint(parsed_response)
last_price1 = parsed_response[ticker1]['lastPrice']

print('The latest price for '+ticker1+' is: ',format(last_price1))

app.quit()
app.kill()


1 Like

Authentication. To use TDA’s API you must go through an authentication process

# -*- coding: utf-8 -*-
"""
Created on Tue Jul 16 10:31:07 2019

@author: Tony Roylance
"""

import time
import urllib
import requests

from selenium import webdriver
from tdlogin import client_id, password, username

browser = webdriver.Chrome(r'C:\python373\chromedriver')

#executable_path = {'executable_path': r'C:\python373\chromedriver'}
#browser = Browser('chrome', **executable_path, headless = False)

#define the components of the url
method = 'GET'
url = 'https://auth.tdameritrade.com/auth?'
client_code = client_id + '@AMER.OAUTHAP'
payload = {'response_type':'code','redirect_uri':'http://localhost/test','client_id':client_code} #works
#payload = {'response_type':'code','redirect_uri':'https://127.0.0.1','client_id':client_code}

#build the url
built_url = requests.Request(method,url,params = payload).prepare()
built_url = built_url.url

#go to the url
browser.get(built_url)

# define the elements to pass through to the form

payload = {'username':username,'password':password}
#fill out each element in the form
#browser.find_by_id("username").first.fill(payload['username'])
tdelem = browser.find_element_by_id('username')
tdelem.send_keys(username)

#browser.find_by_id("password").first.fill(payload['password'])
tdelem_pw = browser.find_element_by_id('password')
tdelem_pw.send_keys(password)
 
#browser.find_by_id("accept").first.click()
first_accept = browser.find_element_by_id('accept')
type(first_accept)
first_accept.click()


time.sleep(2)
#click to accept terms and conditions
#browser.find_by_id("accept").first.click()
second_accept = browser.find_element_by_id('accept')
type(second_accept)
second_accept.click()


time.sleep(2)
new_url = browser.current_url

#grab url and parse
parse_url = urllib.parse.unquote(new_url.split('code=')[1])
#close the browser
browser.quit()
#print(parse_url)

#define the endpoint
urlnew = r'https://api.tdameritrade.com/v1/oauth2/token'
headers = {'Content-Type':"application/x-www-form-urlencoded"}
#define the payloadnew
payloadnew={'grant_type':'authorization_code',
            'access_type':'offline',
            'code':parse_url,
            'client_id':client_id,
            'redirect_uri':'http://localhost/test'}
            #'redirect_uri':'https://127.0.0.1'}
authReply=requests.post(urlnew,headers=headers,data=payloadnew)
#convert json to string to dictionary
decoded_content = authReply.json()
access_token=decoded_content['access_token']
headers = {'Authorization': "Bearer {}".format(access_token)}
#print it out to the console, what the hell
#print(access_token)
#print it to a text file
f = open('tdaccesstoken.txt','w+')
f.write(access_token)
f.close()
#print it to a python file so it can be easily re-imported
import pprint
#pprint.pformat(access_token)
fileObj=open('tdaccesstoken.py','w')
print('Writing access token...')
fileObj.write("access_token=")
fileObj.write(pprint.pformat(access_token))
fileObj.close()
print('access token saved')







This will get you the authentication code, or at least it used to. We’ve moved to using TDA Institutional so I don’t use this anymore. Hopefully it can be adapted for the current environment.

# -*- coding: utf-8 -*-
"""
Created on Tue Jul 16 10:31:07 2019

@author: Tony Roylance
"""

import time
import urllib
import requests
from splinter import Browser
#from tdlogin import client_id, password, username
import xlwings as xw

app = xw.App(visible=False)
wb = xw.Book(r'C:/python373/ordersheet.xlsx')
ws=wb.sheets('00001')

client_id=ws['P3'].value
password=ws['P1'].value
username=ws['P4'].value


executable_path = {'executable_path': r'C:\python373\chromedriver'}
browser = Browser('chrome', **executable_path, headless = False)

#define the components of the url
method = 'GET'
url = 'https://auth.tdameritrade.com/auth?'
client_code = client_id + '@AMER.OAUTHAP'
payload = {'response_type':'code','redirect_uri':'http://localhost/test','client_id':client_code} #works
#payload = {'response_type':'code','redirect_uri':'https://127.0.0.1','client_id':client_code}

#build the url
built_url = requests.Request(method,url,params = payload).prepare()
built_url = built_url.url

#go to the url
browser.visit(built_url)

# define the elements to pass through to the form

payload = {'username':username,'password':password}
#fill out each element in the form
browser.find_by_id("username").first.fill(payload['username'])
browser.find_by_id("password").first.fill(payload['password'])
browser.find_by_id("accept").first.click()
time.sleep(2)
#click to accept terms and conditions
browser.find_by_id("accept").first.click()

time.sleep(2)
new_url = browser.url

#grab url and parse
parse_url = urllib.parse.unquote(new_url.split('code=')[1])
#close the browser
browser.quit()
#print(parse_url)

#define the endpoint
urlnew = r'https://api.tdameritrade.com/v1/oauth2/token'
headers = {'Content-Type':"application/x-www-form-urlencoded"}
#define the payloadnew
payloadnew={'grant_type':'authorization_code',
            'access_type':'offline',
            'code':parse_url,
            'client_id':client_id,
            'redirect_uri':'http://localhost/test'}
            #'redirect_uri':'https://127.0.0.1'}
authReply=requests.post(urlnew,headers=headers,data=payloadnew)
#convert json to string to dictionary
decoded_content = authReply.json()
access_token=decoded_content['access_token']
headers = {'Authorization': "Bearer {}".format(access_token)}
#print it out to the console, what the hell
#print(access_token)
#print it to a text file
f = open('tdaccesstoken.txt','w+')
f.write(access_token)
f.close()
#print it to a python file so it can be easily re-imported
import pprint
#pprint.pformat(access_token)
fileObj=open('tdaccesstoken.py','w')
print('Writing access token...')
fileObj.write("access_token=")
fileObj.write(pprint.pformat(access_token))
fileObj.close()
print('access token saved')








1 Like

OK obvisouly I’m a dummy and see that you do have an API. oops!

john

100% agree with Ameritrade. :100: :+1:

Hi, would be thrilled if you share your code Tony!
Thanks in advance,
FDG

it’s all above in the thread my good man!
Kindest Regards,
tony