Saturday 18 November 2017

Ausgewählter Wert Amibroker Forex


Ami broker Hier ist ein Artikel, der Ihnen alles, was Sie wissen müssen über die Verwendung von AmiBroker für den Handel FOREX Märkte erzählt. AmiBroker ist sehr flexibel in Bezug auf die Datenquellen, die verwendet werden können, um Daten zu dem Programm zu füttern. 1) Echtzeit-Daten Forex Trader benötigen in der Regel eine Echtzeit-Datenquelle und mit AB haben Sie eine Vielzahl von Entscheidungen. Der genaue Konfigurationsprozess hängt von der jeweiligen Quelle 8211 ab. Klicken Sie auf den entsprechenden Link, um zu erfahren, wie Sie die Quelle Ihrer Wahl konfigurieren können: 2) AmiQuote downloader Wenn Sie keine Echtzeit-Zitate benötigen, aber es genügt, dass Sie die historischen Daten haben (z Für Backtesting Ihre Strategien) 8211 dann können Sie auch AmiQuote Downloader-Programm (ein Begleiter-Programm, das mit AmiBroker installiert ist) und es ermöglicht es Ihnen, kostenlose Forex-Daten zu erhalten (sowohl EOD und Intraday: 1-, 3-, 5-, 15 -, 30-, 60- und 120-Minuten-Intervallen). AmiQuote kann die Angebote für folgende Währungspaare herunterladen: EURCHF, EURGBP, EURJPY, EURUSD, GBPUSD, USDCHF, USDJPY Sie müssen Folgendes tun: 8211 Datenbank in AmiBroker einrichten (File - gt Neue Datenbank, lokale Datenbank, Basiszeitintervall (Z. B. EOD) 8211 AmiQuote ausführen (START - gt Programme - gt AmiBroker - gt AmiQuote) 8211 Hinzufügen von Devisensymbolen in AQ: (Bearbeiten - gt Hinzufügen von Hinweisen) 8211 Auswählen von FOREX als Datenquelle 8211 Auswählen von Zeitbereich 8211 überprüfen 8220Automatisches Import8221 Feld 8211 auswählen : File - gt Start Download Die Intraday-Forex-Quotes sind nur in der registrierten Version von AmiQuote verfügbar. Obwohl der gesamte Datenbereich sehr lang ist, müssen Sie bedenken, dass im Falle von Intraday-Anführungszeichen der beste Weg ist, Daten in kleinen Teilen, wenige Wochen zu einer Zeit zu erhalten. Andernfalls kann die Anforderung zu groß sein, damit der Datenserver es verarbeiten kann, und dadurch wird die Anforderung abgelehnt. Die andere wichtige Sache zu erinnern ist, dass die Daten nicht verfügbar ist für Downloads zwischen 13:00 8211 22:00 GMT Zeit (7:00 8211 16:00 EST) 8211 in diesen Stunden der Data Vendor8217s Server nur lehnt alle Anfragen für Intraday Anführungsstriche. Sie können auch alle Daten, die in den Textdateien kommt. Der im AmiBroker verfügbare ASCII Importer ist sehr flexibel und akzeptiert praktisch jeden Standard von Daten. Zum Importieren von Angeboten 8211 ist die Verwendung von File - gt Import Wizard am bequemsten. Weitere Informationen zum Importieren der Daten aus ASCII-Dateien 8211 finden Sie in folgendem Tutorial: amibroker / guide / wimpwizard. html Nach dem Konfigurieren der Datenbank (zum Lesen von Echtzeitdaten) müssen Sie nur noch das Symbol hinzufügen Über: Symbol - gt Neues Menü und AmiBroker werden automatisch die Daten für das ausgewählte Symbol lesen. Beachten Sie bitte, dass verschiedene Datenquellen unterschiedliche Symbologien haben. Beachten Sie daher bitte immer die Symboldatei, um mehr über das erforderliche Symbolformat zu erfahren. Hier finden Sie die Links zu den beliebtesten Anbietern Guidlines: 8211 Interactive Brokers: amibroker / ib. html Im Falle von Interactive Brokers 8211, wenn Sie irgendwelche Zweifel, welches Format zu verwenden 8211 können Sie ganz einfach jedes Symbol in IB. Geben Sie einfach das Symbol in Interactive Brokers TWS ein, und ändern Sie die Ansicht in den Symbolmodus (Ansicht - gt Symbolmodus). Nun können Sie das aktuelle Symbol aus drei Feldern zusammensetzen: SYMBOL-EXCHANGE-TYPE Dabei gilt: SYMBOL ist identisch mit der Symbolspalte, wie sie in TWS angezeigt wird, während unter Symbolmodus EXCHANGE die Umschaltung d in TWS ist, während im Symbolmodus TYPE eine ist FIFF 8211, FUT 8211 Futures, FOP 8211 Optionen auf Futures, OPT 8211 Optionen, IND 8211 Indizes, CASH - cash (ideal FX) Da die meisten Währungspaare 4 Dezimalstellen benötigen, um die Kurse korrekt anzuzeigen, ist es notwendig, die Einstellungen vorzunehmen AmiBroker entsprechend. Die Anzahl der Nachkommastellen kann im Einstellungsdialog definiert werden: Werkzeuge - gt Voreinstellungen - gt Sonstiges Die Änderungen wirken sich auch auf Werkzeuge wie Fibonacci Extension oder Retracement Zeichenwerkzeuge aus. IV. SCANNING UND DATENERFAHRUNGEN Mit AmiBroker können Sie anspruchsvolle Scan - und Datenexplorationen (sowohl in Echtzeit als auch unter Verwendung von historischen Anführungszeichen) durchführen. Um die Datenanalyse durchzuführen und die Werte der ausgewählten Indikatoren in der angepassten Tabelle 8211 anzuzeigen, können wir das Fenster Automatische Analyse verwenden. Die detaillierte Beschreibung der Durchführung von Explorationen finden Sie unter: amibroker / guide / hexploration. html Als Kurzbeispiel 8211 finden wir die Frequenzweichen von MACD und deren Signalleitung und zusätzlich 8211 Anzeigewerte des zu testenden Symbols. Der 3. Parameter der AddColumn () - Funktion ermöglicht es, die Anzahl der Stellen nach dem Dezimalpunkt anzupassen, so dass es möglich ist, anzugeben, ob wir 2 oder 4 Dezimalstellen benötigen. Wenn wir: AddColumn (Close, 8220Close8221, 1.4) verwenden, dann werden 8211 4 Nachkommastellen angezeigt. Auf der anderen Seite 8211, wenn wir verwenden: AddColumn (Schließen, 8220Close8221, 1.2) dann AB zeigt nur 2 Dezimalstellen. Um den Test durchzuführen, müssen Sie folgende Schritte durchführen: 8211 Öffnen Sie den Formel-Editor (Analysis - gt Formula Editor) 8211 Geben Sie die Formel ein: 8211 Tools - gt Senden an Auto-Analyse 8211 Wählen Sie den Zeitbereich der Exploration 8211 drücken Sie EXPLORE Als Ergebnis 8211 erhalten wir eine Liste der MACD / Signal-Crossover-Punkte und den Wert des gewählten Symbols auf diesem Balken. Zuerst müssen Sie die symbolspezifische Information in die Symbol - gt Informationsseite (einzeln für jeden Ticker) eingeben. Im Falle von Währungen, die auf USD lauten (wie EURUSD), sollten folgende Einstellungen verwendet werden: 8211 runde Losgröße sollte gleich 1 8211 Tickgröße sollte auf Pipwert gleich 0,0001 für Währungen mit vier Dezimalstellen und 0,01 für Währungen mit gesetzt werden Zwei Dezimalstellen (also bei EURUSD it8217s 0.0001). 8211 Der Punktwert sollte auf den Dollarwert eines einzelnen Pip dividiert durch Pip gesetzt werden, so dass für EURUSD: 10 / 0.0001 100000 8211 Margin Einzahlung in den meisten Fällen sollte auf 1000 gesetzt werden (1 Marge von 1008217000) 1) Währungen auf denominiert In USD Let8217s analysieren die Ergebnisse durch eine einfache Formel (ein Crossover von 12- und 24-Tage-Moving Averages of Closing Preis, Trading 3 Verträge zu einem Zeitpunkt) generiert. Um einen Backtest 8211 auszuführen, benötigen Sie die folgenden Schritte: 8211 Öffnen Sie den Formel-Editor (Analysis - gt Formula Editor) 8211 Geben Sie die Formel ein: 8211 wählen Sie: Werkzeuge - gt Senden an Auto-Analyse Als Ergebnis 8211 wird das Fenster Automatische Analyse geöffnet . Im Einstellungsdialog (SETTNGS-Taste) ist es notwendig, den Futures-Modus einzuschalten (um die im Informationsdialog eingegebenen Informationen zu nutzen) und das Anfangs-Eigenkapital zu definieren. Dann 8211 drücken Sie OK. Im AA-Fenster-Hauptbildschirm ist es notwendig, den Zeitbereich des Backtests und die im Test enthaltenen Symbole zu definieren. Für unser Beispiel, das sein wird: Aktuelles Symbol, Alle Zitate Dann 8211, sobald alles konfiguriert ist 8211 die BACKTEST-Taste drücken. Nun let8217s haben einen Blick auf die Ergebnisliste. Der Gewinn wird wie folgt berechnet: NumContracts (SellPrice 8211 BuyPrice) PointValue In der ersten Transaktion: 8211 ist der Eintrittspreis 1.2154 8211 Der Exit Price entspricht 1.2304 8211 NumContracts 3 (da wir 3 Verträge handeln). 8211 wir handeln auf 1 Marge so Ablagerung ist 1.000 x 3.000 (das8217s ausgedrückt in Positionswert) So 8211 der Gewinn entspricht den Ergebnissen, die wir durch manuelle Berechnung erhalten. 2) Währungen, die auf eine andere Währung als USD lauten (vorausgesetzt, dass Ihr Konto in USD ist), können Sie eine Basiswährung und Wechselkurse (fest oder dynamisch) für verschiedene Währungen definieren und damit 8211, um korrekte Backtest-Ergebnisse zu erhalten Die auf unterschiedliche Währung lauten als Ihre Basisportfoliowährung. Diese Einstellungen können in: Tools - gt Preferences - gt Währungen Dialog definiert werden. AmiBroker erlaubt es, sowohl feste als auch dynamische (historische) Quotes für Backtesting-Zwecke zu verwenden (mit dynamischen Anführungszeichen können Sie den tatsächlichen Einfluss der Wechselkursänderungen für Ihre Trades, die auf unterschiedliche Währungen lauten, überprüfen). Es gibt folgende Voraussetzungen, um Währungseinstellungen anwenden zu können: a) Symbol-gtInformation, 8220 Währung 8221 Feld zeigt Währungen, die sich von BASE-Währung unterscheiden b) Angemessene Währung (definiert in Symbol-gt-Informationen) hat einen passenden Eintrag in der Präferenzen-gtCurrencies-Seite 8220FX SYMBOL8221 definiert in den Voreinstellungen EXISTS in Ihrer Datenbank und HAS QUOTES für jeden Tag unter Analysebereich. 8220INVERSE8221 Kontrollkästchen für die Vorgaben sollten beim Testen der FX-Kurse wie USDJPY oder USDCHF 8211, die nicht auf die Basiswährung des Portfolios lauten, überprüft werden. Aus dem gleichen Grund 8211, wenn wir das Beispiel von EURUSD 8211 betrachten, wenn 8220USD8221 Ihre BASE-Währung ist, dann wäre EUR-Wechselkurs 8220straight8221 EURUSD fx (zum Beispiel 1,25). Aber wenn 8220EUR8221 Ihre BASE-Währung ist, dann USD-Wechselkurs wäre INVERSE von EURUSD (dh Verwandte Artikel: 25. August 2011 WICHTIG: Verwenden Sie nicht die Indikator in einem echten Handelssystem schaut voraus in der Zeit und wird Sie verlieren Geld Ist nur für die Forschung zu zeigen: potenzielle Gewinne zeigen und zeigen Pfeile an sehr profitable Positionen, um die Formulierung besserer Handelsregeln zu erleichtern. Der Indikator ist hier sehr ähnlich dem ZigZag Indicator mit Ausnahme, dass die Wendepunkte für diesen Indikator sind, wo die gegenüberliegenden Bollinger Bands sind Zuletzt verletzt, bevor das nächste Signal. Die Formel ist als Handelssystem geschrieben. Es kann rückgängig gemacht werden, und die BB-Periode und Breite können optimiert werden. Da ist dies nur eine experimentelle Formel kein Versuch wurde gemacht, um den Code zu optimieren Herman um 8:43 pm unter Indikatoren Comments Off auf Bollinger Band ZigZag Indicator 6. Januar 2011 Die übliche Art und Weise zu reduzieren Indicator Verzögerung in Mittelung Formeln, wie die MA (), EMA und Tilson T3 (), ist zu versuchen und zu träumen Up eine völlig neue Formel. Das isn8217t einfach. Es ist oft einfacher, die Verzögerung von einem bereits geglätteten Plot zu entfernen, als die grundlegende Glättungsformel zu verbessern. Indikatorverzögerung ist häufig eine wesentliche Indikatorqualität und (imo) ist nicht dieselbe wie Indikatorverzögerung. Die ideale Glättungsfunktion ist eine mit Nullverzögerung, d. h. eine, die den Preis mit einer perfekt glatten Erscheinung verfolgt. Die Verzögerung kann später als unabhängige Qualität mit der ref () - Funktion hinzugefügt werden. Einige Glättungsformeln haben bereits eine Empfindlichkeitseinstellung, diese verhalten sich nicht notwendigerweise genauso wie der unten beschriebene LagReducing-Faktor. Die Optimierung aller Parameter für beste Ergebnisse wird empfohlen. Die hier vorgestellte Lag-Reducing-Formel kann auf die meisten Mittelungsformeln und auf Indikatoren angewendet werden, die auf Durchschnittswerten (wie Bands) basieren. Der Verzögerungsparameter (RLFactor) der Funktion Reducelag () kann auch verwendet werden, um Formeln anpassungsfähig in Bezug auf einen anderen Preis oder eine Indikatorqualität zu machen. Das untenstehende Bild zeigt, wie Verzögerung für die Tilson T3-Formel reduziert wurde. So sehen Sie, wie diese Formel funktioniert Übernehmen Sie die untenstehende Codeanzeige auf einen neuen Indikatorbereich, öffnen Sie das Parameterfenster und versuchen Sie es mit anderen Einstellungen. Abgelegt von Herman um 9:32 am unter Indikatoren Comments Off auf Reduzierung Indicator-Lag 21. Februar 2009 das Ziel ist es, Trades auf Diagramm, so dass es periodisch revieweed werden kann, um zu lernen, besser zu handeln. Das Ziel ist es, eine generische afl, die in das Symbol zu nehmen, Handel Termine und Preise und Handlung auf einem Diagramm zu produzieren. Unterstützen verschiedene Zeitrahmen, so dass das Plotten noch sichtbar ist. Täglich, wöchentlich, intraday, 5 Minuten / 15 Minuten Fähigkeit, Positionskalierung zu unterstützen, da es mehrere Handelseinträge / Exits geben kann, benötigt dieser die Eingabe im Ausdruck s der statischen Variablen wie folgt. So müssen Sie möglicherweise einen Adapter, der Ihre Trades nehmen und legen Sie es auf afl. // definiert, ob es sich um eine Aktie oder einen Forex handelt. StaticVarSetText (TradeType. Stocks) // StocksForex // definiert das Forex Symbol StaticVarSetText (forexSymbol. SBUX) //EUR. USD-IDEALPRO-CASH // definiert das Aktiensymbol StaticVarSetText (Stocksymbol, SBUX) // YHOO // lang oder kurz Handel. StaticVarSetText (ShortOrLong. Long) // ShortLong // Einstiegspreise StaticVarSetText (EntryPrice. 14.5,15.5) // Ausfahrt Preise StaticVarSetText (ExitPrice. 14.3) // Einstieg Datum Nummer Komma StaticVarSetText begrenzt (Entrydate. 1080717,1080723) // Exit-Datum in Datumsnummer. Komma getrennte StaticVarSetText (ExitDate, 1080725) // Eintrittszeit in Zeitnummer Komma StaticVarSetText (EntryTime, 142500,120000) begrenzt // Austrittszeit in Zeitnummer Komma StaticVarSetText begrenzt (Exittime. 110500) // Handel-ID. Es ist ein interner Schlüssel für mich StaticVarSetText (Tradeid. 4) // Handelsstrategie. StaticVarSetText (TradeStrategy. fsdfdsfds) // Kommentare zum Trade StaticVarSetText (TradeComments Dies ist der Kommentar) / legt die Anzahl der Einträge fest, so dass der Code beim Drucken der Anzahl der Trends verschoben wird. Wenn 1, dann sollte es nur 1 Eintrag Datum / Zeit, wenn es mehr, dass 1 Eintrag oder Exits, die Anzahl der Komma getrennte Einträge Exits sollte die statische Variable NoOfEntries und das gleiche gilt für Exits / StaticVarSet (NoOfEntries.2) das gleiche wie oben. StaticVarSet (NoOfExits 1) SetChartOptions (0, chartShowArrows chartShowDates) N (Titel StrFormat (8220 8211 Öffnen g, Hallo g, Lo g, Schließen g (.1f) 8221, O, H, L, C, SelectedValue (ROC (C , 1)))) Titel Titel 8220n8221 NumToStr (DATENUM ()) Titel Titel 8220n8221 NumToStr (TimeNum ()) Plot (C, 8220Close8221, ParamColor (8220Color8221, Farbeschwarz), styleNoTitle ParamStyle (8220Style8221) GetPriceStyle ()) // TRACE ( 8220ABTest: Test TRACE1 8220) // umfassen 8220C: Programm FilesAmiBrokersharedLibraryDateTimeToNumber. afl8221 / include 8220C: Programm FilesAmiBrokersharedLibraryDateTimeToNumber. afl8221 StaticVarSetText (8220TradeType8221, 8221Stocks8221) // StocksForex StaticVarSetText (8220forexSymbol8221, 8221AAPL8221) //8221EUR. USD-IDEALPRO-CASH StaticVarSetText (8220StockSymbol8221 , 8221AAPL8221) // 8220YHOO8221 StaticVarSetText (8220ShortOrLong8221, 8221Short8221) // 8221ShortLong8221 StaticVarSet (8220EntryPrice8221, 163,52000) StaticVarSet (8220ExitPrice8221, 148,18000) StaticVarSet (8220EntryDate8221, DateToNum (8220200807218221)) StaticVarSet (8220ExitDate8221, DateToNum (8220200807218221)) StaticVarSet (8220EntryTime8221, TimeToNum (822011: 01: 478221)) StaticVarSet (8220ExitTime8221, TimeToNum (822017: 52: 178221)) StaticVarSetText (8220TradeType8221) 8220Stocks8221) // StocksForex StaticVarSetText (8220forexSymbol8221. 8220SBUX8221) //8221EUR. USD-IDEALPRO-CASH StaticVarSetText (8220StockSymbol8221, 8220SBUX8221) // 8220YHOO8221 StaticVarSetText (8220ShortOrLong8221. 8220Long8221) // 8221ShortLong8221 StaticVarSetText (8220EntryPrice8221. 822014.5,15.58221) StaticVarSetText (8220ExitPrice8221. 822014,38221) StaticVarSetText (8220EntryDate8221. 82201080717,10807238221) StaticVarSetText (8220ExitDate8221, 822010807258221) StaticVarSetText (8220EntryTime8221, 8220142500,1200008221) StaticVarSetText (8220ExitTime8221. 82201105008221) StaticVarSetText (8220Tradeid8221. 822048221) StaticVarSetText (8220TradeStrategy8221. 8220fsdfdsfds8221) StaticVarSetText (8220TradeComments8221. 8220this ist die comment8221 ) StaticVarSet (8220NoOfEntries8221. 2) StaticVarSet (8220NoOfExits8221. 1) Funktion returnBarIndex (Array) indx -1 für (i 1 i lt BarCounti) Funktion returnShiftedArray (Array, Shift) für (i 1 i 0) ampamp ((Shift i) lt BarCount)) newArrayshifti Wahr newArrayi Falsch, wenn (strtoupper (Name ()) strtoupper (StaticVarGetText (8220forexSymbol8221)) OR (strtoupper (Name ()) strtoupper (StaticVarGetText (8220StockSymbol8221)))) // erhalten die statischen Variablen TradeType StaticVarGetText (8220TradeType8221) forexSymbol StaticVarGetText (8220forexSymbol8221) Stocksymbol StaticVarGetText (8220StockSymbol8221) ShortOrLong StaticVarGetText (8220ShortOrLong8221) if (TradeType 8220Stocks8221) stockname Stocksymbol SetOption (8220FuturesMode8221, false) sonst stockname forexSymbol SetOption (8220FuturesMode8221, True) für (i 0 i lt StaticVarGet (8220NoOfEntries8221) i) VarSet (8220EntryDate8221 (i), StrToNum (StrExtract (StaticVarGetText (8220EntryDate8221), (i)))) VarSet (8220EntryPrice8221 (i), StrToNum (StrExtract (StaticVarGetText (8220EntryPrice8221), (i)))) VarSet (8220EntryTime8221 (i), StrToNum (StrExtract (StaticVarGetText (8220EntryTime8221), (i)))) TRACE (8220ABTest: Test 182 8221 8220EntryDate8221 (i) NumToStr (VARGET (8220EntryDate8221 (i)))) TRACE (8220ABTest: Test 182 8221 8220EntryDate8221 (i) 8220string8221 StrExtract (StaticVarGetText (8220EntryDate8221), (i))) // geprüft, ob die Variablen existieren für (i 0 i lt StaticVarGet (8220NoOfEntries8221) i) TRACE (8220ABTest: Test 182 TESTING8221 8220EntryDate8221 (i) NumToStr (VARGET (8220EntryDate8221 (i)) )) TRACE (8220ABTest: Test 182 TESTS timeframe8221 inWeekly) for (j 0 j lt StaticVarGet (8220NoOfExits8221) j) VarSet (8220ExitDate8221 (j), StrToNum (StrExtract (StaticVarGetText (8220ExitDate8221), (j)))) VarSet (8220ExitTime8221 ( j), StrToNum (StrExtract (StaticVarGetText (8220ExitTime8221), (j)))) VarSet (8220ExitPrice8221 (j), StrToNum (StrExtract (StaticVarGetText (8220ExitPrice8221), (j)))) // TRACE (8220ABTest: Test 182 8221 8220ExitDate8221 (j) 8220string8221 StrExtract (StaticVarGetText (8220ExitDate8221), (j))) // Short-Abdeckung entryPrices exitPrices Falsch // kaufen Verkaufen, wenn das Symbol übereinstimmt, was ich für dn DATENUM Suche () entryPrices exitPrices Buy Short-Abdeckung Falsch Bereich H 8211 verkaufen L Schalter (Intervall ()) // START DES SCHALTERS. für (b 0b lt BarCountb) // START OF DAILY für (i 0 i dnb 8211 1) und (VARGET (8220EntryDate8221 i) lt dnb 1)) entryPricesb VARGET (8220EntryPrice8221 i) Buyb Shortb Wahr // TRACE (8220ABTest: Test 182 passender Preis 8221 NumToStr (VARGET (8220EntryPrice8221 i))) PlotText (StaticVarGetText (8220ShortOrLong8221) 8221 Eintrag 8221 i 8221 8221 8220:.. 8221 entryPricesb b, Highb rangeb, Farbeblau) // PlotText (8220entry8221 VARGET (8220EntryPrice8221 i) b, EntryPrice0 Farbeblau,) // TRACE (8220ABTest: Test 182 ABGESTIMMTER 8221 NumToStr (VARGET (8220EntryDate8221 i)) NumToStr (DNB)) for (j 0 j dnb 8211 1) und (VARGET (8220ExitDate8221 j) lt dnb 1)) exitPricesb VARGET ( 8220ExitPrice8221 j) Sellb Koverb Wahre PlotText (StaticVarGetText (8220ShortOrLong8221) 8221 Abfahrt 8221 j 8220: 8221 VARGET (8220ExitPrice8221 j) b, lowb 8211 rangeb, Blau und Rot) // TRACE (8220ABTest. Test 182 ABGESTIMMTER 8221 NumToStr (VARGET (8220ExitPrice8221 j) NumToStr) (DNB) NumToStr (VARGET (8220ExitDate8221 j))) für (b 1b lt BarCount 8211 1b) // START OF wöchentlich für (i 0 i 0) PreviousBarb-1 NextBarb wenn (b dnb) und (VARGET (8220EntryDate8221 i ) lt dnb1)) entryPricesb VARGET (8220EntryPrice8221 i) Buyb Shortb Wahr TRACE (8220ABTest: Test 182 passende Preiseingabe 8221 NumToStr (VARGET (8220EntryPrice8221 i))) PlotText (StaticVarGetText (8220ShortOrLong8221) 8221 entry8221 i 8221 8221 8220: 8221 entryPricesb. b, Highb rangeb, Farbeblau) // PlotText (8220entry8221 VARGET (8220EntryPrice8221 i) b, EntryPrice0, Farbeblau) // //. (8220ABTest: Test 182 ABGESTIMMTER 8221 NumToStr (VARGET (8220EntryDate8221 i)) NumToStr (DNB)) für ( j 0 j dnb-1) und (VARGET (8220EntryDate8221 i) dnb) und (VARGET (8220ExitDate8221 j) lt dnb1)) exitPricesb VARGET (8220ExitPrice8221 j) Sellb Koverb Wahre PlotText (StaticVarGetText (8220ShortOrLong8221) 8221 Exit8221 j 8220: 8221 VARGET ( 8220ExitPrice8221 j) b, lowb 8211 rangeb, Blau und Rot) // TRACE. (8220ABTest: Test 182 ABGESTIMMTER 8221 NumToStr (VARGET (8220ExitPrice8221 j)) NumToStr (DNB) NumToStr (VARGET (8220ExitDate8221 j))) // START OF wöchentlich // TRACE (8220ABTest: Test 182 8221 8221getting zu break8221) für (b 1b lt BarCount 8211 1b) // START OF intraday für (i 0 i TNB) und (VARGET (8220EntryTime8221 i) lt tnb1)) entryPricesb VARGET (8220EntryPrice8221 i) Buyb Shortb Wahr TRACE (8220ABTest: Test 182 passende Preiseingabe 8221 NumToStr (VARGET (8220EntryPrice8221 i))) PlotText (StaticVarGetText (8220ShortOrLong8221) 8221 entry8221 i 8221 8221 8220: 8221 entryPricesb. b, Highb rangeb, Farbeblau) // PlotText (8220entry8221 VARGET (8220EntryPrice8221 i) b, EntryPrice0, Farbeblau) // //. (8220ABTest: Test 182 ABGESTIMMTER 8221 NumToStr (VARGET (8220EntryDate8221 i)) NumToStr (DNB)) für ( j 0 j dnb-1) und (VARGET (8220EntryDate8221 i) TNB) und (VARGET (8220ExitTime8221 j) lt tnb1)) exitPricesb VARGET (8220ExitPrice8221 j) Sellb Koverb Wahre PlotText (StaticVarGetText (8220ShortOrLong8221) 8221 Exit8221 j 8220: 8221 VARGET ( 8220ExitPrice8221 j) b, lowb 8211 rangeb, Blau und Rot) // TRACE. (8220ABTest: Test 182 ABGESTIMMTER 8221 NumToStr (VARGET (8220ExitPrice8221 j)) NumToStr (DNB) NumToStr (VARGET (8220ExitDate8221 j))) // Ende der intraday // TRACE (8220ABTest: Test 182 8221 8221getting zu break8221) PlotShapes (IIf (Kauf oder kurz, shapeSmallCircle, shapeNone), colorBrightGreen, 0, EntryPrices, 0) PlotShapes (IIf (verkaufen oder Cover, shapeSmallCircle, shapeNone), Blau und Rot, 0. ExitPrices , 0) Miny-Status (8220axisminy8221) Maxy-Status (8220axismaxy8221) pxheight Status (8220pxheight8221) y (GetCursorYPosition () 8211 Miny) / (Maxy 8211 Miny) y (1 8211 y) pxheight GfxSelectPen (Blau und Rot, 1) // GfxRectangle (2 , Y-100, 270, y) GfxSelectFont (8220Tahoma8221, 8, 700) GfxTextOut (Name () 8221 Tradeid 8221 StaticVarGetText (8220Tradeid8221). x, y) GfxTextOut (8221 Strategie 8221 StaticVarGetText (8220TradeStrategy8221). x, y 10) GfxTextOut (8221 Kommentare 8221 StaticVarGetText (8220TradeComments8221). x, y 20) // // wenn das Symbol übereinstimmt, was ich für von Suresh Filed Suche Um 7:57 Uhr unter AmiBroker Tools und Funktionen, Uncategorized Comments Off auf Plotten Trades auf Diagramm 16. März 2008 Ab Version 4.67.0 bietet AmiBroker eine benutzerdefinierte Backtester-Schnittstelle zu ermöglichen, die Anpassung der Operation der backtester8217s zweite Phase, die die Handelssignale verarbeitet . Dies ermöglicht eine Reihe von speziellen Situationen erreicht werden, dass aren8217t nativ unterstützt durch die Backtester. AmiBroker neigt dazu, diese als die Advanced Portfolio Backtester-Schnittstelle zu verweisen, aber wie es scheint mehr als die Custom Backtester-Schnittstelle bezeichnet werden, werde ich diese letztere Terminologie verwenden. Aufgrund des von der Backtester-Schnittstelle verwendeten Objektmodells ist ein höheres Programmierwissen erforderlich als bei einfachem AFL oder Looping. Dieses Dokument beginnt mit der Diskussion dieses Modells, so zielt auf AFL-Programmierer, die bereits kompetent und komfortabel mit grundlegenden AFL-Nutzung, Array-Indexierung und Looping. Wenn Sie don8217t Verständnis Looping, dann haben Sie fast sicher, won8217t die benutzerdefinierte Backtester-Schnittstelle. Das moderne Programmierungsparadigma wird als objektorientierte Programmierung bezeichnet, wobei das System als ein Satz von Objekten entwickelt wird, die interagieren. Die benutzerdefinierte Backtester-Schnittstelle folgt diesem Modell. Ein Objekt kann als eine geschlossene Black-Box betrachtet werden, die bestimmte Eigenschaften besitzt und bestimmte Funktionen ausführen kann. Interne it8217s eine Kombination von Code und Variablen, wobei beide können entweder privat zu den Interna des Objekts nur oder zugänglich von außen für den Nutzen der Benutzer des Objekts. Der private Code und die Variablen sind völlig von der Außenwelt verborgen und für die Benutzer des Objekts nicht von Interesse. Nur Entwickler, die an dem Objekt selbst arbeiten, kümmern sich um sie. Benutzer des Objekts interessieren sich nur für den Code und die Variablen, die für ihre Verwendung zugänglich gemacht werden. Jede Variable, die einem object8217s-Benutzer zugänglich gemacht wird, wird als Eigenschaft des Objekts bezeichnet. Zum Beispiel hat das Backtester-Objekt eine Eigenschaft (Variable) mit der Bezeichnung 8220Equity8221, die der aktuelle Wert des Portfolio-Eigenkapitals während eines Backtests ist. Eigenschaften können gelesen und geschrieben werden viel die gleiche wie jede andere Variable, nur indem Sie sie in Ausdrücken und ihnen Werte zuweisen (obwohl einige Eigenschaften schreibgeschützt sein können). Allerdings ist die Syntax ein wenig anders aufgrund der Tatsache, dass sie Eigenschaften eines Objekts, nicht gewöhnliche Variablen. Ein object8217s-Code wird seinen Benutzern zugänglich gemacht, indem ein Satz von Funktionen bereitgestellt wird, die in Bezug auf das Objekt aufgerufen werden können. Diese Funktionen werden als Methoden des Objekts bezeichnet. Sie sind im wesentlichen identisch mit gewöhnlichen Funktionen, führen aber Operationen durch, die für den Zweck des Objekts relevant sind. Beispielsweise verfügt das Backtester-Objekt über Methoden (Funktionen), die Operationen im Zusammenhang mit Backtesting durchführen. Methoden werden in der gleichen Weise wie andere Funktionen aufgerufen, aber wieder ist die Syntax ein wenig anders, weil sie Methoden eines Objekts anstelle von gewöhnlichen Funktionen sind. Das Ziel des Objektmodells besteht darin, die Anwendung als einen Satz von in sich geschlossenen und wiederverwendbaren Objekten darzustellen, die ihre eigene Funktionalität verwalten und Schnittstellen für andere Objekte und den zu verwendenden Code bereitstellen können. Stellen Sie sich vor, es ist ähnlich wie bei einem Home-Entertainment-System, wo Sie kaufen eine Reihe von Komponenten (Objekte) wie ein Fernseher, DVD-Player, Surround-Sound-System und Karaoke-Einheit (wenn Sie auf diese Weise geneigt). Jede dieser Komponenten verwaltet ihre eigene Funktionalität und bietet Ihnen eine Reihe von Anschlüssen und Kabeln zu verbinden sie alle zusammen, um die endgültige Anwendung erstellen: das Home-Entertainment-System. Die Schönheit dieser Anordnung besteht darin, dass jede Komponente eine Standardschnittstelle bereitstellt (wenn Sie Glück haben), die es erlaubt, beliebige Marken der anderen Komponenten anzuschließen, ohne dass diese Komponenten die Details davon kennen müssen, wie alle anderen Komponenten intern und beträchtlich funktionieren Wahl in der Struktur der endgültigen Entertainment-System gebaut. Ebenso verfügen Softwareobjekte über Standardschnittstellen in Form von Methoden und Eigenschaften, die es erlauben, in jeder Software verwendet und wiederverwendet zu werden. Zugriff auf Objekteigenschaften und Methoden Um auf die Eigenschaften und Methoden eines Objekts zuzugreifen, müssen Sie nicht nur den Namen der Eigenschaft oder Methode kennen, sondern auch den Namen des Objekts. In AmiBroker AFL können Sie keine eigenen Objekte definieren oder erstellen, sondern nur von AmiBroker bereitgestellte Objekte verwenden. AmiBroker hilft Details all seine Objekte, Methoden und Eigenschaften im Abschnitt 8220Advanced Portfolio-Backtester interface8221. Um reale AFL-Beispiele zu verwenden, ist das erste in der Hilfe detaillierte Objekt das Backtester-Objekt. AmiBroker stellt ein Backtester-Objekt zur Durchführung von Backtests zur Verfügung. Um das Backtester-Objekt verwenden zu können, müssen Sie zunächst eine Kopie davon erhalten und diese Ihrer eigenen Variablen zuordnen: Die Variable 8220bo8221 ist Ihre eigene Variable, und Sie können diese beliebig innerhalb der Namensregeln von AFL aufrufen. Allerdings, um eine Menge von ausführlichen Aussagen zu vermeiden, it8217s gut, um es schön und kurz. Bisher haben you8217ve nur mit Variablen, die entweder einzelne Zahlen, Arrays von Zahlen oder Zeichenfolgen behandelt. Die Variable 8220bo8221 ist keine davon, sondern eine neue Variablenvariable namens Objektvariable. In diesem Fall hält es das Backtester-Objekt (oder eigentlich ein Verweis auf das Backtester-Objekt, aber ich möchte nicht in das komplizierte Thema der Referenzen hier bekommen). Nachdem Sie das Backtester-Objekt in Ihrer eigenen Variablen haben, können Sie auf seine Eigenschaften und Methoden zugreifen. Die Syntax für das Verweisen auf eine object8217s-Eigenschaft lautet objectName. objectProperty. Zum Beispiel bo. InitialEquity. Das kann dann das gleiche wie jede andere Variable (vorausgesetzt, es8217s nicht eine schreibgeschützte Eigenschaft, die InitialEquity ist nicht): Von diesem können Sie sehen, den Vorteil der Beibehaltung Objekt Variablennamen kurz. Wenn Sie die Variable 8220myBacktesterObject8221 aufgerufen haben, dann für das letzte Beispiel oben you8217d am Ende mit: Hier I8217ve musste die Schriftgröße zu reduzieren, nur um es alle auf einer einzigen Zeile passen. Wenn eine Eigenschaft schreibgeschützt ist, können Sie keine Operation ausführen, die ihren Wert ändern würde. Also, mit der Equity-Eigenschaft, die schreibgeschützt ist: Die gleiche Syntax wird verwendet, um auf die Methoden eines Objekts zuzugreifen. Dem Methodennamen steht der Objektname mit einem Dezimalpunkt vor: objectName. objectMethod (). Alle Parameter werden auf dieselbe Weise an die Methode übergeben wie normale Funktionen: Um zum Beispiel die Methode Backtester object8217s AddCustomMetric aufzurufen und die beiden obligatorischen Parameter Title und Value zu übergeben, würde eine Anweisung wie diese verwendet werden: AmiBroker help gibt an, dass diese Methode Liefert einen Wert vom Typ 8220bool8221, was boolean bedeutet und somit nur die Werte True und False annehmen kann. Jedoch, es doesn8217t Detail, was dieser Rückgabewert bedeutet. Eine gute Vermutung wäre, dass es True zurückgibt, wenn die benutzerdefinierte Metrik erfolgreich hinzugefügt wurde und False, wenn aus irgendeinem Grund es nicht hinzugefügt werden konnte. Allerdings that8217s nur eine Vermutung, sondern ein häufiger Grund für die Rückgabe von booleschen Werten. Für einige der anderen Methoden, die Werte vom Typ 8220long8221 zurückgeben, ist es schwieriger zu erraten, was sie enthalten könnten. Ein weiteres Beispiel mit einem Rückgabeparameter: Hier ist die Variable 8220sig8221 eine andere Objektvariable, aber diese Zeit vom Typ Signal anstatt Backtester. Mit anderen Worten, es enthält ein Signal-Objekt und kein Backtester-Objekt. Im Gegensatz zum Single Backtester-Objekt kann AmiBroker viele verschiedene Signalobjekte gleichzeitig erzeugen (eine für jedes Trading-Signal). Wenn ein Signalobjekt die Signaldaten für ein bestimmtes Symbol an einem bestimmten Balken hält, muss das Verfahren die Balkenanzahl kennen, die typischerweise unter Verwendung einer Schleifenindexvariablen (8216i8217 oben) innerhalb einer Schleife angegeben wird: Sobald ein Signalobjekt war Erhalten, können seine Eigenschaften und Methoden referenziert werden: Beachten Sie, dass die Eigenschaft sig. PosScore eine einzelne Zahl und kein Array ist. Während die AFL-Variable PositionScore ein Array ist, enthält das Objekt 8220sig8221 nur Daten für einen einzelnen Balken, so dass die Eigenschaft sig. PosScore nur der Positionswert für diese Balken ist, also eine einzelne Zahl. Beachten Sie auch, dass AmiBroker Hilfe ist nicht sehr klar, auf einige Themen. Beispielsweise enthält das Signal-Objekt nur wenige Methoden, die anzeigen, ob der aktuelle Balken ein Eingangs-, Ausgangs-, Lang - oder Kurzsignal enthält oder ein Skalenein - oder - ausgangssignal aufweist. Allerdings ist es doesn8217t angeben, wie Sie diese kombinieren, um die genauen Details zu erhalten. Zum Beispiel, wie Sie den Unterschied zwischen einer Skalierung und einer Skala-out Skaliert in eine lange Position eine Kombination von IsScale, IsEntry und IsLong, oder vielleicht nur IsScale und IsLong, oder keiner von denen In einigen Fällen Müssen Sie Trial and Error verwenden und sehen, was tatsächlich funktioniert (lernen Sie, wie Sie das DebugView-Programm mit TRACE-Anweisungen verwenden: siehe Anhang B). Glücklicherweise für dieses spezielle Beispiel hat das Signal-Objekt auch eine Eigenschaft namens Typ, die genau, welche Art das Signal zeigt. Verwenden der benutzerdefinierten Backtester-Schnittstelle Um Ihre eigene benutzerdefinierte Backtest-Prozedur zu verwenden, müssen Sie zuerst AmiBroker mitteilen, dass Sie dies tun werden. Es gibt mehrere Möglichkeiten, dies zu tun: Durch Setzen eines Pfades zu der Datei, die die Prozedur in der Portfolio-Seite Automatische Analyseeinstellungen enthält. Dieses Verfahren wird dann mit allen Backtests verwendet, wenn das Kontrollkästchen 8220Enable custom backtest procedure8221 aktiviert ist. Durch Angabe dieser beiden Einstellungen in Ihrem AFL-Code mit den Funktionen SetOption (8220UseCustomBacktestProc8221, True) und SetCustomBacktestProc (8220 8220). Note that path separators inside strings need to use two backslashes, for example 8220c:AmiBrokerFormulasCustomBacktestsMyProc. afl8221. Although why is not important here, it8217s because a single backslash is what8217s called an escape character, meaning the character(s) after it can have special meaning rather than just being printable characters, so to actually have a printable backslash, you have to put two in a row. By putting the procedure in the same file as the other AFL code and using the statement SetCustomBacktestProc(82208221). This tells AmiBroker that there is a custom backtest procedure but there8217s no path for it, because it8217s in the current file. This option will be used throughout the rest of this document. The next thing that8217s required in all backtest procedures is to ensure the procedure only runs during the second phase of the backtest. That8217s achieved with the following conditional statement: And finally, before anything else can be done, a copy of the Backtester object is needed: So all custom backtest procedures, where they8217re in the same file as the other AFL code, will have a template like this: If the backtests were using a procedure in the file: then the first line above in your system AFL code would be replaced with: and the rest of the procedure would be in the specified file. Or, if the same values were specified in the Automatic Analysis settings, the two lines above would not be needed in your AFL code at all, and the procedure would be in the specified file. Custom Backtester Levels The AmiBroker custom backtester interface provides three levels of user customisation, simply called high-level, mid-level, and low-level. The high-level approach requires the least programming knowledge, and the low-level approach the most. These levels are just a convenient way of grouping together methods that can and need to be called for a customisation to work, and conversely indicate which methods cannot be called in the same customisation because their functionality conflicts. Some methods can be called at all levels, others only at higher levels, and others only at lower levels. AmiBroker help details which levels each method can be used with. Naturally, the higher the level and the simpler the programming, the less flexibility that8217s available. This document will not detail every single method and property available, so the rest of this document should be read in conjunction with the AmiBroker help sections 8220Advanced portfolio backtester interface8221 and 8220Adding custom backtest metrics8221. The high-level interface doesn8217t allow any customising of the backtest procedure itself. It simply allows custom metrics to be defined for the backtester results display, and trade statistics and metrics to be calculated and examined. A single method call runs the whole backtest in one hit, the same as when the custom backtester interface isn8217t used at all. AmiBroker help has an example of using the high level interface to add a custom metric. See the section called 8220Adding custom backtest metrics8221. In essence, the steps are: Start with the custom backtest template above Run the backtest Get the performance statistics or trade details Calculate your new metric Add your new metric to the results display That would look something like this: As well as just using the built-in statistics and metrics, obtained from the Stats object after the backtest has been run, it8217s also possible to calculate your metric by examining all the trades using the Trade object. As some positions may still be open at the end of the backtest, you may need to iterate through both the closed trade and open position lists: In this example, 8220trade8221 is an object variable of type Trade, meaning it holds a Trade object. As with the Signal object, AmiBroker can have many Trade objects created at the same time, one for each closed or open trade. The first for loop iterates through the closed trade list, and the second through the open position trade list. The continuation condition 8220trade8221 theoretically means while the trade object is not zero, but in fact 8220trade8221 will be Null when the end of the list is reached. However, any conditional involving a null value is always false, so this will still work. The five Backtester object methods GetFirstTrade, GetNextTrade, GetFirstOpenPos, GetNextOpenPos, and FindOpenPos all return Null when the end of the list is reached or if no trade or open position is found. The for loops are a little different to normal for loops in that they don8217t have a standard loop index variable like 8216i8217 that gets incremented at the end of each pass. Instead they call a Backtester object method to get the initial value (the first Trade object) and then another member to get the next value (the next Trade object). So the for loop conditions here are just saying start from the first Trade object, at the end of each pass get the next Trade object, and keep doing that until there are no more Trade objects (ie. 8220trade8221 is Null). The loops are iterating through the list of trades, not the bars on a chart. Each Trade object holds the details for a single trade. Putting that code inside the custom backtest template looks like this: As an example, say we want to calculate the average number of calendar days that winning trades were held for (there8217s already a built-in Stats object value for number of bars, but we want number of calendar days). For that we8217ll need a function that can calculate the number of calendar days between two dates. Let8217s call it 8220DayCount8221, a function that takes two parameters: the entry date and the exit date, both in AmiBroker date/time format. Since this document is about the custom backtester interface, I don8217t want to go into how that function works right now. Let8217s just assume it does, but the code for such a function is given in Appendix A if you8217re interested. Then, for each trade we8217ll need to know: If it was a winning or losing trade The entry date The exit date And to calculate the average, we8217ll need a total figure for the number of winning trade days and another total figure for the number of trades. The average is the total number of days winning trades were held divided by the total number of winning trades. For the trade details, the Trade object has the following properties: EntryDateTime The entry date 038 time ExitDateTime The exit date 038 time and the following method: GetProfit() The profit for the trade Before trying this example, the first time we8217ve used this Trade object method, we make the assumption that the profit will be negative for losing trades and positive for winning trades, as AmiBroker help doesn8217t clarify that detail (it could be some undefined value for losing trades). If trial and error proves that not to be the case, then we could alternatively try using the Trade object properties EntryPrice, ExitPrice, and IsLong to determine if it was a winning or losing trade. As it turns out upon testing, GetProfit does in fact work as expected. Note that the Trade object also has a property called BarsInTrade, which looks like it could potentially be used instead of the dates, but that only gives the number of bars, not the number of calendar days. So, to get the number of calendar days spent in a trade, we call our DayCount function passing the entry and exit dates: DayCount(trade. EntryDateTime, trade. ExitDateTime) and to determine if it was a winning trade, where break-even doesn8217t count as winning: trade. GetProfit() 0 The whole procedure would then be: Note that we only need to consider closed trades in this example, as counting open positions would not accurately reflect the number of days trades were typically held for. Also, the 8220totalTrades8221 variable only counts winning trades, not all trades, since we8217re only averaging over winning trades. When a backtest is run with this custom interface and a report generated, our new metric 8220avgWinDays8221 will be printed at the bottom of the report: And if we run an optimisation (using a different backtest to above), it will have a column near the right-hand end of the results: Note that the reason the 8220W. Avg Bars Held8221 column doesn8217t seem to agree with the 8220AvgWinDays8221 column (ie. the former goes down while the latter goes up) is because the average bars figure includes open positions at the end of the backtest whereas we specifically excluded them. As well as overall metrics per backtest, it8217s also possible to include individual trade metrics in the backtester results. For this, the metric is added to each Trade object rather than the Backtester object and the trades are listed at the end of the procedure. For example, to display the entry position score value against each trade in the backtester results, the following code could be used: The first for loop iterates through the closed trade list and the second through the open position list to get the entry score value for every trade listed in the results. Note that the bo. BackTest call is passed the value 8220True8221 in this case to prevent the list of trades being generated automatically by the backtester. Instead, they8217re generated by the subsequent call to the bo. ListTrades method. As another example, say we want to list for each winning trade how far above or below the average winning profit it was as a percentage, and similarly for each losing trade, how far above or below the average loss it was as a percentage. For this we need the 8220WinnersAvgProfit8221 and 8220LosersAvgLoss8221 values from the Stats object, and the profit from the Trade objects for each closed trade (for this example we8217ll ignore open positions). Relative loss percentages are displayed as negative numbers. To be able to modify actual backtest behaviour, the mid-level or low-level interfaces must be used. New metrics can also be calculated at these levels, but since that8217s already covered above, this section will only look at what backtest behaviour can be modified at this level. Essentially this means using Signal objects as well as the Backtester object. With the mid-level interface, each trading signal at each bar can be examined and the properties of the signals changed, based on the value of other Signal or Backtester object properties, before any trades are executed for that bar. For example, one Backtester object property is 8220Equity8221, which gives the current portfolio equity, and one Signal object property is 8220PosSize8221, the position size specified in the main AFL code, so the mid-level interface can allow, for example, position size to be modified based on current portfolio equity. The custom backtester interface template for a mid-level approach, where all the signals at each bar need to be examined, is: In this example, the variable 8220sig8221 is an object variable of type Signal, meaning it holds a Signal object. As with the Trade object in the earlier example, the inner for loop iterates through the list of signals at each bar, not through all bars on a chart. The for loop conditions are effectively saying start from the first Signal object for the current bar, at the end of each pass get the next Signal object for the same bar, and keep doing that until there are no more Signal objects for the bar (ie. 8220sig8221 is Null). Each Signal object holds the details of one signal at the current bar (ie. a buy, sell, short, cover or scale indication for one symbol). The main differences between the mid-level and high-level approaches are: The Backtester object8217s Backtest method is not called. The Backtester object8217s ProcessTradeSignals method is called instead at each bar, after examining and possibly modifying some of the Signal object properties and/or closed or open Trade object properties. A loop is required to iterate through all bars of the chart. A nested loop is required inside that one to iterate through all the signals at each of those bars. If a trading decision needs to be based on some other property of a particular stock, like it8217s average daily trading volume for example, then the stock code symbol must be used to obtain that information. This is available in the Signal object8217s 8220Symbol8221 property. However, since the backtester at this level is not run in the context of a particular symbol, the data must be saved to a composite symbol in the main code (or perhaps a static variable) and referenced in the custom backtest procedure with the Foreign function. For example, in the main AFL code: Here the volume EMA array is saved to a separate composite symbol for each stock (ie. each composite consists of just a single stock). For this to work in backtests, the atcFlagEnableInBacktest flag must be used. Then in the custom backtest procedure: As a real example, to limit the number of shares purchased to a maximum of 10 of the 100 day EMA of the daily volume, and also ensure the position size is no less than 5,000 and no more than 50,000, the following mid-level procedure could be used: In this example, the statement psize (-psize/100) bo. Equity converts the percentage of equity value (which is negative) to its actual dollar value, using the Backtester object8217s Equity property. The term - psize/100 (which doesn8217t actually need to be inside brackets) converts the negative percentage to a positive fraction which is then multiplied by the current portfolio equity. The statement if (sig. IsEntry() 038038 sig. IsLong()) calls the two Signal object methods IsEntry and IsLong to determine if the current signal is an entry signal and a long signal (ie. a buy signal). Remember that the 038038 operator is equivalent to AND. An alternative would be to check if the Signal object8217s Type property was equal to one. The array variable 8220evol8221 contains the whole EMA array realigned to the number of bars used by the custom backtest procedure. Padded bars don8217t matter here as there won8217t be any signals for the stock at any of those bars, and we8217re only checking the volume on bars where there is a signal. As 8220evol8221 is an array, at each bar we8217re only interested in the value for the current bar, hence the references to evoli. Finally, as detailed in the AmiBroker help, the Signal object8217s Price property gives the price for the current signal, so there8217s no need to use BuyPrice, SellPrice, etc. and the PosSize property is the signal8217s position size value for the current bar. As this is not a read-only property, it can be both read and modified. Another example, to prevent scaling in a position that already has 50,000 or more in open position value: In this example, as each new scale-in signal is detected, the list of open positions is checked for an open position in the same stock as the new signal. If an open position exists, its current value is obtained, and if that value is 50,000 or more, the position size is set to zero to prevent the scale-in from happening. The example combines use of the Backtester object, Signal objects and Trade objects to determine whether or not scale-in of a position should be permitted. Note that the Trade object is returned Null if no open position is found. As any comparison with a null value is always false, provided the test is for the True condition then the IsNull function is not needed: ie. 8220if (trade)8221 gives the same result as 8220if (IsNull(trade))8221. However, if the test is for the negative condition, IsNull is required: ie. 8220if (trade)8221 won8217t work (when 8220trade8221 is Null it will be treated as False rather than the desired True) and 8220if (IsNull(trade))8221 becomes necessary. The low-level interface provides the most flexibility to control backtester operation. As well as allowing signal properties to be modified, it also allows the entering, exiting, and scaling of trades even if no signal exists. With the low-level interface, each trading signal at each bar can be examined, the properties of the signals changed, and trades entered, exited, and scaled. This could be used to implement special stop conditions not provided in the ApplyStop function, or to scale trades based on current portfolio equity or open position value and the like. The custom backtester interface template for a low-level approach is: Note that this template currently has no trades performed in it, as there are a number of options there depending on the system. Typically, inside the signal loop (or possibly the trades loop) there will be a number of tests for various conditions and then trades entered, exited, and scaled accordingly. The main differences between the low-level and mid-level approaches are: The Backtester object8217s ProcessTradeSignals method is not called. The Backtester object8217s EnterTrade, ExitTrade, and ScaleTrade methods are called instead at each bar, after examining and possibly modifying some of the signal properties and/or closed or open trade properties. The Backtester object8217s HandleStops method must be called once per bar to apply any stops programmed in the settings or by the ApplyStop function. The Backtester object8217s UpdateStats method must be called at least once for each bar to update values like equity, exposure, MAE/MFE, etc. The AmiBroker help is a little vague on how the TimeInsideBar parameter works (the values 821618217 038 821628217 in the sample above), but it must be called exactly once with that parameter set to two. It should also be called with it set to one to update the MAE/MFE statistics, but why it would be called with the value set to zero or more than once, I8217m not sure. As an example, let8217s create a custom backtest procedure that scales in a long position by 50 of its injected capital (ie. excluding profit) whenever its open position profit exceeds its total injected capital, which means it8217s sitting on 100 or more profit. The scale-in can be repeated whenever this condition occurs, as immediately after each scale-in, the injected capital will go up by 50. The system doesn8217t do any shorting and no other scaling occurs. The required conditions therefore are: The profit must be greater than the injected capital to scale in. The scale-in position size is equal to half the injected capital. No signal is required to perform the scale-in. The Signal object list is still needed to enter and exit all trades, as there8217s no other mechanism to do that, but just the Trade object list is needed for scaling open positions. At each bar, each open long position in the trade open position list must be tested for scaling in, and a scale-in performed if the conditions are met. The test for scale-in then looks like this: The scale-in position size is: And the scale-in method call, using the closing price for scaling, is: Putting it all into our template gives: Since we stated that the system doesn8217t do any shorting, the tests for sig. IsLong aren8217t really necessary. The signal for loop processes all entry and exit signals generated by our buy and sell conditions in the main AFL code. As mentioned above, this is necessary since we8217re not calling the ProcessTradeSignals method now, as that8217s a mid-level method. The trade open position for loop checks for and processes all scaling in. When an exit signal occurs, the whole position is closed. Extending this example now to include our custom avgWinDays metric from the high-level interface example: Note that stops are handled before scale-in checking occurs, as there8217s no point scaling in a trade if it8217s about to get stopped out on the same bar (although it would be unlikely to satisfy the scale-in condition anyway if it was about to get stopped out). Also note that the Trade object method GetEntryValue returns the total amount of injected capital, including all previous scale-in amounts. It8217s not possible to get just the amount used in the initial purchase. It would actually be nice here if the Trade object had a few user-defined properties, to allow the user to persist any values they wanted to throughout the life of a trade (although this could also be done with static variables). For example, as mentioned above, the initial purchase amount before any scaling could be remembered, or perhaps the number of times scaling has occurred (your system may want to limit scaling in to a maximum of say three times). Another similar example, but this time scaling out a position once it has doubled in value, removing the initial capital invested (approximately): In this example we only want to do the scale-out once, which introduces a new problem: how do we tell whether we8217ve already done it or not Trial and error shows that the entry value returned by the GetEntryValue method halves if you remove half of the value, so AmiBroker appears to treat a scale-out of half the value as being half profit and half original capital. As mentioned above, we really need a Trade object property here that we can write to with our own information. Since we8217re not using margin, we can use the MarginLoan property, which fortunately is not read-only. I tried to use the Score property first, but that turned out to be read-only, despite AmiBroker help not mentioning that fact. This example is mostly the same as the previous one, but instead of scaling in, we now scale out. Again, the trigger condition is the profit being greater than the entry value (injected capital), but we need to use a state variable to remember whether or not we8217ve already scaled out the position so that we only do it once. As mentioned above, we can8217t tell this from the entry value alone. While the MarginLoan property was available and writeable in this case, it would be much better, as already mentioned, if Trade objects had some user-definable properties. And once again as a reminder, since I use C and C syntax rather than the syntax defined in AmiBroker help. trade. MarginLoan is the same as NOT trade. MarginLoan and 038038 is equivalent to AND. The statement trade. MarginLoan just means if trade. MarginLoan equals zero. That pretty much covers the use of the custom backtester interface at all three levels. While there are a number of object properties and methods I haven8217t mentioned or used, this document is not intended to be a reference manual but rather an introduction to using the interface. There should be enough information here to allow you to figure out the rest for yourself with a bit of trial and error (as I8217ve had to use myself while writing this document). Computer programming in any language can be a rewarding, but at times extremely frustrating, experience. After many hours of trying to get your 8220simple8221 piece of code working properly, by which time you8217re ready to swear on your grandmother8217s grave that there has to be a problem with the language interpreter or compiler, almost invariably the problem is in your own code. It could be as simple as a missing semicolon, or as complex as a complete misunderstanding about how something is supposed to work. But as Eric Idle once said, always look on the bright side of life. The good thing about an extremely frustrating problem is that it feels SO good once you finally figure it out Appendix A 8211 DayCount Function The code for the DayCount function used to calculate the number of calendar days between two date/time values is below. This includes both entry and exit days in the count. It consists of two functions, the DayCount function itself, and a DayInYear function to calculate the current day number in a year for a particular date. Firstly, the DayInYear function: This gets called by the DayCount function for both the entry and exit days. Now the DayCount function: Appendix B 8211 Using DebugView This appendix discusses the use of the Microsoft SysInternals program DebugView for debugging AFL applications. DebugView can be obtained from the Microsoft website here: microsoft/technet/sysinternals/Miscellaneous/DebugView. mspx When you run the program, you will get a window like this: The display area is where your AFL application can write to using TRACE statements. Note though, as can be seen above, that your application may not be the only thing sending data to the viewer. DebugView captures all data sent to the viewer from all running applications. The main toolbar controls are: The Clear Display button is the one you8217ll likely use the most while debugging an application. And as with most applications, you can multi-select lines in the output display and use Edit-Copy (CtrlC) to copy them to the Clipboard for pasting into another application for further analysis. Using The AFL TRACE Statement To output messages to the viewer from your AFL code, including from custom backtest procedures, you use the TRACE statement: You can concatenate strings simply by 8220adding8221 them together: To include the value of parameters in the message, use the StrFormat function the same as for Plot statements: A sample trace while testing the first low-level example given in this document: That output was produced by the following code in the custom backtest procedure: Remember that as newlines are considered white space by the language, one statement can be spread over multiple lines for readability without affecting its operation. The only thing to be aware of is where a single string inside double quotes needs to span multiple lines. White space in a string is treated as exactly what it is, so if you put a line break in the middle of it, you will end up with a line break in your output (this is not true in all languages, but is with AFL as far as tracing goes). Instead, you can split it into two strings and concatenate them: In the end though, this is only for readability purposes. As far as the language goes, it doesn8217t matter if a single line is 1000 characters long and scrolls off the right-hand end of the screen. It just makes it more difficult to read the line when you8217re working on that part of the code. There8217s little else that can be said about using DebugView for debugging your AFL code. Debugging is something of an art, and knowing what sort of information to trace at which parts of the code is something you8217ll get better at the more you do it. Too little information and you can8217t tell what8217s happening. Too much and it can be like looking for the proverbial needle in a haystack. Appendix C 8211 Lichello AIM Algorithm The default parameters specified here are the AIM standard values, with 10K initial position, 10K cash, and 10 buy and sell safes. For vealies, the maximum cash balance for a stock defaults to 100K. To experiment with this algorithm in the manner it was intended, try it on individual stocks that have had significant swings but no overall trend. Strongly uptrending stocks will give the best results as the parameters approach buy and hold, with initial cash and buy safe of zero, and sell safe of 100. Note that the code uses trade. Sharestrade. GetPrice(i, 8220C8221) for the current value, not trade. GetPositionValue. That8217s because the latter function use8217s the previous bar8217s closing price to determine the current value, whereas we want the current bar8217s price (it8217s assumed that buy/sell tests are made after the close of trading). The actual prices then used are the next bar8217s prices, to mimic making the trade the next trading day. Trade delays are set to zero to avoid confusion and conflict. To run this code, copy everything in blue to an AFL file and then run it with the backtester. If you run it over a single stock, set the total cash value to be the sum of the initial position and initial cash values (the default setting), otherwise the backtest report won8217t give a realistic result for the percentage return (most of the cash would never have been invested so would have zero gain for that component unless an annual interest rate was set). If running it over a portfolio, set the total cash value to be some multiple of the two initial values to allow that many positions to be entered simultaneously. Running it over a large watchlist of stocks will only pick a few positions, depending on the total cash available, with new positions subsequently only being opened if others are stopped out (note that the maximum loss stop is not part of the AIM algorithm, it8217s my own addition). If the backtester results report the trade list, there will only be one entry for each position, no matter how many times it scaled in and out. However, if it got stopped out and the same stock subsequently purchased again, that would show as two trades in the list. To see all the scale in and out trades, run the backtest in Detailed Log mode. At the end of a backtest, the final quantity of shares, their value, the position control, and the cash balance figures are added to the Trade objects as custom metrics (one or two will be the same as existing metrics though). If the trade was closed, the quantity will be zero. The parameters include a percentage for Monte Carlo testing. This is the probability of ignoring any particular new buy signal. A value of zero means all buys will be taken, subject to cash availability, while a value of 100 means none will be. The value shouldn8217t be set too high otherwise the results might be unrealistic due to a sparsity of trades taken. I8217d suggest a value up to 50, with 25 being what I typically use myself. The less buy signals there are in the Buy array, the lower the value needs to be to avoid giving unrealistic results. To run a Monte Carlo test, set a percentage value and then run an optimisation. The random PositionScore array also helps with Monte Carlo testing. Finally a disclaimer: while I8217ve made every attempt to ensure this correctly implements the AIM algorithm as I have specified in the comments and accompanying text, I can8217t guarantee that there are no errors or omissions or that this does in fact implement the algorithm correctly. I have presented it here primarily as a more advanced example of a custom backtest procedure, and all use is at your own risk. However, if you do find any errors, please let me know. Filed by Herman at 11:52 am under Custom Backtester Comments Off on AmiBroker Custom Backtester Interface September 30, 2007 This indicator program was developed for the trader who wishes to plot opening gaps to aid his identification of where gaps occur in a price chart. The gaps are drawn as horizontal lines (green upper, red lower) extending a variable number of bars to the right of the gap. The code hasn8217t been optimized so that you can use the variables in subsequent code. While AFL has GapUp() and GapDown() functions the code below uses custom definitions to allow substitution of other criteria. Filed by Herman at 12:49 pm under Indicators Comments Off on Plotting Gap Prices Recent Posts Recent Comments Categories Copyright (C)2006 AmiBroker . This site uses WordPress Page generated in 0.617 seconds. August 25, 2011 IMPORTANT: Do not use the indicator in a real trading system it looks ahead in time and will make you lose money. It is meant for research only: to show potential profits and display arrows at highly profitable positions to facilitate formulating better trading rules. The indicator presented here is very similar to the ZigZag Indicator except that the turning points for this indicator are where the opposite Bollinger Bands are last breached before the next signal. The formula is written as a trading system. It can be Backtested, and the BB period and width can be optimized. Since this is just an experimental formula no attempt has been made to optimize the code. Filed by Herman at 8:43 pm under Indicators Comments Off on Bollinger Band ZigZag Indicator March 29, 2011 In real trading it is desirable to use a persistent trade record so that trades for multiple sessions be analyzed using the Backtester. The easiest way to do this is to save the trades in a composite. The code shown below is a simplified version of what will be used in the TDash system, however, it can be used with any trading system. This code requires you set Preferences - Intraday - 8220Time of first tick inside bar8221 or 8220START time of interval8221. Apply the code to an empty pane, start Bar-Replay, and open the Parameter window. After placing some trades you can send the code to the Backtester for analysis. You can perform the following actions: I use small solid triangles for Buy and Sell signals, and hollow triangles for Short and Cover signals. This allows me to overlay the Buy and Cover signals, and the Sell and Short signals, to display trade reversals. The triangles are placed at the actual trading price (the Close in this example). This is what the arrows look like: Filed by Herman at 7:26 pm under Developing a RT Trading Dashboard Comments Off on Logging and displaying trades March 7, 2011 This function was requested on the main list, and was solved with the help of several expert programmers from the list. Thanks guys This function can be copied to an include file that is included in each program from which you might want to synchronize the datetime range for all visible windows. The function places a small R button at the right top of your chart. Clicking this button will set the datetime ranges of all windows equal to the one you click the button in. Note that this window has to be active for the button to work, i. e. if the window was not active (selected) it will require two clicks for the button to respond. Filed by Herman at 7:17 am under AFL - Utilities and Functions Comments Off on Equalize X-Range for all windows March 6, 2008 This indicator formula allows you to select Candlestick patterns, mark their occurrence on the chart, display their frequency, and test their predictive value. Apply the code to an Indicator, open up the Param window, and drag the CandlePattern slider left and right to change to a different pattern. The selected pattern is identified in the chart Title text and graphically on your chart by a upwards pointing Blue arrow. The white line on your chart represents the resulting equity (profit plot in the Param window) for the pattern for the selected Profit Period. This line can be turned On or Off in the Param window. Entries (Buy or Short) are at the Close of the Pattern bar. Exits (Sell or Cover) are at the Open and can be delayed up to 10 bars with respect to the entry, as set in the Param window. This code was originally written many years ago and was revised to take advantage of newer AFL functions. Also, code has been added to allow you to Backtest and Optimize to find the best pattern, delay, and trading mode. Note that trading mode 822018221 in the optimizer report indicates Long trades, a 822008221 indicates Short trades. Red Arrows are either Sell or Short, Green Arrows are either Buy or Cover, depending on your Mode selection. The chart below shows how typical CandlePatterns are identified: Try different tickers they will all behave differently. Only basic stats are provided in the chart Title, please add your own price patterns and metrics. Edited by Al Venosa. Filed by Herman at 3:37 pm under Research and System Explorations Comments Off on Candle-Stick Evaluation (v2) February 18, 2008 When starting up AmiBroker the chart range defaults to the last number of bars set in Preferences. This means that in virtually all cases you have to manually zoom and restore the chart range you were previously working with. This post presents a function that will restore the last used range before you shut down AmiBroker. If you like to use this function routinely, you can copy the functions below to your default Include file and place this call at the top of your code: This function checks the contents of a static variable named 8220StartUp8221ChartIDStr. This static variable will return a NULL the first time it is called. When this happens, the ZoomToIndex() is called. This function retrieves the last used range for the current chartID from your hard disk and zooms to this range. The Plot() and Title statements are added to help you verify proper operation. You can also uncomment the two TRACE() commands and start up DebugView for further diagnostic purposes. If you do not have it yet, be sure to create a folder for the PersistentVariables, as shown at the top of the code. This is where the First and Last Indexes, which point to the start and end of the range being restored, are saved in a small file. You can open these with Notepad to help debugging operations. Edited by Al Venosa. Filed by Herman at 1:54 pm under AFL - Utilities and Functions Comments Off on Restore Last Used Range v2 November 14, 2007 Filed by brianz at 9:43 pm under AFL - The Basics Comments Off on Selected Date Range October 11, 2007 In real-time trading it is vital to keep your chart right justified, i. e. ensuring the right-most price bar is visible at all times. Failing to do so and looking at the wrong bar when trading real-money can invoke a panic response by the trader that results in erroneously closing a position or worse, placing a wrong order. This can easily happen if you are running several computers and are not always monitoring the chart being traded. The following code shows you how you can right-justify your chart at system startup or from the Param window. A visible alert that changes the chart back ground color when the last bar is not visible is included. The Alarm uses DateTime() to automatically correct for blank bars at the right edge of your chart. The code is kept explicit and you may be able to optimize it for speed. Edited by Al Venosa. Filed by Herman at 12:41 pm under Real-Time AFL Programming Comments Off on Keeping Your Chart Right-Justified August 30, 2007 July 22, 2007 The design of real-time automated trading systems involves two major design phases: 1) Designing the trading system and 2) Developing the trade-automation code. While you may be able to re-use some previously developed AT functions, you can rarely transport the entire automation section from one trading system to the next. Adjusting your AT code to work with a new system can be very time consuming it can involve weeks of real-time testing and debugging. Using the code below you can test your new system ideas, in a tick environment, before you have written a single line of automation code. Note that when testing this code with the Bar-Replay tool, the log will display the bar8217s closing price instead of the Lastprice (tick data). When testing this code with your own trading system, you may want to add extra output to the TRACE() statements. The code below substitutes DebugView output for orders that would have normally gone to the TWS: Filed by Herman at 7:17 pm under Debugging AFL Comments Off on Order Simulation using DebugView July 21, 2007 In real-time trading many situations arise when you want to delay action until a specific criterion is met. In AmiBroker you can base your delays in many different ways, the only requirement being that the delay variable increments or decrements. If the selected variable doesn8217t revert towards your timeout value (target), your delay function would never time out. In this case you would have to add code to handle that condition. A few variables you might use are: 8211 RT TimeNumber (Now(4)). 8211 Elapsed Seconds (redrawaction). 8211 Real-time Data time-stamp (TimeNum()). 8211 Tick-count (New Data). 8211 Volume (Change in Volume). 8211 Price change (Change in Price). 8211 Chart Refresh (any AFL Execution). 8211 Indicator values. Which of the above variables you would use for your delay depends on the requirements of your trading system. There may be times when you may need to combine several methods to get the required results. For example, if a delay were based on the data-timestamp, it might not time out during a data dropout or a no-trading period. In this case you need to back up your data-timestamp delay with a real-time (seconds) delay. Delays play a critical role in real-time system design. For example, in real-time systems, signals may have a short lifetime. The signal is strongest when it triggers and than quickly decays until, perhaps after a few bars, it has lost all significance. Letting the order fill at the time when it has lost significance is pure gambling. To prevent this, you can cancel the order after a delay, or decrease the position size proportional to the perceived decay in signal strength (perhaps based on elapsed bars) Since in a real-time system the time-lapse between AFL executions can be significant, you should place your LMT price calculations ahead of the ordering code. Calculating the LMT price after the order has been placed postpones order placement until the next AFL execution occurs, i. e. when the next quote arrives by then, the price has probably changed. Especially during periods of low volume, this could be significant. When these delays would be insignificant in EOD systems, they could make-or-break your system in fast-trading systems. To ensure frequent AFL execution in the absence of quotes, you can place a RequestTimedRefresh(1) statement at the top of your code, where the variable 821618217 refers to a 1-second refresh. This guarantees an AFL execution at least once per second. If your code is lengthy and takes a significant amount of time to execute, you may have to check order status at several places in your code. If changed status demands immediate action, you can force an immediate AFL execution by calling the following function:

No comments:

Post a Comment