Estrategia de aberración

El autor:Un sueño pequeño., Creado: 2016-12-10 12:53:45, Actualizado: 2016-12-10 12:57:30

La estrategia de aberración para ganar dinero con tendencias


  • Descripción

Muchos amigos que juegan con los futuros intuitivos pueden estar un poco extraños de la estrategia Aberration, el legendario sistema de negociación que creó un rendimiento anual superior al 100% inventado por Keith Fitschen en 1986. En 1993, publicó el sistema en la revista estadounidense Future Truth, y su rendimiento ha estado en primer lugar desde la fecha de publicación de la estrategia, ocupando el primer lugar en las clasificaciones de rendimiento de los sistemas de negociación lanzados en 1997, 2001 y 2005. Es un sistema de negociación de línea media y larga, con una estrategia de seguimiento de tendencias, que opera con flexibilidad entre 8 variedades de cereales, carnes, metales, energía, divisas, futuros de índices de valores, etc., para obtener ganancias a través del seguimiento de tendencias de línea larga. Y debido a que se negocia simultáneamente en varios mercados no relacionados o con poca correlación, los altos beneficios de tendencias en uno o varios mercados compensan las pérdidas en otros mercados inestables. La estrategia de esta estrategia es la siguiente: primero se utiliza la media móvil de 35 días y el desvio estándar del precio de cierre de 35 días para obtener tres trayectorias superiores y inferiores, cuando el precio de cierre de un Bar es más elevado cuando se pone en marcha, el inferior está abierto cuando se pone en marcha, el inferior se coloca más arriba cuando se coloca en marcha, el superior se coloca en marcha cuando se coloca en marcha. La idea de esta estrategia es muy simple: utilizar la media móvil y el canal de desviación estándar para captar la tendencia y, a cualquier hora, determinar si se rompió el canal. Cuando la tendencia se debilita gradualmente, la trayectoria media se relaja primero, por lo que cuando la línea K cruza la trayectoria central en sentido contrario, se puede considerar que la tendencia ha terminado y detener la salida. La estrategia fue lanzada años antes y puede no ser muy útil en el mercado actual, pero la idea de captar tendencias es duradera.

  • Biografía II

    El sistema de negociación de aberración fue inventado por Keith Fitschen en 1986 y publicado en 1993 en la revista Future Trust. Curiosamente, Keith no era un comerciante nacido, y durante más de 20 años de servicio en la Fuerza Aérea de los Estados Unidos, se especializó en sistemas de navegación de armas, con una gran capacidad para procesar datos de secuencias de tiempo. El sistema de negociación de aberración se caracteriza por un seguimiento pasivo de tendencias, con señales de largo plazo, que se negocian 3-4 veces al año en una variedad, con un tiempo de retención superior al 60% del tiempo total de negociación, y se puede asignar un número diferente de variedades según el tamaño de los fondos. Se obtiene una gran ganancia al capturar tendencias mediante operaciones largas, mientras que las operaciones en varios mercados no relacionados, cuando una variedad retrocede, la otra puede ganar. Concretamente, el sistema de aberración utiliza 3 trayectorias para operar. Primero, se calcula el promedio aritmético MA (close) del precio de cierre de la variedad en los últimos N días como el MID del trayecto, y se calcula el MID + m del trayecto con el desvío estándar (std) del precio de cierre como una medida de la volatilidad.std ((close) y MID-m en el tren inferiorstd ((close) ); hacer más cuando el precio rompe la trayectoria y estabilizar cuando el precio vuelve a la trayectoria media; por el contrario, hacer espacio cuando el precio rompe la trayectoria baja y estabilizar cuando el precio vuelve a la trayectoria media.

  • Principios estratégicos

    La aberración es también un sistema de avance de canal, pero su camino hacia arriba y hacia abajo está determinado por la frecuencia de fluctuación.

    1, la determinación de los trayectos: La aberración se compone de tres líneas de canal, en las que la trayectoria central es la media móvil de un determinado ciclo (AveMa), la trayectoria ascendente y descendente es la base de la trayectoria central, más o menos un cierto valor estándar de precio (StdValue), es decir, la línea de Bryn que conocemos, la estructura del sistema es muy concisa y elegante.

    El proceso de cálculo es el siguiente: (1) Calculación de la trayectoria: AveMa=Average ((Close[1], Length); (2) El error de cálculo de los estándares: StdValue = StandardDev ((Close[1], Length); (3) Computación en línea: UpperBand=Avema+StdDevUpStdValue; (StdDevUp es el parámetro de trayectoria) (4) Calculación de trayectoria: Baja banda = Avema-StdDevDnStdValue; (StdDevDn es el parámetro de trayecto)

    2, Condiciones de venta: El precio de cierre rompe la línea de venta y se abre más, cayendo en la línea media. En la actualidad, el precio de cierre se ha desplomado por debajo de la línea de crédito y el precio de cierre se ha abierto por debajo de la línea de crédito, rompiendo la línea media.

  • El código fuente de la estrategia

    • El marco estratégico es lógico y reutilizable.
    • Desactivación en tiempo real cuando se ejecuta a través de un disco real de funciones interactivas
    • Funcionando de manera estable, los detalles están perfectos.
    • Soporte para múltiples variedades de operaciones simultáneas, con control de volumen de apertura por separado
    • Se puede restablecer el progreso automáticamente según la posición al reiniciar
    • Un módulo de control de viento que muestra el riesgo en tiempo real y detiene el daño.
    • Las notificaciones de WeChat
    • Los usuarios que no quieran alquilar un servidor pueden usar su propia computadora o un Mac para ejecutar sistemas Windows, Linux o Mac, y pueden limpiar el router.
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 de las pruebas

    El poder del sistema sólo se puede aprovechar construyendo una cartera.img

  • Resumen

    1.La variedad y la adaptabilidad al ciclo de la estrategia son excelentes y se adaptan a la mayoría de las variedades de operaciones. 2. la estrategia de retiro es grande y requiere una gestión de fondos y un control de riesgos estrictos;


Más.