Mit dem alten Weißen JavaScript spielen - ein Kauf- und Verkaufspartner erstellen (7) nützliches Tool, das man wissen muss, warum es nützlich ist!

Schriftsteller:Kleine Träume, Erstellt: 2017-03-16 12:29:51, Aktualisiert: 2017-10-11 10:37:54

Ein nützliches Werkzeug muss wissen, warum es nützlich ist!

Es macht Spaß, während eines Wochentages Strategien zu schreiben, und verschiedene Ideen springen in den Editor, vielleicht ist das dein nächster Heiliger Becher, und ich bin aufgeregt darüber nachzudenken! Das einzige, was diese Leidenschaft beeinträchtigt, ist die Handhabung der Kauf- und Verkaufslogik, die für das Trading Strategy System wichtig ist, aber etwas langweilig und kompliziert ist.

  • Es ist gut, wenn man ein gut geschriebenes Modul hat, das man direkt benutzen kann (ich habe es in früheren Artikeln benutzt), aber um zu verstehen, wie es funktioniert und wie man es benutzt, habe ich den Code kommentiert:

- Ich weiß. Interval Versagen Wiederholungsintervall (millisekunden) Zahlenart (Nummer) 500 SlideTick Anzahl der Gleitpunkte (ganze Zahlen) Zahlenart (Nummer) 1 RiskControl Windsteuerung aktiviert MaxTrade@RiskControl Höchstzahl von Handelstätigkeiten pro Wochentag MaxTradeAmount@RiskControl Höchstzahl der Einzahlungen für eine Einzahl */

var __orderCount = 0 // Zeichnet die nächste Anzahl von Einheiten für den aktuellen Arbeitstag auf var __orderDay = 0 // Zeichnet das Datum des aktuellen Arbeitstages auf

function CanTrade ((tradeAmount) { // Risikokontrollmodul, Parameter: Anzahl der Transaktionen if (!RiskControl) { // Default: Windkontrollmodul nicht aktiviert, wenn nicht aktiviert, kann die CanTrade-Funktion true zurückgeben return true Das ist nicht wahr Wir sind hier. if (typeof(tradeAmount) == number && tradeAmount > MaxTradeAmount) { // Die Parameter tradeAmount als Zahlentyp eingeben, und die Anzahl der Einträge größer ist als die Anzahl der Einträge, die in den Vorlageparametern festgelegt sind. Log ((Wirbelsteuerungsmodul beschränkt, übersteigt die maximale Einheitsmenge, MaxTradeAmount, #ff0000 @); // Ausgabe von Tipps, Unterbrechung der Ausführung. Throw-Kuppen unterbrechen die Ausführung der Kuppe Die Antwort ist falsch. Wir sind hier. var nowDay = new Date (().getDate ((); // Erhält das aktuelle Datum if (nowDay!= __orderDay) { // getDate() Returns ein Tag im Monat (1 ~ 31) aus dem Date-Objekt. __orderDay = nowDay; // __orderDay Die globale Variable zeichnet das Auslöserdatum für den ersten Eintritt in das Windmodul auf. __orderCount = 0; // Aktualisierung der Variablen __orderDay, Wiederherstellung der Variablen __orderCount Wir sind hier. __orderCount++; // Globale Variable __orderCount Die nächste Einzahl, selbst addiert. if (__orderCount > MaxTrade) { // entscheidet, ob die Parameter für maximale Tageshandelzahlen festgelegt sind Log ((Wirbelsteuerungsmodul beschränkt, keine Transaktionen, überschreitet die maximale unmittelbare Anzahl von Tons, MaxTrade, #ff0000 @); // überschritten, Ausgabe von Tipps, Unterbrechung der Ausführung. Throw-Kuppen unterbrechen die Ausführung der Kuppe Die Antwort ist falsch. Wir sind hier. return true; // keine der oben genannten Bedingungen ausgelöst, return true, also kann man handeln. Wir sind hier.

function init ((() { // Vorlage-Initialisierungsfunktion, die beim Laden der Vorlage zuerst ausgeführt wird. if (typeof ((SlideTick) === undefined) { // prüft, ob SlideTick nicht definiert ist. SlideTick = 1; // Einstellung Default 1 } else { // Parse-String wird in Zahlen umgewandelt, allerdings kann ein Fehler auftreten, wenn eine String, die mit einem nicht digitalen Zeichen beginnt, NaN zurückgibt Das ist ein sehr schwieriges Thema. Wir sind hier. Log (die Kommoditätshandelskategorie erfolgreich geladen wurde); Wir sind hier.

function GetPosition ((e, contractType, direction, positions) { // kombiniert einen Vertrag mit der gleichen Position in der vergangenen Position, wobei die Parameter: Objekt der Börse, Art des Vertrages, Richtung, API zurückgegebene Positionsdaten (blank)
var allCost = 0; // ContractType Vertrag in Richtung Gesamtbetrag, ohne zu multiplizieren, wie viele Punkte ein Vertrag hat ((weil die Gesamtheit abgetragen werden kann) Var allAmount = 0; // Gesamtzahl der Vertragshändler var allProfit = 0; // Gewinn und Verlust zusammengefasst var allFrozen = 0; // Gesamtmenge der Gefrierungen var pos Margin = 0; // Haltekontrakte Hebel if (typeof(positions) === undefinedᅢ!positions) { // Wenn keine Parameter in die API übertragen werden, werden die zurückgegebenen Lagerinformationen zurückgegeben positions = _C ((e.GetPosition); // wird hier die API aufgerufen, um die Lagerinformationen zu erhalten. Wir sind hier. for (var i = 0; i < positions.length; i++) { // durchläuft die Array der gespeicherten Informationen. if (positions[i].ContractType == contractType && // Vertragskode für die Haltungsdaten des aktuellen Index == Parameter angegebenen Vertragskode ((contractType) und Richtung gleich der Richtung der Parameterübertragung ((direction) der aktuellen oder vergangenen Position (Positions[i].Type == PD_LONG in Position[i].Type == PD_LONG in Position[i].Type == PD_LONG in Position[i].Type == PD_LONG in Position[i].Type == PD_LONG in Position[i].Type == PD_LONG in Position[i].Type == PD_LONG in Position[i].Type == PD_LONG in Position[i].Type == PD_LONG in Position[i].Type == PD_LONG in Position[i].Type == PD_SHORT in Position[i].Type == PD_SHORT in Position[i].Type == PD_SHORT in Position[i].Type == PD_SHORT in Position[i].Type == PD_LONG in Position[i].Type == PD_LONG in Position[i].Type == PD_LONG in Position[i] && direction == PD_SHORT in Position[i] && direction == PD_SHORT in Position[i].Type == PD_SHORT in Position[i] ) { // Konforme Ausführung des if-Blocks PosMargin = positions[i].MarginLevel; // Erhalten von Hebelwerten allCost += (positions[i].Price * positions[i].Amount); // Gesamtkosten ((Die Anzahl der aufgenommenen Anteile, der aktuelle Index-Holdingpreis *Holdingvolumen) allAmount += positions[i].Amount; // Summe der Anzahl der Vertragshändler allProfit += positions[i].Profit; // Kontraktflüssiger Gewinn und Verlust allFrozen += positions[i].FrozenAmount; // Summe der Anzahl der gefrorenen Vertragshändler Wir sind hier. Wir sind hier. if (allAmount === 0) { // Wenn die Anzahl der qualifizierten Vertragshändler, die nach dem Durchsuchen erfolgt sind, 0 beträgt, kehrt null zurück, d.h. keine bedingte begrenzte Vertragshaltung zurück null; Wir sind hier. return { // allAmount ist nicht 0 und gibt eine Objekt-Behaltungsdaten nach dem Zusammenschluss zurück. Das ist ein großes Problem. FrozenAmount: allFrozen, das ist das erste Mal, dass ich auf Facebook gesprochen habe. Preis: _N (allCost / allAmount), Amount: allAmount, Profit: allProfit, Typ: Richtung Vertragstyp: Vertragstyp Ich bin nicht derjenige. Wir sind hier.

Funktion Open ((e, contractType, direction, opAmount) { // Funktion für die Operation von Einzelkontrakten Funktion, Parameter: Objekt der Börse, Vertragscode, Richtung, Anzahl der Operationen var initPosition = GetPosition ((e, contractType, direction); // Aufrufe der oberen GetPosition-Funktion, die nach dem Zusammenschluss die Lagerungsinformationen erhält. var isFirst = true; // Setzt den Marker isFirst (siehe unten) var initAmount = initPosition? initPosition.Amount : 0; // Wenn initPosition null ist, wird initAmount 0 zugewiesen, andernfalls wird initPosition.Amount zugewiesen var positionNow = initPosition; // erklärt, dass eine Variable positionNow die aktuelle Informationen enthält while (true) { // while Schleife var needOpen = opAmount; // Deklariert die temporäre Variable needOpen und gibt ihr einen Wert mit dem Parameter Quantität der Transaktionen if (isFirst) { // Wenn dies die erste Ausführung ist, wird nur der isFirst-Block aktualisiert. istFirst = false; } else { PositionNow = GetPosition ((e, contractType, direction); // aktualisiert positionNow, die aktuelle Lagerinformationen. if (positionNow) { // Wenn es eine Halteinformation gibt, ist die Anzahl der nächsten Positionen, die eröffnet werden müssen, needOpen gleich der Anzahl der Operationen, die durch die Parameter angefordert werden, abzüglich der Differenz zwischen der erhaltenen Halteinformation und der vorherigen (d. h. wie viele neue Hände geöffnet wurden) - die Position Now.Amount - initAmount; Wir sind hier. Wir sind hier. Var insDetail = _C ((e. SetContractType, contractType); // Kontrakttyp eingestellt. // Log (Log Initial, initAmount, Current, positionNow, Need to Build, needOpen); if (needOpen < insDetail.MinLimitOrderVolume) { // Wenn die nächste Anzahl von Positionen kleiner ist als die Mindestzahl der Positionen, die auf der Limitliste des Vertrags stehen Break; // Aus dem Kreislauf springen Wir sind hier. if (!CanTrade(opAmount)) { // Wind-Control-Modul Detektiert, wenn False zurückkehrt, springt aus der Runde ohne Handel. Ich bin nicht derjenige. Wir sind hier. Var depth = _C ((e.GetDepth); // Erhält Markttiefe Informationen. var amount = Math.min ((insDetail.MaxLimitOrderVolume, needOpen); // Beschränken Sie, dass die Anzahl der Aufträge nicht größer sein darf als die maximale Anzahl der Aufträge, die für den Vertrag festgesetzt wurden e.SetDirection ((direction == PD_LONG? buy: sell); // Einstellung der einzelnen Richtungen nach dem Parameter direction. - die Angabe der Angabe if (direction == PD_LONG) { // Aufrufe unterschiedlicher APIs für Transaktionen (mehr oder weniger) je nach Richtung der Parameter direction orderId = e.Buy ((depth.Asks[0].Price + (insDetail.PriceTick * SlideTick), Math.min ((amount, depth.Asks[0].Amount), contractType, Ask, depth.Asks[0]); // Die API-Dokumentation zeigt, dass ein Sprung des CTP-Warenstoff-Futures für insDetail.PriceTick ein ganzes Mal dieses Wertes sein muss. // Die tatsächliche Einheitenmenge der aufgerufenen APIs ist nicht größer als die Menge der Aufzeichnungen in einer Klasse } else { orderId = e.Sell ((depth.Bids[0].Price - (insDetail.PriceTick * SlideTick), Math.min ((amount, depth.Bids[0].Amount), contractType, Bid, depth.Bids[0]); Wir sind hier. // Verzichten Sie PendingOrders while (true) { // Nach dem Auftragen ein Interval, um noch nicht abgeschlossene Bestellungen zu stornieren. Schlaf (Intervall); Var orders = _C ((e.GetOrders); // holt alle noch nicht ausgeführten Bestellungen if (orders.length === 0) { // Wenn orders eine leere Array ist, springt der aktuelle while aus Ich bin nicht derjenige. Wir sind hier. for (var j = 0; j < orders.length; j++) { // Durchsucht eine nicht abgeschlossene Bestell-Array e.CancelOrder ((orders[j].Id); // die Bestellung nach der ID in der Bestellungsinformation des aktuellen Index stornieren。 if (j < (orders.length - 1)) { // über einen bestimmten Intervall, eine Seite zu hoch frequentiert. Sleep ((Interval); // Sleep Pause Interval Millisekunden Wir sind hier. Wir sind hier. Wir sind hier. } // Wenn die Hauptschleife während aussteigt var ret = { // erklärt ein Objekt, das zurückgegeben wird Preis: 0, // Durchschnittspreis Menge: 0, // Anzahl der Transaktionen position: positionNow // jüngst erhaltene Lagerinformationen dieser Sorte Ich bin nicht derjenige. if (!positionNow) { // Wenn keine Lagerungsinformationen vorhanden sind, kehrt direkt das initialierte Ret zurück Das ist nicht so einfach. Wir sind hier. if (!initPosition) { // Wenn keine Lagerinformationen dieser Art vorhanden sind, wenn die aktuelle Funktion ausgeführt wird. Ret.price = positionNow.Price; // Preis in der aktuellen PositionNow ist der durchschnittliche Preis, den die Transaktion erreicht hat Ret.amount = positionNow.Amount; // auch oben } else { // wenn zu Beginn bereits Informationen über die Spezies vorhanden waren. ret.amount = positionNow.Amount - initPosition.Amount; // Abweichung für die Anzahl der neuen Positionen ret.price = _N(((positionNow.Price * positionNow.Amount) - (initPosition.Price * initPosition.Amount)) / ret.amount); // Die Neuzunahme der Kosten für diesen Handel wird durch die Erhöhung der Neuzulassung ermittelt. Wir sind hier. return ret; // zurück Ret Wir sind hier.

Funktion Cover (e, contractType) { // Einartiges Flachgebiet, Parameter: Austauschobjekt, Vertragskode var insDetail = _C ((e.SetContractType, contractType); // Einstellung des Vertragstyps while (true) { // Hauptschleife while Var n = 0; // Berechnung von Standortvorgängen var opAmount = 0; // Erklärung Operation Variable var positions = _C ((e.GetPosition); // Aufrufe der API erhalten Lagerinformationen, um die oben genannten Funktionen zu unterscheiden; siehe API-Dokumentation für weitere Informationen. for (var i = 0; i < positions.length; i++) { // Durchsuchen if (positions[i].ContractType!= contractType) { // Wenn die Lagerinformationen für den aktuellen Index nicht gleich dem zu handhabenden Vertrag sind: contractType Weiter; // Überspringen Wir sind hier. var amount = Math.min ((insDetail.MaxLimitOrderVolume, positions[i].Amount); // Steuert maximale Transaktionsmenge, die nicht größer ist als die Aufforderung Das ist ein sehr schwieriger Fall. if (positions[i].Type == PD_LONG の の positions[i].Type == PD_LONG_YD) { // Verarbeitung von mehreren Positionen depth = _C(e.GetDepth); // Aufruf der API, um die aktuellen Datensätze zu erhalten opAmount = Math.min ((amount, depth.Bids[0].Amount); // Einschränkung if (!CanTrade ((opAmount)) { // Windsteuerungsmodul nachgewiesen zurück. Wir sind hier. e.SetDirection ((positions[i].Type == PD_LONG? closebuy_today button : closebuy button); // Einstellungen „Transaktionsrichtung“, siehe API-Dokumentation

            e.Sell(depth.Bids[0].Price - (insDetail.PriceTick * SlideTick), opAmount, contractType, positions[i].Type == PD_LONG ? "平今" : "平昨", 'Bid', depth.Bids[0]);
                                                                                           // 执行平仓 API ,详细参见 API文档。
            n++;                                                                           // 操作计数累加
        } else if (positions[i].Type == PD_SHORT || positions[i].Type == PD_SHORT_YD) {    // 处理 空仓 类似多仓处理
            depth = _C(e.GetDepth);
            opAmount = Math.min(amount, depth.Asks[0].Amount);
            if (!CanTrade(opAmount)) {
                return;
            }
            e.SetDirection(positions[i].Type == PD_SHORT ? "closesell_today" : "closesell");
            e.Buy(depth.Asks[0].Price + (insDetail.PriceTick * SlideTick), opAmount, contractType, positions[i].Type == PD_SHORT ? "平今" : "平昨", 'Ask', depth.Asks[0]);
            n++;
        }
    }
    if (n === 0) {                                                                         // 如果n 等于 0 ,即初始为0 ,在遍历时没有累加,没有可平的仓位。
        break;                                                                             // 跳出主while循环
    }
    while (true) {                                                                         // 间隔一定时间后, 取消所有挂单。类似Open函数的  CancelPendingOrders
        Sleep(Interval);
        var orders = _C(e.GetOrders);
        if (orders.length === 0) {
            break;
        }
        for (var j = 0; j < orders.length; j++) {
            e.CancelOrder(orders[j].Id);
            if (j < (orders.length - 1)) {
                Sleep(Interval);
            }
        }
    }
}

}

var trans = { // Verwendet für die Anzeige von Kontodetails in der Statusleiste, chinesische Übersetzung, Wörterbuch Der Account-ID-Tablett: Der Investor-Account-Tablett: In der Tat ist es nicht einfach, sich zu entscheiden, was man tun soll, wenn man sich in einer Situation befindet. Die Zentralbank der Schweiz (Zentralbank der Niederlande) hat die Zentralbank der Niederlande (Zentralbank der Niederlande) für die Berechnung von Zinsen und Gebühren eingerichtet. Der Code ist für Broker-IDs, die sich mit dem Code "Broker-ID-Code" befassen. Das Geld ist nicht mehr ausreichend, um die Probleme zu lösen. Die Schlüssel zu einem erfolgreichen Wachstum in der Wirtschaft sind: Das ist eine schlechte Nachricht, aber es ist eine gute Nachricht. Die Banken haben sich in den vergangenen Jahren in der Lage gemacht, ihre Kreditwürdigkeit zu verbessern. Der Curr-Margin-Margin: Die Summe der derzeitigen Sicherheiten ist hoch, und die Summe der derzeitigen Sicherheiten ist niedrig. Die Währungs-ID-Kette: Die Code-Kette für die Währung. Zitat: Zwei Zwei-Jahres-Jahres-Jahre sind für die Zentralbank von Zentralbank von Zentralbank von Zentralbank von Zentralbank von Zentralbank von Zentralbank. Einige von ihnen sind in der Lage, sich selbst zu helfen, wenn es um Geld geht. Die Zentralbank hat die Zentralbank für die Zentralbank für die Zentralbank für die Zentralbank für die Zentralbank für die Zentralbank für die Zentralbank für die Zentralbank für die Zentralbank für die Zentralbank für die Zentralbank für die Zentralbank für die Zentralbank für die Zentralbank für die Zentralbank für die Zentralbank für die Zentralbank für die Zentralbank für die Zentralbank. Zwei der wichtigsten Punkte, die von den chinesischen Investoren in den letzten zehn Jahren aufgegriffen wurden, waren die Investitionen in Gold. Der "FrozenCash"-Platz: Ein eingefrorener Geldkasten. Die FrozenCommission: Die Gefrierten Gebühren werden von den Bürgerinnen und Bürgern in den USA bezahlt. Die Frozen Margin-Platte: Eine Garantie für gefrorene Goldplatten. Die Bank hat eine Reihe von Aktien, die von den Banken in den Vereinigten Staaten und den Vereinigten Staaten in Anspruch genommen wurden. Die Banken haben die Möglichkeit, ihre Anleihen in einem anderen Land zu veräußern. Die Zinszahlungen werden von den Banken in den Ländern, in denen die Zinszahlungen erfolgt sind, aufgeteilt. Die Zinsspanne steigt, die Zinsspanne steigt, die Zinsspanne steigt. Die Zinsspanne der Zinsbasis ist sehr niedrig, und die Zinsspanne der Zinsspanne ist sehr hoch. Die Hypotheken-Hypotheken: Die Hypotheken-Hypotheken, die Hypotheken-Hypotheken, die Hypotheken-Hypotheken, die Hypotheken-Hypotheken. Der "Mortgageable Fund" ist ein Geldfonds, der Geldmengen als Pfand anbietet. Die Position-Profit-Taste: Die Position-Profit-Taste: Die Position-Profit-Taste: Die Position-Profit-Taste: Vorheriger ArtikelPre-Balance: Vorheriger Beitrag:Pre-Balance: Vorheriger Beitrag:Pre-Balance:Pre-Balance: Vorheriger Beitrag:Pre-Balance:Pre-Balance:Pre-Balance:Pre-Balance:Pre-Balance:Pre-Balance:Pre-Balance:Pre-Balance:Pre-Balance:Pre-Balance:Pre-Balance:Pre-Balance:Pre-Balance:Pre-Balance:Pre-Balance:Pre-Balance:Pre-Balance:Pre-Balance:Pre-Balance:Pre-Balance:Pre-Balance:Pre-Balance:Pre-Balance:Pre-Balance:Pre-Balance:Pre-Balance:Pre-Balance:Pre-Balance:Pre-Balance:Pre-Balance:Pre-Balance:Pre-Balance:Pre-Balance:Pre-Balance:Pre-Balance:Pre- Vor Kredit: Bei der letzten Kreditauszahlung war der Kredit sehr hoch. Das ist eine sehr schwierige Sache, aber es ist nicht einfach, es zu tun. Das ist ein sehr schwieriges Problem, aber es gibt viele Möglichkeiten, wie man das Problem lösen kann. Das ist ein sehr schwieriges Problem, aber es gibt viele Möglichkeiten, wie man es lösen kann. Vor-Margin-Zahlen: Zahlen, die zuletzt in der Garantie-Zahlen-Zahlen-Zahlen-Zahlen-Zahlen gehandhabt wurden, haben sich in den letzten Jahren verändert. Vor-Hypothek-Hypothek: Bei der letzten Hypothek-Hypothek, bei der ich mich aufhielt, habe ich eine Hypothek aufgegeben. Das ist ein sehr schwieriges Problem, aber es gibt viele Möglichkeiten, das Problem zu lösen. Reserve Balance-Reihe: Reserve-Reihe für die Abrechnung von Futures-Reihe, die für die Abrechnung von Futures-Reihe verwendet wird. Sie haben sich mit dem Problem beschäftigt, dass sie nicht mehr in der Lage sind, sich selbst zu identifizieren. SpecProductCloseProfit: Spezielle Produkte, die in Lager sind, machen einen Gewinn oder Verlust. Die SpecProductCommission (SPC) verlangt eine Gebühr für spezielle Produkte. SpecProductExchange Margin: Die SpecProduct-Exchange garantiert Gold, und die SpecProduct-Exchange-Margin wird von den Anbietern des Marktes garantiert. SpecProductFrozenCommission-Tappen: Spezielle Produkte, die für die Gefrierprozedur verwendet werden. SpecProductFrozenMargin-Polyester: Die Spezialprodukte werden mit Gold-Polyester eingefroren. SpecProduct Margin: Spezielle Produkte werden durch die Gewährleistung von SpecMargin genutzt. SpecProductPositionProfit-Profit: Spezielle Produkte, die im Lager sind, machen einen Gewinn oder Verlust. SpecProductPositionProfitByAlg-Profit: Spezielle Produkte, die nach dem Algorithmus für die Berechnung des Lagerverlustes berechnet werden. Der "Trading Day" ist ein Tag, an dem die meisten Menschen in der ganzen Welt ihre eigenen Geschäfte tätigen. Einer der größten Schwierigkeiten, die es gibt, ist, dass man sich nicht mit dem Geld beschäftigt, das man hat. Mit Hilfe der "WithdrawQuota"-Taste können Sie Geld abheben. Ich bin nicht derjenige.

function AccountToTable ((jsStr, title) { // Funktion, die die Kontoinformationen in eine Status-Tabelle exportiert, Parameter: JSON-String, Titel, zu zeigen if (typeof(title) === undefined) { // Wenn der Titel-Parameter nicht eingegeben wurde, wird initialiert: Kontoinformationen title = Übersicht über die Kontoinformationen; Wir sind hier. var tbl = { // Deklariert ein Formularobjekt, das für die LogStatus-Funktion verwendet wird und in der Statusleiste angezeigt wird type: table, // Typ angegeben als table title: title, // Parameter title Bewertet das Titelfeld von tbl cols: [Klangfeld, Beschreibung, Grenzwerte], // Tabelle, Spaltenheader rows: [] // Array-Felder, in denen die Daten pro Zeile der Tabelle gespeichert werden, beginnend mit einer leeren Array. Ich bin nicht derjenige. try { // Ermittlung von Ausfällen var fields = JSON.parse ((jsStr); // Parsiert die jsStr-String for (var k in fields) { // Eigenschaften des fields-Objekts durchsuchen, k ist der Eigenschaftswert, nicht verstanden. if (k == AccountID k == BrokerID ) { // Überspringen, wenn die Eigenschaften, die gerade durchsucht werden, beide Eigenschaften sind. Weiter Wir sind hier. var desc = trans[k]; // nach dem Eigenschaftsnamen des trans-Wörterbuchs zu der chinesischen Beschreibung desc gelangen var v = fields[k]; // Erhält den Wert des aktuellen Eigenschaftsnamens if (typeof(v) === number) { // Wenn der Eigenschaftswert numerischer Art ist, bleibt eine 5-Bit-Teilzahl erhalten. v = _N ((v, 5); Wir sind hier. tbl.rows.push (([k, typeof(desc) === undefined? : desc, v]); // Drückt die aktuellen Eigenschaften, Eigenschaftsbeschreibungen, Eigenschaftswerte und Kombinationen einer ein-dimensionalen Array in die rows-Attribute des Tabellenobjekts tbl. Wir sind hier. } catch (e) {} // Abweichungen erfasst, aber nicht behandelt return tbl; // Rückkehr des Objekts tbl Wir sind hier.

var PositionManager = (function() { // erklärt, dass eine Variable PositionManager den Wert einer anonymen Funktion akzeptiert, die den Wert eines konstruierten Objekts zurückgibt function PositionManager ((e) { // erklärt, dass eine Funktion PositionManager innerhalb einer anonymen Funktion ist. if (typeof(e) === undefined) { // Wenn kein Parameter e eingegeben wurde, wird standardmäßig die globale Variable exchange zu e zugewiesen e = exchange; Wir sind hier. if (e.GetName()!== Futures_CTP) { // Prüft, ob das Objekt der Hauptexchange e eine Kommoditäts-Futures-Exchange ist, oder ob es eine Ausnahme ist. throw Nur CTP unterstützt; // Nur CTP unterstützt Wir sind hier. this.e = e; // fügt der aktuellen Funktion (die eigentlich auch ein Objekt ist) eine Eigenschaft e hinzu und gibt ihr den Wert des Arguments e this.account = null; // Hinzufügen einer Account Variable, die anfänglich null ist Wir sind hier. - Erhalten Sie Cache PositionManager.prototype.Account = function (() { // Hinzufügen von Methoden zur oben genannten PositionManager-Funktion Account if (!this.account) { // Wenn die PositionManager-Attribute für das Account null ist this.account = _C ((this.e.GetAccount); // Die GetAccount-Funktion (also die Exchange-Object-API) des This.e-Börsenobjekts wird aufgerufen, um die Kontoinformationen zu erhalten. Wir sind hier. return this.account; // Diese Methode gibt die PositionManager.account-Kontoinformationen zurück. Ich bin nicht derjenige. PositionManager.prototype.GetAccount = function ((getTable) { // Hinzufügen von Methoden Diese Methode erhält aktuelle Kontoinformationen Dies ist ein Beispiel für die Art und Weise, wie Sie Ihre Daten in Ihrem Konto einfügen können. if (typeof ((getTable)!== undefined && getTable) { // Wenn man die Details der zuletzt abgerufenen Kontoinformationen in einem Objekt zurückgeben will, muss getTable true sein return AccountToTable ((this.e.GetRawJSON))) // Funktion GetRawJSON Siehe API-Dokumentation für weitere Informationen Wir sind hier. return this.account; // zurückgibt die Akteninformationen, die nach der Aktualisierung verwendet wurden. Ich bin nicht derjenige.

PositionManager.prototype.GetPosition = function(contractType, direction, positions) { // 给 PositionManager 添加方法 用于在主策略中调用该模板的 函数
    return GetPosition(this.e, contractType, direction, positions);
};

PositionManager.prototype.OpenLong = function(contractType, shares) {                  // 添加 开多仓 方法
    if (!this.account) {
        this.account = _C(this.e.GetAccount);
    }
    return Open(this.e, contractType, PD_LONG, shares);
};

PositionManager.prototype.OpenShort = function(contractType, shares) {                 // 添加 开空仓 方法
    if (!this.account) {
        this.account = _C(this.e.GetAccount);
    }
    return Open(this.e, contractType, PD_SHORT, shares);
};

PositionManager.prototype.Cover = function(contractType) {                             // 添加 平仓 方法
    if (!this.account) {
        this.account = _C(this.e.GetAccount);
    }
    return Cover(this.e, contractType);
};
PositionManager.prototype.CoverAll = function() {                                      // 添加 所有仓位全平方法
    if (!this.account) {
        this.account = _C(this.e.GetAccount);
    }
    while (true) {
        var positions = _C(this.e.GetPosition)
        if (positions.length == 0) {
            break
        }
        for (var i = 0; i < positions.length; i++) {                                   // 首先平掉 对冲合约 对冲合约 举例 MA709&MA705
            // Cover Hedge Position First
            if (positions[i].ContractType.indexOf('&') != -1) {
                Cover(this.e, positions[i].ContractType)
                Sleep(1000)
            }
        }
        for (var i = 0; i < positions.length; i++) {
            if (positions[i].ContractType.indexOf('&') == -1) {
                Cover(this.e, positions[i].ContractType)
                Sleep(1000)
            }
        }
    }
};
PositionManager.prototype.Profit = function(contractType) {                            // 添加计算收益的方法
    var accountNow = _C(this.e.GetAccount);
    return _N(accountNow.Balance - this.account.Balance);
};

return PositionManager;                                                                // 匿名函数返回 在自身内声明的 PositionManager 函数(对象)。

})();

$.NewPositionManager = function(e) { // Exportiert eine Funktion, die ein PositionManager-Objekt erstellt return new PositionManager ((e); Ich bin nicht derjenige.

// Über:http://mt.sohu.com/20160429/n446860150.shtml$.IsTrading = function ((symbol) { // Beurteilt, ob ein Vertrag in einem Handel ist. var now = new Date ((); // Erhält das aktuelle Zeitobjekt Var day = now.getDay ((); // Erhält die aktuelle Zeit für einen bestimmten Tag der Woche. Var hour = now.getHours ((); // Erhält die Stunde innerhalb der 24 Stunden

if (day === 0 || (day === 6 && (hour > 2 || hour == 2 && minute > 30))) {              // 第一个过滤, day == 0 星期天  或者  day == 6 星期六并且
    return false;                                                                      // 2点30以后 。 星期五 夜盘结束。  返回 false  即所有品种不在交易时间
}
symbol = symbol.replace('SPD ', '').replace('SP ', '');                                // 正则表达式 匹配其交易系统用“SPD”表示跨期套利交易,若指令买进“SPD CF1609&CF17...
                                                                                       // 过滤掉 跨期套利的 合约编码
var p, i, shortName = "";
for (i = 0; i < symbol.length; i++) {                                                  // 遍历合约代码字符串,取出 代码(排除数字的部分)赋值给shortName 并且转换为大写
    var ch = symbol.charCodeAt(i);
    if (ch >= 48 && ch <= 57) {
        break;
    }
    shortName += symbol[i].toUpperCase();
}

var period = [                                                                         // 通常交易时间  9:00 - 10:15,
    [9, 0, 10, 15],                                                                    //             10:30 - 11:30
    [10, 30, 11, 30],                                                                  //              13:30 - 15:00
    [13, 30, 15, 0]
];
if (shortName === "IH" || shortName === "IF" || shortName === "IC") {                  // 如果是这些 品种,交易时间 period 调整
    period = [
        [9, 30, 11, 30],
        [13, 0, 15, 0]
    ];
} else if (shortName === "TF" || shortName === "T") {                                  // 国债品种  时间调整
    period = [
        [9, 15, 11, 30],
        [13, 0, 15, 15]
    ];
}


if (day >= 1 && day <= 5) {                                                            // 如果是 周一 到周五, 不考虑夜盘。 判断当前时间是否符合 period 设定的时间表
    for (i = 0; i < period.length; i++) {
        p = period[i];
        if ((hour > p[0] || (hour == p[0] && minute >= p[1])) && (hour < p[2] || (hour == p[2] && minute < p[3]))) {
            return true;                                                               // 符合遍历出的  时间表 中的 时间段,  即该品种在交易时间内。
        }
    }
}

var nperiod = [                                                                        // 额外判断 夜盘品种  nperiod[n][0] 是夜盘时间相同的一类
                                                                                       // 品种汇总,nperiod[n][1] 就是该类品种的夜盘交易时间
    [
        ['AU', 'AG'],
        [21, 0, 02, 30]
    ],
    [
        ['CU', 'AL', 'ZN', 'PB', 'SN', 'NI'],
        [21, 0, 01, 0]
    ],
    [
        ['RU', 'RB', 'HC', 'BU'],
        [21, 0, 23, 0]
    ],
    [
        ['P', 'J', 'M', 'Y', 'A', 'B', 'JM', 'I'],
        [21, 0, 23, 30]
    ],
    [
        ['SR', 'CF', 'RM', 'MA', 'TA', 'ZC', 'FG', 'IO'],
        [21, 0, 23, 30]
    ],
];
for (i = 0; i < nperiod.length; i++) {                                                // 遍历所有夜盘品种 交易时间段,对比当前时间。
    for (var j = 0; j < nperiod[i][0].length; j++) {
        if (nperiod[i][0][j] === shortName) {
            p = nperiod[i][1];
            var condA = hour > p[0] || (hour == p[0] && minute >= p[1]);
            var condB = hour < p[2] || (hour == p[2] && minute < p[3]);
            // in one day
            if (p[2] >= p[0]) {
                if ((day >= 1 && day <= 5) && condA && condB) {
                    return true;
                }
            } else {
                if (((day >= 1 && day <= 5) && condA) || ((day >= 2 && day <= 6) && condB)) {
                    return true;
                }
            }
            return false;
        }
    }
}
return false;

};

$.NewTaskQueue = function ((onTaskFinish) { // Funktion zur Erstellung von Warteschlangenobjekten für verschiedene Transaktionen. Parameter: Funktion, die zurückruft, wenn die Aufgabe abgeschlossen ist. var self = {} // erklärt einen leeren Objekt self.ERR_SUCCESS = 0 // Definition der Rücksendung erfolgreich self.ERR_SET_SYMBOL = 1 // Fehler beim Festlegen des Vertrags self.ERR_GET_RECORDS = 2 // Fehler beim Erhalten von K-Linien self.ERR_GET_ORDERS = 3 // Fehler beim Erhalt einer nicht abgeschlossenen Bestellung self.ERR_GET_POS = 4 // Fehler beim Erhalt der Lagerinformationen self.ERR_TRADE = 5 // Transaktionsfehler self.ERR_GET_DEPTH = 6 // Fehler bei der Gewinnung der Tiefe self.ERR_NOT_TRADING = 7 // nicht zum Zeitpunkt des Handels self.ERR_BUSY = 8 // Blockiert

self.onTaskFinish = typeof(onTaskFinish) === 'undefined' ? null : onTaskFinish  // 如果在 初始化队列对象时没有 传入需要回调的匿名函数,该属性赋值为null,否则赋值回调函数
self.retryInterval = 300                                                        // 重试间隔 毫秒数
self.tasks = []                                                                 // 这个是一个重要的属性,队列中储存任务的数组。
self.pushTask = function(e, symbol, action, amount, arg, onFinish) {            // 给空对象添加函数,该函数是压入 新任务 到任务数组中。参数分别为:
                                                                                // 交易所对象、合约代码、执行动作、数量、回调函数参数、回调函数
    var task = {                                                                // 构造一个任务对象
        e: e,                                                                   // 交易所对象
        action: action,                                                         // 执行的动作
        symbol: symbol,                                                         // 合约代码
        amount: amount,                                                         // 操作数量
        init: false,                                                            // 是否初始化
        finished: false,                                                        // 是否任务完成
        dealAmount: 0,                                                          // 已处理的 量
        preAmount: 0,                                                           // 上一次的 量
        preCost: 0,                                                             // 上一次的 花费
        retry: 0,                                                               // 重试次数
        maxRetry: 10,                                                           // 最大重试次数
        arg: typeof(onFinish) !== 'undefined' ? arg : undefined,                // 如果没有传入 回调函数,此项 设置为 undefined
        onFinish: typeof(onFinish) == 'undefined' ? arg : onFinish              // 如果没有传入回调函数,把 arg 复制给 onFinish(实际上是 arg没传入,中间隔过去了)
    }
    
    switch (task.action) {                                                      // 根据执行的动作初始化描述信息
        case "buy":
            task.desc = task.symbol + " 开多仓, 数量 " + task.amount
            break
        case "sell":
            task.desc = task.symbol + " 开空仓, 数量 " + task.amount
            break
        case "closebuy":
            task.desc = task.symbol + " 平多仓, 数量 " + task.amount
            break
        case "closesell":
            task.desc = task.symbol + " 平空仓, 数量 " + task.amount
            break
        default:
            task.desc = task.symbol + " " + task.action + ", 数量 " + task.amount
    }

    self.tasks.push(task)                                                       // 压入任务数组中
    Log("接收到任务", task.desc)                                                  // 输出日志 显示 接收到任务。
}

self.cancelAll = function(e) {                                                  // 添加函数,取消所有,参数: 交易所对象
    while (true) {                                                              // 遍历未完成的所有订单,逐个取消。
        var orders = e.GetOrders();
        if (!orders) {                                                          // 所有API 调用都不重试,如果API调用失败,立即返回。
            return self.ERR_GET_ORDERS;
        }
        if (orders.length == 0) {
            break;
        }
        for (var i = 0; i < orders.length; i++) {
            e.CancelOrder(orders[i].Id);
            Sleep(self.retryInterval);
        }
    }
    return self.ERR_SUCCESS                                                      // 返回 完成标记
}

self.pollTask = function(task) {                                                 // 执行数组中弹出的任务
    var insDetail = task.e.SetContractType(task.symbol);                         // 切换到当前 任务 task 对象保存的合约类型
    if (!insDetail) {                                                            // 切换失败 立即返回
        return self.ERR_SET_SYMBOL;
    }
    var ret = null;
    var isCover = task.action != "buy" && task.action != "sell";                 // 根据执行的动作,设置 是否是平仓的 标记
    do {                                                                         // do while 循环,先执行 do 以内
        if (!$.IsTrading(task.symbol)) {                                         // 判断是否在交易时间
            return self.ERR_NOT_TRADING;                                         // 不在交易时间立即返回
        }
        if (self.cancelAll(task.e) != self.ERR_SUCCESS) {                        // 调用全部取消函数 ,如果不等于 完成状态
            return self.ERR_TRADE;                                               // 返回交易失败
        }
        if (!CanTrade(task.amount)) {                                            // 风控模块检测。
            ret = null
            break
        }
        var positions = task.e.GetPosition();                                    // 获取持仓信息
        // Error
        if (!positions) {
            return self.ERR_GET_POS;                                             // 如果调用获取持仓 API 错误,立即返回
        }
        // search position
        var pos = null;
        for (var i = 0; i < positions.length; i++) {                             // 遍历持仓信息,查找持仓合并持仓,类似 上面的 GetPosition 函数
            if (positions[i].ContractType == task.symbol && (((positions[i].Type == PD_LONG || positions[i].Type == PD_LONG_YD) && (task.action == "buy" || task.action == "closebuy")) || ((positions[i].Type == PD_SHORT || positions[i].Type == PD_SHORT_YD) && (task.action == "sell" || task.action == "closesell")))) {
                if (!pos) {
                    pos = positions[i];
                    pos.Cost = positions[i].Price * positions[i].Amount;
                } else {
                    pos.Amount += positions[i].Amount;
                    pos.Profit += positions[i].Profit;
                    pos.Cost += positions[i].Price * positions[i].Amount;
                }
            }
        }
        // record pre position
        if (!task.init) {                                                        // 如果任务没有初始化,执行以下
            task.init = true;                                                    // 更新为已初始化
            if (pos) {                                                           // 如果查找到之前的持仓,把之前的持仓数量、 花费 复制给task 的相应变量保存
                task.preAmount = pos.Amount;
                task.preCost = pos.Cost;
            } else {                                                             // 如果执行这个任务 时没有 ,同样的方向  同样合约的持仓,把task相关变量赋值0
                task.preAmount = 0;
                task.preCost = 0;
                if (isCover) {                                                   // 如果是 平仓动作,输出日志 : 找不到仓位,跳出循环。
                    Log("找不到仓位", task.symbol, task.action);
                    ret = null;
                    break;
                }
            }
        }
        var remain = task.amount;                                                // 声明一个局部变量,用 任务的属性 amount(任务设定的交易量) 初始化
        if (isCover && !pos) {                                                   // 如果 第二次循环中 , 该任务动作是平仓,并且 没有持仓了,给pos 赋值
            pos = {Amount:0, Cost: 0, Price: 0}
        }
        if (pos) {                                                               // 如果 pos 不为null 
            task.dealAmount = pos.Amount - task.preAmount;                       // 已经处理的任务量 等于 每次获取的持仓信息持仓量 与最初开始循环的初始持仓信息持仓量的差值
            if (isCover) {                                                       // 如果是 平仓动作, dealAmount 是负值, 这里取反操作
                task.dealAmount = -task.dealAmount;
            }
            remain = parseInt(task.amount - task.dealAmount);                    // 任务的 交易量 减去 已经处理的交易量  得出 剩余需要处理的交易量
            if (remain <= 0 || task.retry >= task.maxRetry) {                    // 如果剩余需要的交易量小于等于0(此处分析应该是不会小于0,有兴趣的可以分析下。) 或者重试次数大于最大重试上限.
                ret = {                                                          // 更新ret 对象,  更新为已经成交的信息,和 当前仓位信息。
                    price: (pos.Cost - task.preCost) / (pos.Amount - task.preAmount),
                    amount: (pos.Amount - task.preAmount),
                    position: pos
                };
                if (isCover) {                                                   // 如果是 平仓动作
                    ret.amount = -ret.amount;                                    // 平仓时计算出的是负值  ,取反操作
                    if (pos.Amount == 0) {                                       // 如果持仓量为0了, 把ret 的持仓信息 赋值为 null
                        ret.position = null;
                    }
                }
                break;                                                           // remain <= 0 || task.retry >= task.maxRetry 符合这个条件,跳出while循环
            }
        } else if (task.retry >= task.maxRetry) {                                // 如果不是 平仓操作。pos 为null 没有持仓(平仓操作 pos 此处不会是null)
            ret = null;                                                          // 并且 该任务重试测试 大于最大重试次数。跳出循环。
            break;                                                               // 即此时  , 超过最大重试次数,并且 没有增加持仓(开仓 每次都失败了。),跳出循环
        }

        var depth = task.e.GetDepth();                                           // 获取 深度数据
        if (!depth) {
            return self.ERR_GET_DEPTH;                                           // 获取失败立即返回
        }
        var orderId = null;                                                      // 订单ID
        var slidePrice = insDetail.PriceTick * SlideTick;                        // 计算具体滑价值
        if (isCover) {                                                           // 如果是平仓操作
            for (var i = 0; i < positions.length; i++) {                         // 遍历本轮的  API 返回的持仓信息。
                if (positions[i].ContractType !== task.symbol) {                 // 不是当前任务 品种的  跳过。
                    continue;
                }
                if (parseInt(remain) < 1) {                                      // 需要处理的 交易的量 如果小于1,跳出 while
                    break
                }
                var amount = Math.min(insDetail.MaxLimitOrderVolume, positions[i].Amount, remain);  // 在合约规定的最大下单量、持仓量、需要处理的量中取最小值。 
                if (task.action == "closebuy" && (positions[i].Type == PD_LONG || positions[i].Type == PD_LONG_YD)) {   // 如果是平多仓, 持仓信息 为 今日多仓  或者 昨日多仓
                    task.e.SetDirection(positions[i].Type == PD_LONG ? "closebuy_today" : "closebuy");                  // 设置方向
                    amount = Math.min(amount, depth.Bids[0].Amount)                                                     // 根据盘口量 和 下单量 再取一个最小值。
                    orderId = task.e.Sell(_N(depth.Bids[0].Price - slidePrice, 2), amount, task.symbol, positions[i].Type == PD_LONG ? "平今" : "平昨", 'Bid', depth.Bids[0]);
                                                                                                                        // 执行具体的 API 操作,以下平空类似
                } else if (task.action == "closesell" && (positions[i].Type == PD_SHORT || positions[i].Type == PD_SHORT_YD)) {
                    task.e.SetDirection(positions[i].Type == PD_SHORT ? "closesell_today" : "closesell");
                    amount = Math.min(amount, depth.Asks[0].Amount)
                    orderId = task.e.Buy(_N(depth.Asks[0].Price + slidePrice, 2), amount, task.symbol, positions[i].Type == PD_SHORT ? "平今" : "平昨", 'Ask', depth.Asks[0]);
                }
                // assume order is success insert
                remain -= amount;                                                // 假设是成功执行, 需要处理的交易量 减去 此次交易的量。
            }
        } else {                                                                 // 开仓
            if (task.action == "buy") {
                task.e.SetDirection("buy");
                orderId = task.e.Buy(_N(depth.Asks[0].Price + slidePrice, 2), Math.min(remain, depth.Asks[0].Amount), task.symbol, 'Ask', depth.Asks[0]);
            } else {
                task.e.SetDirection("sell");
                orderId = task.e.Sell(_N(depth.Bids[0].Price - slidePrice, 2), Math.min(remain, depth.Bids[0].Amount), task.symbol, 'Bid', depth.Bids[0]);
            }
        }
        // symbol not in trading or other else happend
        if (!orderId) {                                                          // 没有返回具体的ID ,可能是 交易不在交易队列,或者其他错误。
            task.retry++;                                                        // 累计重试次数
            return self.ERR_TRADE;                                               // 返回错误信息。即使不成功, 重新 执行该任务的时候 会重新一次流程。除了task对象的数据 所有数据都会刷新
        }
    } while (true);                                                              // 循环判断 恒为真
    task.finished = true                                                         // 如果在 while 循环中没有直接 return  顺序执行到此,则任务完成                                                      

    if (self.onTaskFinish) {                                                     // 如果队列控制对象的 回调函数 设置 不为null(即 self.onTaskFinish 存在)
        self.onTaskFinish(task, ret)                                             // 执行回调函数。把 task 任务 对象  和 交易的结果  ret 对象 传入回调函数。 
    }

    if (task.onFinish) {                                                         // 处理 任务的回调函数
        task.onFinish(task, ret);
    }
    return self.ERR_SUCCESS;
}

self.poll = function() {                                                         // 迭代执行 弹出 tasks 中的任务 ,并调用 pollTask 执行任务。
    var processed = 0                                                            // 未执行完成的任务计数 ,每次初始0
    _.each(self.tasks, function(task) {                                          // 迭代  可以搜索 _.each 的用法
        if (!task.finished) {                                                    // 如果 任务不是完成状态,
            processed++                                                          // 未完成任务 计数 累计
            self.pollTask(task)                                                  // 执行弹出的任务
        }
    })
    if (processed == 0) {                                                        // 如果没有未完成的任务,即 所有任务队列内的任务完成 ,执行清空 队列对象中 tasks 数组.
        self.tasks = []
    }
}

self.size = function() {                                                         // 给队列对象添加 函数 size 获取 任务队列 中 任务个数
    return self.tasks.length
}

return self                                                                      // 返回构造好的队列对象

}

$.AccountToTable = AccountToTable;


Mehr