Skip to content

OverpoweredCoding/traderPy-Port

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

7 Commits
 
 
 
 
 
 

Repository files navigation

Purpose

Port of my original traderJS module from 2 years ago to Python. Python is a more utilitarian language when it comes to automation of trading, so this module will allow for users to utilize this language with their Tradovate accounts.

Setup

  1. Create a Tradovate account and register an app
  2. Create accessToken.json (leave blank or if there's an error, setup as {"accessToken":""})
  3. Create a .env (fill it in with all your account details)
  4. Run the file calling the refresh access token function in order to obtain an access token. This is how you will authenticate sending orders and performing core account actions.
  5. Place orders and call the refres access token function in a loop in order to ensure that it never expires
  6. Get rich? I don't know - up to you.

Variable Information

If you do not understand any variable names defined in the trader.py file, please refer to Tradovate's official documentation. I have kept all of the variable names the same as the ones which they use on their website. https://api.tradovate.com/#section/Getting-Started-With-the-Tradovate-API

Code

import datetime
import requests
import json
import dotenv
import os

# Toggle between sending requests to the live or demo environment
# I would recommend using the demo environment to test your code before going live
# WARNING: DO NOT SWITCH TO MD - THIS WILL BREAK EVERYTHING
# MD IS MARKET DATA AND DOES NOT ALLOW FOR ORDER PLACEMENT OR ACCOUNT AUTHENTICATION

# version = "live"
version = "demo"

dotenv.load_dotenv()

# These are the environment variables that you need to set in your .env file

name = os.getenv('TRADOVATE_NAME')
password = os.getenv('TRADOVATE_PASSWORD')
app_id = os.getenv('TRADOVATE_APP_ID')
app_version = os.getenv('TRADOVATE_APP_VERSION')
cid = os.getenv('TRADOVATE_CID')
sec = os.getenv('TRADOVATE_SEC')
device_id = os.getenv('TRADOVATE_DEVICE_ID')

# This function will place an order for you

def place_order(symbol, order_action, quantity, account_spec, account_id):
    with open('./accessToken.json') as f:
        access_token = json.load(f)['accessToken']

    initial = {
        "accountSpec": account_spec,
        "accountId": account_id,
        "symbol": symbol,
        "action": order_action,
        "orderQty": quantity,
        "orderType": "Market",
        "isAutomated": True
    }

    headers = {
        "Content-Type": "application/json",
        "Authorization": f"Bearer {access_token}"
    }

    response = requests.post(f"https://{version}.tradovateapi.com/v1/order/placeorder", headers=headers, data=json.dumps(initial))

    print(f'Tradovate Status: {response.status_code}')
    print(response.text)

# This function will cancel an order for you

def cancel_order(account_id, contract_id):
    with open('./accessToken.json') as f:
        access_token = json.load(f)['accessToken']

    body = {
        "accountId": account_id,
        "contractId": contract_id,
        "admin": False
    }

    headers = {
        "Content-Type": "application/json",
        "Authorization": f"Bearer {access_token}"
    }

    response = requests.post(f'https://{version}.tradovateapi.com/v1/order/liquidateposition', headers=headers, data=json.dumps(body))

    print(f'Tradovate Status: {response.status_code}')
    print(response.text)

# This function will refresh your access token
# It is advisable to call this function in a loop to keep your access token fresh
# As of my present knowledge, the access token expires every hour

def refresh_access_token():
    print(f"Refreshing your access token... [{datetime.datetime.now()}]")

    # You must register an app on tradovate's website prior to these variables working properly

    body = {
        "name": f"{name}",
        "password": f"{password}",
        "appId": f"{app_id}",
        "appVersion": f"{app_version}",
        "cid": cid,
        "sec": f"{sec}",
        "deviceId": f"{device_id}"
    }

    response = requests.post(f'https://{version}.tradovateapi.com/v1/auth/accesstokenrequest', json=body)

    if response.status_code == 200:
        print(f"Access token successfully refreshed [{datetime.datetime.now().isoformat()}]")
        try:
            data = {"accessToken": response.json()['accessToken']}
        except Exception as e:

            # Most common exception is thrown because you forgot to register your app properly

            print(f"Error: {e}")
            print(f"Response: {response.text}")
            return
        with open("./accessToken.json", 'w') as f:
            json.dump(data, f)

Helper

In the event that you do not know your device ID and are hellbent on using python, it becomes difficult to get an actual unique identifier which works with Tradovate. The brokerage themselves recommends the npm library "device-uuid" in javascript, however, js and py are a massive headache to use in conjunction, in my opinion. This is why I have also created a program which replicates the uuid generated by the device-uuid npm library. In the event that this does not work for some reason, just use the npm library - this usually only works with windows and linux devices (sorry mac users).

python -m pip install screeninfo
import hashlib
import platform
import psutil
import uuid
import socket
import uuid
from datetime import datetime, time, timezone
from screeninfo import get_monitors
from PIL import Image

def get_time_zone_offset():
    utc_offset_sec = datetime.now(timezone.utc).astimezone().utcoffset().total_seconds()
    utc_offset_hours = int(utc_offset_sec / 3600)
    return str(utc_offset_hours)

def get_screen_resolution():
    monitors = get_monitors()
    if monitors:
        monitor = monitors[0]
        return f"{monitor.width}x{monitor.height}"
    return "Unknown"

def get_color_depth():
    img = Image.new('RGB', (1, 1))
    return img.mode

def format_uuid(uuid_str):
    return f"{uuid_str[:8]}-{uuid_str[8:12]}-{uuid_str[12:16]}-{uuid_str[16:20]}-{uuid_str[20:]}"

def get_device_uuid():
    user_agent = f"Python/{platform.python_version()}"
    os_info = platform.platform()
    cpu_info = str(psutil.cpu_count())
    mac_address = uuid.UUID(int=uuid.getnode()).hex[-12:]
    screen_resolution = get_screen_resolution()
    color_depth = get_color_depth()
    time_zone = get_time_zone_offset()
    hostname = socket.gethostname()

    combined_info = ":".join([
        user_agent,
        os_info,
        cpu_info,
        mac_address,
        screen_resolution,
        color_depth,
        time_zone,
        hostname
    ])

    hashed_uuid = hashlib.md5(combined_info.encode()).hexdigest()

    formatted_uuid = format_uuid(hashed_uuid)

    return formatted_uuid

device_uuid = get_device_uuid()
print(device_uuid)

About

traderJS > traderPY designed for interfacing with tradovate

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages