Jouer à JavaScript avec des vieux - créer un partenaire qui fait des achats et des ventes (7)

Auteur:Le petit rêve, Créé: 2017-03-16 12:29:51, Mis à jour: 2017-10-11 10:37:54

Les outils utiles doivent savoir pourquoi ils sont utiles!

C'est un plaisir d'écrire des stratégies pendant la semaine, et toutes sortes d'idées qui sortent de l'éditeur, qui sont peut-être votre prochaine tasse de thé, sont excitantes à penser! La seule chose qui affecte cette passion est le traitement de la logique de vente et d'achat du système de stratégie de trading, qui est essentiel, mais un peu ennuyeux, et la logique est plus complexe.

  • Heureusement, il y a un module bien écrit qui peut être utilisé directement (j'en ai déjà utilisé dans des articles précédents), mais en plus de l'utiliser et de comprendre comment cela fonctionne, j'ai commenté le code:

Je ne sais pas. Interval échec de répétition d'intervalle (millisecondes) Numérique (numéro) 500 SlideTick Nombre de points de prix glissants (nombre entier) Numérique (nombre) 1 RiskControl activer le contrôle du vent Bulle (true/false) MaxTrade@RiskControl Le nombre maximum de transactions effectuées par jour de travail Numéro (numéro) 50 MaxTradeAmount@RiskControl Le montant maximum par pièce est de 1000 Je suis désolé.

var __orderCount = 0 // Enregistre le nombre d'ordres uniques suivants pour la journée de travail en cours var __orderDay = 0 // Enregistre la date de la journée de travail en cours

fonction CanTrade ((tradeAmount) { // Module de contrôle des risques, Paramètres: Nombre de transactions if (!RiskControl) { // Par défaut, le module de contrôle de vent n'est pas activé, si ce n'est pas le cas, la fonction CanTrade renvoie true retourner vrai Je ne sais pas. if (typeof(tradeAmount) == number && tradeAmount > MaxTradeAmount) { // Le paramètre tradeAmount est de type numérique, et le montant du sous-ensemble est supérieur au montant maximum du sous-ensemble défini par le paramètre du modèle Log ((Limite du module de contrôle de la tempête, dépasse le maximum de monotonie de téléchargement, MaxTradeAmount, #ff0000 @); //Expédition de l'invite, interruption de l'exécution. lancer le jeu interrompt l'exécution retourner faux; Je ne sais pas. var nowDay = new Date (().getDate ((); // obtient la date actuelle if (nowDay!= __orderDay) { // getDate() renvoie un jour du mois (1 ~ 31) depuis l'objet Date. __orderDay = nowDay; // __orderDay La variable globale enregistre la date de déclenchement de la première entrée dans le module de contrôle du vent. __orderCount = 0; // mise à jour de la variable __orderDay, réinitialisation de la variable __orderCount Je ne sais pas. __orderCount++; // la variable globale __orderCount est le nombre unique suivant, auto-additionnel. if (__orderCount > MaxTrade) { // Détermine si le nombre de transactions maximales par jour est supérieur à ce que définit le paramètre Log ((le module de contrôle des orages est limité, aucune transaction ne peut être effectuée, au-delà du nombre unique maximal de tours, MaxTrade, #ff0000 @); // dépassé, message d'avertissement de sortie, interruption de l'exécution. lancer le jeu interrompt l'exécution retourner faux; Je ne sais pas. retourner true; // aucune des conditions ci-dessus n'est déclenchée, retourne true, c'est-à-dire que les transactions peuvent être effectuées. Je ne sais pas.

fonction init ((() { // Fonction d'initialisation du modèle, exécutée en premier lors du chargement du modèle. if (typeof ((SlideTick) === undefined) { // Vérifie si le SlideTick n'est pas défini。 SlideTick = 1; // Par défaut 1 } else { // Parse une chaîne convertie en valeur numérique, mais une erreur peut survenir si la chaîne commence par un caractère non numérique et renvoie NaN Il est possible de modifier les paramètres de l'écran. Je ne sais pas. Log (l'enregistrement de l'enregistrement de l'enregistrement de l'enregistrement de l'enregistrement de l'enregistrement de l'enregistrement de l'enregistrement de l'enregistrement de l'enregistrement de l'enregistrement de l'enregistrement de l'enregistrement de l'enregistrement de l'enregistrement de l'enregistrement de l'enregistrement de l'enregistrement) Je ne sais pas.

fonction GetPosition ((e, contractType, direction, positions) { // Combine un contrat avec les positions actuelles et les positions d'hier dans la même direction, les paramètres sont les suivants: objet de l'échange, type de contrat, direction, données de stockage retournées par l'API (en)
var allCost = 0; // contractType Contract dans la direction du total des fonds dépensés, sans multiplier par le nombre de points du contrat (parce que l'ensemble peut être contracté) Var allAmount = 0; // Nombre total de pièces de contrat Var allProfit = 0; // Le résultat total des gains et pertes var allFrozen = 0; // Nombre total de congélation var pos Margin = 0; // Contrats de détention Levier if (typeof(positions) === undefined論!positions) { // Si le paramètre n'est pas passé dans l'API, les informations de stockage sont renvoyées positions = _C ((e.GetPosition); // est utilisé pour appeler l'API pour obtenir les informations de stockage. Je ne sais pas. pour (var i = 0; i < positions.length; i++) { // parcourt l'ensemble de l'information stockée. if (positions[i].ContractType == contractType && // code de contrat de l'information de détention de l'index actuel == code de contrat spécifié par paramètre ((contractType) et dont la direction est égale à celle du paramètre de transmission ((direction) de la position actuelle ou de la position précédente (Typ == PD_LONG pour les positions i.Typ == PD_LONG pour les positions i.Typ == PD_LONG pour les positions i.Typ == PD_LONG pour les positions i.Typ == PD_LONG pour les positions i.Typ == PD_LONG pour les positions i.Typ == PD_LONG pour les positions i.Typ == PD_LONG pour les positions i.Typ == PD_LONG pour les positions i.Typ == PD_SHORT pour les positions i.Typ == PD_SHORT pour les positions i.Typ == PD_SHORT pour les positions i.Typ == PD_SHORT pour les positions i.Typ == PD_LONG pour les positions i.Typ == PD_LONG pour les positions i.Typ == PD_LONG pour les positions i.Typ == PD_LONG pour les positions i.Typ == PD_SHORT pour les positions i.Typ == PD_LD pour les positions i.Typ == PD_LD pour les positions i.Typ == PD_LONG pour les positions i ) { // exécute conditionnellement le bloc if Pos Margin = positions[i].MarginLevel; // Obtenir une valeur de levier attribuer une valeur à pos Margin allCost += (positions[i].Price * positions[i].Amount); // Coût total ((nombre de parts de contrat en vente, prix de détention actuel de l'indice * volume de détention) cumulé allAmount += positions[i].Amount; // Le nombre total de joueurs du contrat allProfit += positions[i].Profit; // Accumulation des gains et pertes de contrats flottants allFrozen += positions[i].FrozenAmount; // le nombre total de mains de contrat qui sont gelées Je ne sais pas. Je ne sais pas. if (allAmount === 0) { // Si le nombre total de contrats éligibles est égal à 0 après le parcours, il renvoie null, c'est-à-dire le nombre de contrats détenus sans condition limitée retourner null; Je ne sais pas. return { // allAmount non 0, renvoie l'information de stockage d'un objet après le regroupement. MarginLevel: post Margin, qui est un groupe de blogueurs en ligne. FrozenAmount: toutFrozen, toutFrozen, toutFrozen, toutFrozen, toutFrozen, toutFrozen, toutFrozen, toutFrozen, toutFrozen, toutFrozen, toutFrozen, toutFrozen, toutFrozen, toutFrozen, tout Le prix: _N (allCost / allAmount), Le montant: toutAmount, Profit: tout profit, Type: direction Le type de contrat: Je ne sais pas. Je ne sais pas.

fonction Open ((e, contractType, direction, opAmount) { // Opération d'un seul type de contrat Fonction d'ouverture, paramètres: objet de l'échange, code du contrat, direction, nombre d'opérations var initPosition = GetPosition ((e, contractType, direction); // appelle la fonction GetPosition en haut pour obtenir les informations de stockage après la fusion. var isFirst = true; // Marque estFirst (indique que le while suivant est le premier cycle vrai) var initAmount = initPosition? initPosition.Amount : 0; // Si initPosition est nul, initAmount est attribué 0, sinon initPosition.Amount est attribué var positionNow = initPosition; // déclare une variable positionNow indiquant l'information actuellement en stock while (true) { // while en boucle var needOpen = opAmount; // déclare la variable temporaire needOpen et lui attribue une valeur avec le paramètre quantité de transaction requise if (isFirst) { // Si c'est la première fois, il suffit de mettre à jour le bloc isFirst. estFirst = faux; Je ne sais pas. positionNow = GetPosition ((e, contractType, direction); // mettre à jour positionNow, les informations de stockage actuelles. if (positionNow) { // Si une position est disponible, le nombre d'opérations nécessaires à l'ouverture de la position suivante needOpen est égal à la quantité d'opérations requise par le paramètre moins la différence entre la position obtenue cette fois et la dernière fois (c'est-à-dire le nombre de nouvelles mains ouvertes) NeedOpen = opAmount - (positionNow.Amount - initAmount); Je ne sais pas. Je ne sais pas. var insDetail = _C ((e. SetContractType, contractType); // définir le type de contrat. // Log (pour le cache initial, initAmount, pour le cache actuel, positionNow, pour le cache à ajouter, needOpen); if (needOpen < insDetail.MinLimitOrderVolume) { // Si le nombre de commandes à ouvrir est inférieur au nombre de commandes à ouvrir le plus bas de la liste de commandes limitée du contrat break; // saute du cycle Je ne sais pas. if (!CanTrade(opAmount)) { // Module de contrôle du vent Détecte si false est retourné Sautez du cycle sans transaction. Je ne sais pas. Je ne sais pas. Var depth = _C ((e.GetDepth); // Obtenez des informations sur la profondeur du marché. var amount = Math.min ((insDetail.MaxLimitOrderVolume, needOpen); // Limiter le volume de sous-traitance ne peut pas être supérieur au volume de sous-traitance maximal de la sous-traitance au prix du contrat e. SetDirection ((direction == PD_LONG? buy: sell); // définir la direction de la ligne en fonction du paramètre direction. le nom de l'application; if (direction == PD_LONG) { // appeler des API différentes pour effectuer des transactions (plus ou moins) selon la direction du paramètre direction L'ordre de commande est le même que celui de l'ordre d'achat. L'ordre d'achat est le même que celui de l'ordre de commande. // Pour plus de détails, voir la documentation de l'API, le prix d'un bond de CTP sur un produit à terme est insDetail.PriceTick, qui doit être un nombre entier de fois cette valeur // Le volume réel de l'appel d'API n'est pas supérieur au volume de l'inventaire Je ne sais pas. L'ordre de vente est le type de la commande, le type de la commande, le type de la commande, le type de la commande, le type de la commande, le type de la commande. Je ne sais pas. // annuler les commandes en attente while (true) { // Après avoir passé une commande À intervalles d'un intervalle de temps, annuler les commandes non terminées. Je ne sais pas comment faire. Var orders = _C ((e.GetOrders); // récupère toutes les commandes qui ne sont pas encore terminées if (orders.length === 0) { // Si les ordres sont des ensembles vides, sautez le while actuel Je ne sais pas. Je ne sais pas. for (var j = 0; j < orders.length; j++) { // Traverse une plage d'ordres qui n'est pas terminée e.CancelOrder ((orders[j].Id); // annuler une commande selon l'ID de l'information de commande dans l'index actuel. if (j < (orders.length - 1)) { // traverse un intervalle de temps, une fois la fréquence est trop élevée. Sleep ((Interval); // Sleep interrompt l'intervalle en millisecondes Je ne sais pas. Je ne sais pas. Je ne sais pas. } // Si le cycle principal s'arrête pendant var ret = { // Déclare un objet à retourner prix: 0, // prix moyen de la transaction quantité: 0, // le nombre de transactions effectuées position: positionNow // Informations récentes sur le stockage de cette variété Je ne sais pas. if (!positionNow) { // Si aucune information de stockage n'est disponible, retournez directement le ret d'initialisation retour ret; Je ne sais pas. if (!initPosition) { // Si aucune information de stockage de cette espèce n'est disponible au début de l'exécution de la fonction actuelle. ret.price = positionNow.Price; // Le prix de la positionNow est le prix moyen de la position actuelle. Ret.amount = positionNow.Amount; // En même temps } else { // si la variété a déjà été stockée au début. ret.amount = positionNow.Amount - initPosition.Amount; // le décalage est le nombre de positions ouvertes ret.price = _N(((positionNow.Price * positionNow.Amount) - (initPosition.Price * initPosition.Amount)) / ret.amount); // Les frais supplémentaires de cette transaction sont déduits du prix moyen de cette transaction Je ne sais pas. retour ret; // retour ret Je ne sais pas.

fonction Cover ((e, contractType) { // Fonction de placement unique, paramètres: objet de l'échange, code du contrat var insDetail = _C ((e.SetContractType, contractType); // définir le type de contrat while (true) { // cycle principal while Var n = 0; // Compte des opérations de mise en place var opAmount = 0; // déclaration Opération Variable var positions = _C ((e.GetPosition); // appeler l'API pour obtenir des informations de stockage, pour distinguer les fonctions de stockage ci-dessus. Voir la documentation de l'API pour plus de détails. pour (var i = 0; i < positions.length; i++) { // parcourir les informations stockées if (positions[i].ContractType!= contractType) { // Si l'information de stockage de l'index actuel Le contrat n'est pas égal au contrat à exploiter, c'est à dire: contractType Continue; // Sautez Je ne sais pas. var amount = Math.min ((insDetail.MaxLimitOrderVolume, positions[i].Amount); // contrôle le volume maximal des transactions qui ne sont pas supérieurs à celui du reçu la profondeur varie; if (positions[i].Type == PD_LONG の の positions[i].Type == PD_LONG_YD) { // Traite plusieurs positions depth = _C ((e.GetDepth); // appeler l'API pour obtenir les données actuelles de l'inventaire opAmount = Math.min ((amount, depth.Bids[0].Amount); // limitation La quantité d'opérations ne doit pas dépasser une tranche if (!CanTrade ((opAmount)) { // Détection du module de contrôle du vent retourner; Je ne sais pas. e.SetDirection ((positions[i].Type == PD_LONG? closebuy_today fenêtre : closebuy fenêtre); // paramètres Direction de transaction, voir la documentation API pour plus de détails

            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 = { // est utilisé pour afficher des informations détaillées sur le compte dans la barre d'état, dictionnaire Le compte ID de l'investisseur est une barre de caractères qui permet à l'investisseur d'avoir un compte en ligne. Le gouvernement a décidé de mettre en place un système d'épargne-investissement pour les personnes âgées. Les banques ont également mis en place des systèmes de paiement en espèces, qui permettent aux banques d'économiser de l'argent. Le code de la société de courtage est le Code de la société de courtage. Le déficit de trésorerie est en hausse, et le déficit de trésorerie est en hausse. Le gouvernement a annoncé que le projet de loi sur le financement de l'investissement dans le secteur de l'électricité serait mis en œuvre. Le gouvernement chinois a décidé de suspendre le paiement de la taxe de séjour. Le taux de crédit est en hausse, et les taux de change sont en hausse. Le montant total des garanties actuelles est élevé, mais le montant total des garanties actuelles est inférieur au montant total des garanties actuelles. Le code de la monnaie est le code de la monnaie, le code de la monnaie. Les investisseurs ont livré de l'or de garantie, mais ils ont perdu de l'argent. Les dépôts sont des dépôts d'argent, des dépôts d'argent, des dépôts d'argent. Le prix de l'or est le prix le plus élevé au monde, et le prix le plus élevé au monde. Les banques ont mis en place un système de garantie de l'or sur les marchés boursiers, ce qui a permis aux banques de se doter de l'argent nécessaire pour financer leurs activités. Le projet de loi sur les fonds froids a été lancé par le gouvernement chinois, qui a décidé d'envoyer des fonds froids à la banque. Le projet de loi de la Commission sur le gel des tarifs a été adopté par le Conseil de sécurité. Le film est basé sur le livre de la même marque, "Frozen Margin". Le montant des prêts hypothécaires disponibles est le montant des prêts hypothécaires disponibles, et les prêts hypothécaires disponibles sont les prêts hypothécaires disponibles. Le fonds hypothécaire en crypto: le fonds hypothécaire en crypto est un fonds hypothécaire en crypto, un fonds hypothécaire en crypto. Le fonds hypothécaire a été mis en place pour financer des prêts hypothécaires. Les intérêts augmentent, les revenus augmentent, les intérêts augmentent. Le taux d'intérêt de la banque est le plus élevé au monde. Le gouvernement a annoncé que le projet de loi sur les prêts hypothécaires devrait être mis en œuvre en 2020. Les fonds hypothécaires sont des fonds qui peuvent être utilisés pour l'acquisition d'un bien immobilier ou de biens immobiliers. Les investisseurs qui ont une position sur le marché ont une position sur le marché et les investisseurs ont une position sur le marché. Il a également déclaré qu'il n'était pas en mesure d'évaluer les réserves d'or. Il y a eu une augmentation du taux de crédit de la banque, et il y a eu une augmentation du taux de crédit de la banque. Le dépôt préalable est un dépôt qui peut être effectué à partir de la dernière fois que vous avez déposé. L'article est intitulé "Pre-Fund Mortgage In": "La dernière fois que vous avez mis de l'argent dans un prêt hypothécaire, vous avez mis de l'argent dans un prêt hypothécaire". Il y a un autre problème avec le prêt hypothécaire: le prêt hypothécaire pré-financée est un prêt hypothécaire qui ne peut être remboursé qu'à partir du moment où le prêt hypothécaire est remboursé. Le groupe a également publié un article intitulé "L'économie de la marge de revient" sur son site officiel. Il y a eu une réaction positive de la part du gouvernement à l'annonce de l'annulation de l'opération. L'aluminium réserve: L'aluminium est une réserve d'or de base. Les réserves de réserve sont les réserves de réserve de l'épargne-investissement, les réserves de réserve de l'épargne-investissement et les réserves de réserve de l'épargne-investissement. Le problème est que les gens ne sont pas prêts à accepter la solution, mais ils ne peuvent pas accepter de la prendre. Les produits spéciaux qui sont stockés dans des magasins ont gagné ou perdu de l'argent, et les produits spéciaux qui sont stockés dans des magasins ont perdu de l'argent. Le prix du produit spécifique est calculé sur la base des tarifs des produits spéciaux, et les tarifs des produits spéciaux sont calculés sur la base des tarifs des produits spécifiques. Les échanges de produits spéciaux garantissent des échanges de produits spéciaux. Les pommes de terre spécialement conçues pour la congélation des produits spéciaux sont des pommes de terre à frais de congélation. Les produits spéciaux de la pomme de terre sont les pommes de terre froides, les pommes de terre froides, les pommes de terre froides, les pommes de terre froides. Les produits spéciaux sont couverts par des marges de garantie de l'or, et les produits spéciaux sont couverts par des marges de garantie de l'or. Les produits spéciaux sont stockés sur le marché, et les produits spéciaux sont stockés sur le marché, et les produits spéciaux sont stockés sur le marché. Le produit spécifique (SpecProductPositionProfitByAlg): le produit spécifique (SpecProductPositionProfitByAlg) est un produit spécifique (SpecProductPositionProfitByAlg) calculé en fonction de l'algorithme du produit spécifique (SpecProductPositionProfitByAlg). Les traders ont été invités à participer à l'événement. Le "Withdraw" est un jeu de tirage au sort qui consiste à retirer une somme d'or. Le site officiel de l'organisation est le site officiel de l'organisation: Je ne sais pas.

fonction AccountToTable ((jsStr, title) { // fonctionnalité permettant d'exporter des informations de compte dans un formulaire à barres d'état, paramètre: chaîne de structure JSON à afficher, titre if (typeof(title) === undefined) { // Si le paramètre title n'est pas entré, initialement: informations de compte Titre = Voir la barre d'informations du compte; Je ne sais pas. var tbl = { // Déclare un objet de table utilisé pour transmettre la fonction LogStatus, affichée dans la barre d'état type: table, // type Désigné comme table title: title, // paramètre title attribuer une valeur au champ title de tbl cols: [Coupe des champs de colonne, Coupe des champs de description, Coupe des valeurs thérapeutiques], // titre de la table rows: [] // champs arithmétiques dans lesquels les données sont stockées par ligne de la table, à l'origine en tant qu'arrayons vides. Je ne sais pas. Try { // détecte une anomalie var fields = JSON.parse ((jsStr); // analyse de la chaîne jsStr pour (var k in fields) { // traverse les propriétés des objets fields, k est la valeur de l'attribut, ne comprenant pas peut consulter le tutoriel JS. if (k == AccountID k == BrokerID) { // Si l'attribut actuellement parcouru est l'une ou l'autre des deux attributs, sautez-le. Poursuite Je ne sais pas. var desc = trans[k]; // basé sur le nom de l'attribut du dictionnaire trans var v = fields[k]; // obtient la valeur du nom de l'attribut actuel if (typeof(v) === number) { // Si la valeur de l'attribut est de type numérique, une fraction de 5 bits est conservée. v = _N ((v, 5); Je ne sais pas. tbl.rows.push (([k, typeof(desc) === undefined? : desc, v]); // Comprime l'ensemble d'attributs, de descriptions et de valeurs d'attributs en une seule dimension dans l'attribut rows de l'objet de la table tbl. Je ne sais pas. } catch (e) {} // Capture une exception, mais ne traite pas retourner tbl; // retourner l'objet tbl Je ne sais pas.

var PositionManager = (function() { // Déclare qu'une variable PositionManager accepte la valeur de retour d'une fonction anonyme qui est une valeur d'objet construite fonction PositionManager ((e) { // Déclare qu'une fonction PositionManager est une fonction anonyme. if (typeof(e) === undefined) { // Si le paramètre e n'est pas passé, attribuer par défaut la variable globale Exchange à e e = échange; Je ne sais pas. if (e.GetName()!== Futures_CTP) { // Détecte si l'objet principal de l'échange est un échange de futures sur des produits, si ce n'est pas une exception de lancement. throw Only support CTP ; // ne prend en charge que CTP Je ne sais pas. this.e = e; // ajouter une propriété e à la fonction actuelle (en fait aussi un objet) et lui attribuer le paramètre e this.account = null; // ajouter un compte La variable est initialement null Je ne sais pas. // Obtenez le cache PositionManager.prototype.Account = function (() { // Ajouter une méthode à la fonction Account de PositionManager déclarée ci-dessus if (!this.account) { // Si l'attribut account de PositionManager est nul this.account = _C ((this.e.GetAccount); // appelle la fonction GetAccount (l'API de l'objet de l'échange) de cet objet d'échange pour obtenir les informations sur le compte. Je ne sais pas. retourner ce.account; // Cette méthode renvoie l'information de ce compte PositionManager.account. Je ne sais pas. PositionManager.prototype.GetAccount = function ((getTable) { // Ajouter une méthode pour obtenir les dernières informations sur le compte Cette page contient les informations suivantes: if (typeof ((getTable)!== undefined bar && getTable) { // Pour retourner les détails de l'information de compte la plus récente dans un objet, getTable doit être true retour AccountToTable ((this.e.GetRawJSON)) // Fonction GetRawJSON voir la documentation de l'API Je ne sais pas. retourner this.account; // renvoie les informations de compte mises à jour. Je ne sais pas.

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) { // Exporte une fonction pour créer un objet PositionManager retourner le nouveau PositionManager ((e); Je ne sais pas.

// par le biais:http://mt.sohu.com/20160429/n446860150.shtml$.IsTrading = function ((symbol) { // Détermine si un contrat est en cours de négociation Dans la période de temps, le paramètre symbol Le code du contrat var now = new Date ((); // obtient l'objet à l'heure actuelle Var day = now.getDay ((); // obtient l'heure actuelle pour un jour de la semaine spécifique. Var hour = now.getHours ((); // Retrouve l'heure de l'heure dans les 24 heures var minute = now.getMinutes ((); // Retrouve quelle minute dans une minute

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) { // est une fonction de construction d'objets de file d'attente utilisée pour effectuer une variété de transactions. Paramètre: fonction de retour à l'achèvement de la tâche. var self = {} // déclare un objet vide self.ERR_SUCCESS = 0 // Définition de retour d'information Réussite erreur de mise en place du contrat l'erreur de ligne K est obtenue self.ERR_GET_ORDERS = 3 // Obtenir une commande qui n'est pas terminée self.ERR_GET_POS = 4 // Erreur d'obtention de l'information de stockage L'erreur de transaction est apparue. l'erreur d'obtention de la profondeur de champ est self.ERR_NOT_TRADING = 7 // pas en cours de négociation L'option est définie comme suit:

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 = compte à table;


Plus de