Sydney NSW
Experience: Intermediate
Platform: TradeStation
Trading: Futures
Posts: 2 since Oct 2023
Thanks Given: 0
Thanks Received: 0
|
Hi everyone,I’m working on a script to automate my TradeStation chart setup end‑to‑end by reading in the multiwalk text strategy file and the setting up the following commands:[list=1]
New Workspace
New Chart (symbol, interval, session)
Walk‑forward strategy insertion
Chart settings (date range, time zone, bar‑build method, volume source)
Strategy settings (slippage, commission, MaxBarsBack, LIBB, pyramiding)
I’ve had partial success using the Chart Analysis command‑line (e.g. .NewWorkspace, .NewChart, .FirstDate, .LastDate, .BarBuildingMethod, .ForVolume, and .InsertStrategy "<name>"). However, I’ve hit a wall:
No .Slippage or .Commission commands in Chart Analysis
No .MaxBarsBack, .LIBB or .Pyramiding commands exposed via CLI
Strategy settings aren’t available until a strategy is on the chart
I’ve resorted to inserting a dummy strategy first and then using UI automation for the rest, but it’s… clunky
Has anyone:
Built a robust EasyLanguage/Chart Analysis macro or Python+AutoGUI script to fully automate chart+strategy setup?
Discovered undocumented command‑line actions or registry tweaks to expose strategy properties?
Created a more elegant UI‑automation sequence to open Format Strategy → Properties, set slippage, MaxBarsBack, etc., and then insert your walk‑forward strategy?
Any code snippets, PowerShell scripts, or TradeStation extensions you can share?
I’d really appreciate any pointers, examples, or shared tools that can help streamline this process. Thanks in advance for your insights!
Code so far....
import sys
import time
import re
import pyperclip
import pyautogui
import keyboard
import tkinter as tk
from tkinter import filedialog, messagebox
def select_el_file():
root = tk.Tk()
root.withdraw()
return filedialog.askopenfilename(
title="Select ELCode.txt",
filetypes=[("Text Files", "*.txt"), ("All Files", "*.*")]
)
def parse_el_file(path):
settings = {}
try:
with open(path, 'r') as f:
for line in f:
line = line.strip()
if not line.startswith('//'):
continue
content = line[2:].strip()
if ':' not in content:
continue
key, val = map(str.strip, content.split(':', 1))
settings[key] = val
except Exception as e:
messagebox.showerror("Error", f"Reading file failed:\n{e}")
sys.exit(1)
symbol_series = []
for i in range(1, 5):
key = f'Symbol/Interval/Session Data{i}'
if settings.get(key):
symbol_series.append(settings[key])
if not symbol_series:
messagebox.showerror("Error", "No symbol settings (Data1–Data4) found.")
sys.exit(1)
def convert_date(d):
if not d:
return ''
parts = d.split('-')
if len(parts) != 3:
messagebox.showerror("Error", f"Invalid date format: {d}")
sys.exit(1)
m, da, y = parts
return f"{m}/{da}/{y}"
return {
'symbol_series': symbol_series,
'begin': convert_date(settings.get('Begin Date (mm-dd-yyyy)', '')),
'end': convert_date(settings.get('End Date (mm-dd-yyyy)', '')),
'bar_method': settings.get('Bar Building Method', ''),
'volume_use': settings.get('For Volume, Use', ''),
'slippage': settings.get('Slippage', ''),
'commission': settings.get('Commission', ''),
'fill_assumption': settings.get('Limit Order Fill Assumption', ''),
'max_bars': settings.get('Maximum number of bars (MaxBarsBack)', ''),
'libb': settings.get('Look-Inside-Bar Backtesting (LIBB)', ''),
'pyramiding': settings.get('Multiple position/pyramiding enabled', ''),
'wf_name': settings.get('Walkforward Strategy Name', '')
}
def generate_commands(p):
"""
1) .NewWorkspace
2) .NewChart
3) Insert dummy strategy (must already exist in TS)
4) All your chart & strategy settings
5) Insert real strategy (quoted)
6) The rest (dates, time zone, bar method, volume)
"""
cmds = [
'.NewWorkspace',
'.NewChart',
# 3) Dummy strategy to unlock settings:
'.InsertStrategy "_DummyInitialise"'
]
# 4) Apply all your settings now that 'something' is on the chart:
if p['slippage']:
cmds.append(f'.Slippage {p["slippage"]}')
if p['commission']:
cmds.append(f'.Commission {p["commission"]}')
if p['fill_assumption']:
cmds.append(f'.LimitOrderFillAssumption {p["fill_assumption"]}')
if p['max_bars']:
cmds.append(f'.MaxBarsBack {p["max_bars"]}')
if p['libb']:
cmds.append(f'.LIBB {p["libb"]}')
if p['pyramiding']:
cmds.append(f'.Pyramiding {p["pyramiding"]}')
# 5) Now insert the real walk‑forward strategy, quoted to handle spaces/brackets:
if p['wf_name']:
cmds.append(f'.InsertStrategy "{p["wf_name"]}"')
# 6) Finally, symbol streams, sessions, and dates/ranges:
for s in p['symbol_series']:
m = re.match(r'([^()]+)\(([^)]+)\)', s)
if m:
sym_int = m.group(1).strip().replace('min', ' min')
sess = m.group(2).strip()
cmds += [sym_int, f'.Session {sess}']
else:
cmds.append(s)
if p['begin']:
cmds.append(f'.FirstDate {p["begin"]}')
if p['end']:
cmds.append(f'.LastDate {p["end"]}')
# And any remaining chart‑level commands:
if p['bar_method']:
cmds.append(f'.BarBuildingMethod {p["bar_method"]}')
if p['volume_use']:
cmds.append(f'.ForVolume {p["volume_use"]}')
return cmds
def send_commands_to_ts(commands):
messagebox.showinfo("Ready", "Switch to TradeStation now. Sending in 3 seconds... (Press ESC to abort)")
time.sleep(3)
for cmd in commands:
if keyboard.is_pressed('esc'):
messagebox.showwarning("Aborted", "ESC detected — aborting paste.")
return
pyperclip.copy(cmd)
pyautogui.hotkey('ctrl', 'v')
pyautogui.press('enter')
time.sleep(2)
for _ in range(20):
if keyboard.is_pressed('esc'):
messagebox.showwarning("Aborted", "ESC detected — aborting paste.")
return
time.sleep(0.1)
messagebox.showinfo("Done", "All commands sent successfully!")
def main():
path = select_el_file()
if not path:
return
parsed = parse_el_file(path)
cmds = generate_commands(parsed)
preview = "\n".join(cmds)
tk.Tk().withdraw()
messagebox.showinfo("Commands Preview", preview)
if not messagebox.askokcancel("Proceed", "Ready to send commands?"):
return
send_commands_to_ts(cmds)
if __name__ == "__main__":
main()
|