Stratégie d'aberration

Auteur:Le petit rêve, Créé: 2016-12-10 12:53:45, Mis à jour: 2016-12-10 12:57:30

La stratégie d'aberration pour gagner de l'argent avec les tendances


  • Première présentation

Beaucoup d'amis qui jouent sur les futures intuitives sont peut-être un peu étrangers à la stratégie Aberration, le système de trading légendaire qui a créé un rendement annuel supérieur à 100% inventé par Keith Fitschen en 1986. En 1993, il a publié le système dans le magazine américain Future Truth. Il s'agit d'un système de négociation à courte et moyenne ligne, qui fonctionne de manière flexible entre huit variétés de céréales, de viande, de métaux, d'énergie, de devises et de futures boursières. Il est utilisé pour obtenir des profits en suivant les tendances à long terme. Comme il négocie simultanément dans plusieurs marchés non liés ou peu liés, il est possible de compenser les pertes des autres marchés instables en obtenant des profits élevés sur une ou plusieurs tendances. La stratégie de l'ouverture de l'équilibre est la suivante: utilisez d'abord la moyenne mobile de 35 jours et le déficit standard de la clôture de 35 jours, pour obtenir les trois pistes supérieures et inférieures, lorsque le prix de clôture d'un Bar est trop élevé lorsqu'il traverse la trajectoire, le bas est ouvert lorsqu'il traverse la trajectoire inférieure, le bas traverse la trajectoire inférieure, le haut traverse la trajectoire inférieure et le haut traverse la trajectoire inférieure. L'idée de cette stratégie est simple: utiliser les moyennes mobiles et les canaux de décalage standard, puis à tout moment juger si le canal a été franchi et ainsi capturer la tendance. Lorsque la tendance s'affaiblit progressivement, la tendance à l'atténuation de la trajectoire centrale se produit d'abord, de sorte que lorsque la ligne K traverse la trajectoire centrale à l'envers, la tendance peut être considérée comme terminée et l'arrêt de la course. La stratégie a été publiée plus tôt et n'est peut-être pas très adaptée aux conditions actuelles du marché, mais l'idée de la capture de tendance est durable.

  • Deuxième résumé

    Le système de trading Abberation a été inventé par Keith Fitschen en 1986 et publié dans Future Trust en 1993. Il est intéressant de noter que Keith n'est pas un trader de naissance. Il a servi dans l'armée de l'air américaine pendant plus de 20 ans, spécialisé dans les systèmes de navigation d'armes, qui ont une grande puissance dans le traitement des données de séquences chronologiques. Le système de négociation d'aberration est caractérisé par un suivi passif des tendances, une utilisation de signaux à long terme, une négociation de 3-4 fois par an sur une variété, une tenue de plus de 60% du temps total de négociation, et une allocation de variétés selon la taille des fonds. Il tire des profits énormes en capturant les tendances en faisant des transactions à long terme, tout en faisant des transactions sur plusieurs marchés non liés, et lorsque l'une des variétés se retire, l'autre peut gagner. Plus précisément, le système d'aberration utilise trois trajectoires pour effectuer des transactions. Il calcule d'abord la moyenne arithmétique MA (close) du prix de clôture de la variété au cours des N jours précédents en tant que MID, en utilisant l'écart standard std (close) du prix de clôture comme mesure de la volatilité.std ((close) et MID-m en avalstd ((close) ); faire plus lorsque le prix dépasse la trajectoire et se repose lorsque le prix revient à la trajectoire moyenne; inversement, faire un vide lorsque le prix dépasse la trajectoire moyenne et se repose lorsque le prix revient à la trajectoire moyenne.

  • Les principes stratégiques

    L'aberration est aussi un système de passage de canal, mais son passage vers le haut et vers le bas est déterminé par la fréquence de fluctuation.

    1° Définition de l'accès à la gare: L'aberration se compose de trois lignes de canaux, dont l'orbite centrale est une moyenne mobile d'un certain cycle (AveMa) et l'orbite ascendante est une valeur de prix plus ou moins basse (StdValue) sur la base de l'orbite centrale, c'est-à-dire la ligne de Braille que nous connaissons bien.

    Le processus de calcul est le suivant: (1) calculer la trajectoire moyenne: AveMa = Average ((Close[1], Length); (2) Le décalage est calculé comme suit: StdValue = StandardDev ((Close[1],Length); (3) Le calcul de la trajectoire: UpperBand = Avema + StdDevUpStdValue; (StdDevUp est le paramètre en cours d'exécution) (4) Calcul de la trajectoire: LowerBand=Avema-StdDevDnStdValue; (StdDevDn est le paramètre en aval)

    2° Conditions d'achat et de vente: Plus de points: le prix de clôture dépasse le cours de l'ouverture et dépasse le cours de l'ouverture; Le prix de clôture est tombé en dessous de la trajectoire, la position ouverte est tombée en dessous de la trajectoire, et la position moyenne a été dépassée.

  • Le code source de la stratégie

    • Le cadre stratégique est clair, logique et réutilisable
    • Débogage en temps réel lors de l'exécution du disque de fonctionnalité interactive
    • Le fonctionnement est stable, les détails sont parfaits.
    • Prise en charge de plusieurs opérations simultanées, avec contrôle de la quantité de stockage séparément
    • Retourne automatiquement la progression en fonction de la position au redémarrage
    • Il y a des modules de contrôle du vent, qui montrent les risques en temps réel, et arrêtent les dommages.
    • Vous pouvez télécharger les notifications suivantes
    • Pour ceux qui ne veulent pas louer un serveur, ils peuvent utiliser leur propre ordinateur ou un ordinateur à puce pour exécuter Windows, Linux ou Mac, et le routeur peut être débranché.
function Aberration(q, e, symbol, period, upRatio, downRatio, opAmount) {
    var self = {}
    self.q = q
    self.e = e
    self.symbol = symbol
    self.upTrack = 0
    self.middleTrack = 0
    self.downTrack = 0
    self.nPeriod = period
    self.upRatio = upRatio
    self.downRatio = downRatio
    self.opAmount = opAmount
    self.marketPosition = 0

    self.lastErrMsg = ''
    self.lastErrTime = ''
    self.lastBar = {
        Time: 0,
        Open: 0,
        High: 0,
        Low: 0,
        Close: 0,
        Volume: 0
    }
    self.symbolDetail = null
    self.lastBarTime = 0
    self.tradeCount = 0
    self.isBusy = false

    self.setLastError = function(errMsg) {
        self.lastErrMsg = errMsg
        self.lastErrTime = errMsg.length > 0 ? _D() : ''
    }

    self.getStatus = function() {
        return [self.symbol, self.opAmount, self.upTrack, self.downTrack, self.middleTrack, _N(self.lastBar.Close), (self.marketPosition == 0 ? "--" : (self.marketPosition > 0 ? "多#ff0000" : "空#0000ff")), self.tradeCount, self.lastErrMsg, self.lastErrTime]
    }
    self.getMarket = function() {
        return [self.symbol, _D(self.lastBarTime), _N(self.lastBar.Open), _N(self.lastBar.High), _N(self.lastBar.Low), _N(self.lastBar.Close), self.lastBar.Volume]
    }

    self.restore = function(positions) {
        for (var i = 0; i < positions.length; i++) {
            if (positions[i].ContractType == self.symbol) {
                self.marketPosition += positions[i].Amount * ((positions[i].Type == PD_LONG || positions[i].Type == PD_LONG_YD) ? 1 : -1)
            }
        }
        if (self.marketPosition !== 0) {
            self.tradeCount++
                Log("恢复", self.symbol, "当前持仓为", self.marketPosition)
        }
    }

    self.poll = function() {
        if (self.isBusy) {
            return false
        }

        if (!$.IsTrading(self.symbol)) {
            self.setLastError("不在交易时间内")
            return false
        }

        if (!self.e.IO("status")) {
            self.setLastError("未连接交易所")
            return false
        }

        var detail = self.e.SetContractType(self.symbol)
        if (!detail) {
            self.setLastError("切换合约失败")
            return false
        }
        if (!self.symbolDetail) {
            self.symbolDetail = detail
            Log("合约", detail.InstrumentName.replace(/\s+/g, ""), ", 策略一次开仓:", self.opAmount, "手, 一手", detail.VolumeMultiple, "份, 最大下单量", detail.MaxLimitOrderVolume, "保证金率:", detail.LongMarginRatio.toFixed(4), detail.ShortMarginRatio.toFixed(4), "交割日期", detail.StartDelivDate);
        }
        var records = self.e.GetRecords()
        if (!records || records.length == 0) {
            self.setLastError("获取柱线失败")
            return false
        }

        var bar = records[records.length - 1]
        self.lastBar = bar

        if (records.length <= self.nPeriod) {
            self.setLastError("柱线长度不够")
            return false
        }

        if (self.lastBarTime < bar.Time) {
            var sum = 0
            var pos = records.length - self.nPeriod - 1
            for (var i = pos; i < records.length - 1; i++) {
                sum += records[i].Close
            }
            var avg = sum / self.nPeriod
            var std = 0
            for (i = pos; i < records.length - 1; i++) {
                std += Math.pow(records[i].Close - avg, 2)
            }
            std = Math.sqrt(std / self.nPeriod)

            self.upTrack = _N(avg + (self.upRatio * std))
            self.downTrack = _N(avg - (self.downRatio * std))
            self.middleTrack = _N(avg)
            self.lastBarTime = bar.Time
        }
        var msg
        var act = ""
        if (self.marketPosition == 0) {
            if (bar.Close > self.upTrack) {
                msg = '做多 触发价: ' + bar.Close + ' 上轨:' + self.upTrack;
                act = "buy"
            } else if (bar.Close < self.downTrack) {
                msg = '做空 触发价: ' + bar.Close + ' 下轨:' + self.downTrack;
                act = "sell"
            }
        } else {
            if (self.marketPosition < 0 && bar.Close > self.middleTrack) {
                msg = '平空 触发价: ' + bar.Close + ' 平仓线:' + self.middleTrack;
                act = "closesell"
            } else if (self.marketPosition > 0 && bar.Close < self.middleTrack) {
                msg = '平多 触发价: ' + bar.Close + ' 平仓线:' + self.middleTrack;
                act = "closebuy"
            }
        }

        if (act == "") {
            return true
        }

        Log(self.symbol + ', ' + msg + (NotifyWX ? '@' : ''))

        self.isBusy = true
        self.tradeCount += 1
        if (self.lastErrMsg != '') {
            self.setLastError('')
        }
        self.q.pushTask(self.e, self.symbol, act, self.opAmount, function(task, ret) {
            self.isBusy = false
            if (!ret) {
                return
            }
            if (task.action == "buy") {
                self.marketPosition = 1
            } else if (task.action == "sell") {
                self.marketPosition = -1
            } else {
                self.marketPosition = 0
            }
        })
    }
    return self
}

function main() {
    if (exchange.GetName() !== 'Futures_CTP') {
        throw "只支持传统商品期货(CTP)"
    }
    
    SetErrorFilter("login|ready|初始化")

    LogStatus("Ready...")
    if (Reset) {
        LogProfitReset()
        LogReset()
    }
    
    // Ref: https://www.fmz.com/bbs-topic/362
    if (typeof(exchange.IO("mode", 0)) == 'number') {
        Log("切换行情模式成功")
    }

    LogStatus("等待与期货商服务器连接..")
    while (!exchange.IO("status")) {
        Sleep(500)
    }
    LogStatus("获取资产信息")
    var tblRuntime = {
        type: 'table',
        title: '交易信息',
        cols: ['品种', '每次开仓量', '上轨', '下轨', '中轨', '最后成交价', '仓位', '交易次数', '最后错误', '错误时间'],
        rows: []
    };
    var tblMarket = {
        type: 'table',
        title: '行情信息',
        cols: ['品种', '当前周期', '开盘', '最高', '最低', '最后成交价', '成交量'],
        rows: []
    };
    var tblPosition = {
        type: 'table',
        title: '持仓信息',
        cols: ['品种', '杠杆', '方向', '均价', '数量', '持仓盈亏'],
        rows: []
    };
    var positions = _C(exchange.GetPosition)
    if (positions.length > 0 && !AutoRestore) {
        throw "程序启动时不能有持仓, 但您可以勾选自动恢复来进行自动识别 !"
    }
    var initAccount = _C(exchange.GetAccount)
    var detail = JSON.parse(exchange.GetRawJSON())
    if (positions.length > 0) {
        initAccount.Balance += detail['CurrMargin']
    }
    var initNetAsset = detail['CurrMargin'] + detail['Available']
    var initAccountTbl = $.AccountToTable(exchange.GetRawJSON(), "初始资金")

    if (initAccountTbl.rows.length == 0) {
        initAccountTbl.rows = [
            ['Balance', '可用保证金', initAccount.Balance],
            ['FrozenBalance', '冻结资金', initAccount.FrozenBalance]
        ]
    }

    var nowAcccount = initAccount
    var nowAcccountTbl = initAccountTbl

    var symbols = Symbols.replace(/\s+/g, "").split(',')
    var pollers = []
    var prePosUpdate = 0
    var suffix = ""
    var needUpdate = false
    var holdProfit = 0

    function updateAccount(acc) {
        nowAcccount = acc
        nowAcccountTbl = $.AccountToTable(exchange.GetRawJSON(), "当前资金")
        if (nowAcccountTbl.rows.length == 0) {
            nowAcccountTbl.rows = [
                ['Balance', '可用保证金', nowAcccount.Balance],
                ['FrozenBalance', '冻结资金', nowAcccount.FrozenBalance]
            ]
        }
    }

    var q = $.NewTaskQueue(function(task, ret) {
        needUpdate = true
        Log(task.desc, ret ? "成功" : "失败")
        var account = task.e.GetAccount()
        if (account) {
            updateAccount(account)
        }
    })

    _.each(symbols, function(symbol) {
        var pair = symbol.split(':')
        pollers.push(Aberration(q, exchange, pair[0], NPeriod, Ks, Kx, (pair.length == 1 ? AmountOP : parseInt(pair[1]))))
    })

    if (positions.length > 0 && AutoRestore) {
        _.each(pollers, function(poll) {
            poll.restore(positions)
        })
    }
    var isFirst = true
    while (true) {
        var cmd = GetCommand()
        if (cmd) {
            var js = cmd.split(':', 2)[1]
            Log("执行调试代码:", js)
            try {
                eval(js)
            } catch (e) {
                Log("Exception", e)
            }
        }
        tblRuntime.rows = []
        tblMarket.rows = []
        var marketAlive = false
        _.each(pollers, function(poll) {
            if (poll.poll()) {
                marketAlive = true
            }
            tblRuntime.rows.push(poll.getStatus())
            tblMarket.rows.push(poll.getMarket())
        })
        q.poll()
        Sleep(LoopInterval * 1000)
        if ((!exchange.IO("status")) || (!marketAlive)) {
            if (isFirst) {
                LogStatus("正在等待开盘...", _D())
            }
            continue
        }
        isFirst = false
        var now = new Date().getTime()
        if (marketAlive && (now - prePosUpdate > 30000 || needUpdate)) {
            var pos = exchange.GetPosition()
            if (pos) {
                holdProfit = 0
                prePosUpdate = now
                tblPosition.rows = []
                for (var i = 0; i < pos.length; i++) {
                    tblPosition.rows.push([pos[i].ContractType, pos[i].MarginLevel, ((pos[i].Type == PD_LONG || pos[i].Type == PD_LONG_YD) ? '多#ff0000' : '空#0000ff'), pos[i].Price, pos[i].Amount, _N(pos[i].Profit)])
                    holdProfit += pos[i].Profit
                }
                if (pos.length == 0 && needUpdate) {
                    LogProfit(_N(nowAcccount.Balance - initAccount.Balance, 4), nowAcccount)
                }
            }
            needUpdate = false
            if (RCMode) {
                var account = exchange.GetAccount()
                if (account) {
                    updateAccount(account)
                    var detail = JSON.parse(exchange.GetRawJSON())
                    var netAsset = detail['PositionProfit'] + detail['CurrMargin'] + detail['Available']
                    var risk = detail['CurrMargin'] / (detail['CurrMargin'] + detail['Available'] + detail['PositionProfit'])
                    suffix = ", 账户初始净值约: " + _N(initNetAsset, 2) + " , 风控最小净值要求" + MinNetAsset + " , 当前账户净值约: " + _N(netAsset, 2) + ", 盈亏约: " + _N(netAsset - initNetAsset, 3) + " 元, 风险: " + ((risk * 100).toFixed(3)) + "% #ff0000"
                    if (netAsset < MinNetAsset) {
                        Log("风控模块触发, 中止运行并平掉所有仓位, 当前净值约 ", netAsset, ", 要求低于最小净值:", MinNetAsset)
                        if (RCCoverAll) {
                            Log("开始平掉所有仓位")
                            $.NewPositionManager().CoverAll()
                        }
                        throw "中止运行"
                    }
                }
            }
        }
        LogStatus('`' + JSON.stringify([tblRuntime, tblPosition, tblMarket, initAccountTbl, nowAcccountTbl]) + '`\n价格最后更新: ' + _D() + ', 持仓最后更新: ' + _D(prePosUpdate) + '\n当前持仓总盈亏: ' + _N(holdProfit, 3) + suffix)
    }
}
  • Résultats des tests

    Les investisseurs qui ont un système de gestion de portefeuille ne peuvent utiliser la puissance du système que s'ils construisent un portefeuille.img

  • Résumé

    1° La variété et l'adaptabilité de la stratégie au cycle sont excellentes, adaptées à la plupart des variétés de transactions; 2° La stratégie de retrait est plus importante et nécessite une gestion des fonds et un contrôle des risques plus stricts;


Plus de