Estratégia de aberração

Autora:Sonhos pequenos, Criado: 2016-12-10 12:53:45, Atualizado: 2016-12-10 12:57:30

A estratégia de aberração para ganhar dinheiro com tendências


  • Introdução

Muitos amigos de futuros intuitivos podem estar um pouco desconhecidos da estratégia Aberration, o lendário sistema de negociação que criou um rendimento anual superior a 100% inventado por Keith Fitschen em 1986. Em 1993, ele publicou o sistema na revista americana Future Truth, e seu desempenho tem estado em primeiro lugar desde a data do lançamento da estratégia, ocupando o primeiro lugar nas classificações de desempenho de sistemas de negociação lançados em 1997, 2001 e 2005. Trata-se de um sistema de negociação de médio e longo prazos, com uma estratégia de rastreamento de tendências, que opera com flexibilidade entre oito variedades, entre as quais cereais, carne, metais, energia, forex, futuros de índices de ações, e obtém lucros através de um rastreamento de tendências de longo prazos. Como ele negocia simultaneamente em vários mercados não relacionados ou com baixa correlação, o alto lucro obtido com a tendência em um ou vários mercados compensa os prejuízos em outros mercados instáveis. A estratégia de estabilização da estratégia é a seguinte: primeiro, usar a média móvel de 35 dias e o desvio padrão do preço de fechamento em 35 dias para obter três trajetórias, quando o preço de fechamento de um Bar é mais alto quando ele atravessa o trajeto, o baixo é aberto quando ele atravessa o trajeto, o baixo atravessa o trajeto e o alto atravessa o trajeto. A ideia da estratégia é simples: usar a média móvel e o canal de desvio padrão para captar a tendência e, em seguida, determinar se a tendência foi quebrada. Quando a tendência está em declínio, a linha K pode ser considerada como terminada quando atravessa a linha K em sentido inverso. A estratégia foi lançada muito cedo e pode não ser muito útil no mercado atual, mas a ideia de capturar tendências é duradoura.

  • Resumo II

    O sistema de negociação de aberração foi inventado por Keith Fitschen em 1986 e publicado na revista Future Trust em 1993. Curiosamente, Keith não foi um comerciante de nascença, ele serviu na Força Aérea dos Estados Unidos por mais de 20 anos, especializado em sistemas de navegação de armas, com um profundo poder no processamento de dados de sequência de tempo. O sistema de negociação de aberração é caracterizado por seguir tendências passivas, usando sinais de longo prazo, negociando 3-4 vezes por ano em uma variedade, mantendo um tempo superior a 60% do tempo total de negociação, e pode distribuir um número diferente de variedades de acordo com diferentes tamanhos de capital. Ele obtém grandes lucros por capturar tendências através de negociações de longo prazo, enquanto negocia em vários mercados não relacionados, e quando uma variedade retira-se, outra pode ganhar. Especificamente, o sistema de aberação usa três trajetórias para negociar. Primeiro, calcula a média arquitetônica MA (close) do preço de fechamento da variedade nos últimos N dias como o trajeto médio (MID), com o desvio padrão (std) do preço de fechamento (close) como uma medida da volatilidade, e calcula o trajeto MID + m.std ((close) e MID-mstd ((close) ); fazer mais quando o preço quebra o trajeto e estabiliza quando o preço volta ao trajeto médio; ao contrário, fazer mais quando o preço quebra o trajeto e estabiliza quando o preço volta ao trajeto médio.

  • Princípios estratégicos

    Aberração é também um sistema de rompimento de canal, mas seu caminho para cima e para baixo é determinado pela taxa de flutuação.

    1o, a identificação do trajeto: A aberração é composta por três linhas de canal, onde o meio-campo é a média móvel de um determinado ciclo ("AveMa") e o trajeto ascendente é baseado no meio-campo com um valor de preço padrão (StdValue), ou seja, a linha de Braun, que é conhecida por nós. O sistema é muito simples e elegante.

    O processo de cálculo é o seguinte: (1) Cálculo da trajetória: AveMa=Average ((Close[1],Length); (2) Computação de erro de padrão: StdValue = StandardDev ((Close[1],Length); (3) Computação em rota: UpperBand=Avema+StdDevUpStdValue; (StdDevUp é o parâmetro de tração) (4) Calculação da linha inferior: LowerBand=Avema-StdDevDnStdValue; (StdDevDn para o parâmetro do trilho)

    2 - Condições de venda: O preço de fechamento ultrapassou a linha de chegada para abrir mais posições e caiu para fora da linha de chegada. Embalagem vazia: o preço de fechamento caiu abaixo do trajeto para abrir o espaço vazio, quebrando o trajeto médio.

  • Código de origem da estratégia

    • Estrutura estratégica lógica clara, reutilizabilidade forte
    • Debug em tempo real através de funções interativas em disco real
    • Funcionando de forma estável, com detalhes perfeitos
    • Suporte para operações simultâneas de várias variedades, com controle de volume de armazenamento separado
    • A reinicialização restaura automaticamente o progresso de acordo com a posição
    • Com um módulo de controle de vento, pode mostrar o risco em tempo real, parar os danos
    • Acompanhe a notificação do WeChat
    • Quem não quiser alugar um servidor pode usar o seu próprio computador ou um Windows, Linux ou Mac para executar o sistema, o roteador pode ser limpo.
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)
    }
}
  • Resultados dos testes

    O sistema só pode ser usado para construir um portfólio.img

  • Resumo

    1, a variedade e a adaptabilidade do ciclo da estratégia são excelentes e são adequadas para a maioria das variedades de negociação; 2 - A estratégia de retração é grande e requer uma gestão rigorosa dos fundos e controle de riscos;


Mais.