Hallo zusammen
Hier kommt wie versprochen die Anleitung, wie man sich myTWSStart für neue TWS Versionen selbst anpassen kann. Die Beschreibung basiert auf der vorläufig letzten Version von mvTWStart Public V.1.6.2, welche bei mir per Boardmail angefordert werden kann (Angabe der eMail Adresse nicht vergessen, sonst kann ich die .zip Datei nicht zustellen).
Mit dem hier vorgestellten Coding war myTWSStart auf meinem Papertrading-Account in der Lage, die TWS sowie RTT up-and-running zu halten - auch wenn der PC gelockt war. Hat man auf dem echten Account das Security Device aktiv, kann man myTWSStart wenigstens im interaktiven Modus verwenden (seit Version 1.6.1 vorhanden), so dass man wenigsten nur noch den Security-Code eingeben muss (für Remote Bedienung immerhin ganz nützlich).
Die genannte letzte Programm-Version 1.6.2 hatte ja eigentlich schon alles "an Bord", was man für eigene Anpassungen benötigt. Nehmen wir an, man hat sich die TWS-Version 882.2 neu installiert, dann geht man so vor:
A 1) Einmalig ist im Coding die Zeile 305 so anzupassen:
alt: if WinWaitActive("Login","", $waittime_sec) = 1 then
neu: if WinWaitActive("Login","", $waittime_sec) = 1 or ControlFocus( "Login", "", "") = 1 then
Grund: im Folgenden Coding werden wir nicht mehr die (bei AutoIT-) eingebaute Funktion Send() verwenden, um das Logon-Popup zu bedienen, sondern die ebenfalls eingebaute Funktion ControlSend(), welche auch bei gesperrtem Bildschirm funktioniert. Die "or" Verknüfung ist nötig, damit auch vorhandenes älteres Coding noch funktioniert.
A 2) Ausserdem ist das nun folgende Coding für die deutsche Login-Variante der TWS ausgelegt, man muss also im File jts.ini darauf achten, dass in der Sektion [Logon] diese Zeile steht:
Locale=de
Nun geht es so weiter:
B 1) In der Datei myTWSStart.ini ist diese Zeile hinzuzufügen oder eben auf die verwendete TWS Versions-Nummer einzustellen:
twsversion = 882.2
B 2) Nun kopieren wir VOR dem case else Block (Zeile 321) dieses Coding:
case 882.2
ControlSend("Login", "", "", $userid)
ControlSend("Login", "", "", "{TAB}")
; Passwort vor Gebrauch entschlüsseln ...
;MsgBox ( 48, "Debug: verschlüsseltes Passwort mit Level " & $decryptlevel, $passwd, $waittime_sec ) ; nur zu Debugging Zwecken aktivieren!
$passwd = _StringEncrypt ( 0, $passwd, $decryptphrase , $decryptlevel ) ; 0 to decryp
; MsgBox ( 48, "Debug: entschlüsseltes Passwort mit Level " & $decryptlevel, $passwd, $waittime_sec ) ; nur zu Debugging Zwecken aktivieren!
ControlSend("Login", "", "", $passwd)
Dim $passwd = 'Trash' ; Memory mit entschlüsseltes Passwort direkt nach Gebrauch wegwerfen
ControlSend("Login", "", "", "{TAB}{TAB}{TAB}{TAB}{TAB}{TAB}")
ControlSend("Login", "", "", "{SPACE}") ; Enter drücken
Die Logik dazu ist folgende:
* wenn das TWS Logon Popup gestartet wird, so steht der Cursor in einem bestimmten Feld.
* In dieses Feld Schreibt nun das erste gezeigte ControlSend() Statement hinein.
* Mit ControlSend("Login", "", "", "{TAB}") kann man ins jeweils nächste Feld springen
* mit ControlSend("Login", "", "", "{SPACE}") würde man einen Haken in einem Feld wie z.B. "SSL benützen" setzen wenn das Feld vorher leer war oder den Haken löschen wenn er gesetzt war: das ist also offensichtlich nicht nützlich für solche Anhak-Felder, denn man weiss ja nicht, wie das Feld vorher gesetzt war (warum das so ist, gleich später mehr, siehe PS 1)
* nützlich ist ControlSend("Login", "", "", "{SPACE}") also nur, wenn wir auf einem Button stehen, den man drücken kann: im vorgestellten Coding müssen wir also auf dem "Login" Botton stehen, um den eigentlichen Anmeldevorgang zu starten!
Welche Kombinationen von ControlSend() Statements man verwenden muss, ändert sich leider von TWS-Version zu TWS Version, weil die Kollegen bei IB ständig neue Felder einfügen oder die Reihenfolge ändern! Sogar die unterstützten TWS Sprachen zeigen unterschiedliche Login-Felder (desswegen oben der Punkt A 2).
Und so würde man myTWSStart an eine TWS Version >882.2 anpassen:
C 1) twsversion in der myTWSStart.ini anpassen wie unter B 1 beschrieben
C 2) den case-Block aus Beschreibung B 2 duplizieren und das case Statement auf die neue Versions-Nummer hochsetzen
C 3) die Abfolge der ControlSend() Statements anpassen; hilfreich ist dabei, das Login-Popup der TWS aufzurufen, dann
a) darauf achten wo der Cursor zu Anfang steht
b) mit der Tab-Taste Feld für Feld vorwärts gehen um zu sehen, wo der Cursor der Reihe nach auftacht. Genau gucken!, auch nur Anzeige Felder verraten den Corsor oft durch ein sanftes Blinken.
c) Gemäss dieser Abfolge ergibt sich die Reihenfolge der ControlSend()'s mit der Eingabe von User-ID, Passwort und den TABs und SPACEs; im Zweifel hilft: Experimentiere!
PS 1: Um ein GUI (Grafical User Interface) zu bedienen, gibt es sogenannte Frameworks. AutoIt 3 bedient vollumfänglich nur das Windows Control Framework. Leider verwendet die TWS aber Java und dort im speziellen ein Framework namens AWT. Dieses kann AutoIt 3 nur rudimentär ansprechen: insbesondere ist es nicht möglich, bestimmte Eingabefelder mit Namen zu adressieren um seinen momentanen Status oder Inhalt abzufragen. Nach meinen Tests sind leider nur diese ControlSend() Sachen möglich wie oben im Coding verwendet. Eventuell müsste man auf ein Java-Tool ausweichen, welches AutoIt gleich kommt (das gibt es durchaus), hat dann aber das Problem bei der Steuerung des RTT (welches ja nun ein Windows Progi ist). Also: man kann scheinbar nur wählen zwischen Pest oder Cholera!
PS 2: ganz nett wäre es, wenn jemand gemäss dieser Anleitung einen neuen funktionierenden Case Block für eine neue TWS Version erzeugt hat: bitte hier posten, das hilf dann allen!