Viele Freunde, die sich auf Intuition-Futures verlassen, sind vielleicht ein wenig unbekannt mit der Aberration-Strategie, dem legendären Handelssystem, das 1986 von Keith Fitschen erfunden wurde. Er veröffentlichte es 1993 in der US-amerikanischen Zeitschrift Future Truth. Seit seiner Veröffentlichung hat es die erste Position in den Performance-Listen der bereits veröffentlichten Handelssysteme in 1997, 2001 und 2005 erreicht. Es handelt sich um ein mittel-langfristiges Handelssystem mit einer Trendverfolgungsstrategie, das flexibel zwischen acht Sorten von Getreide, Fleisch, Metallen, Energie, Devisen, Aktien-Futures und anderen Trends abläuft, um Profite zu erzielen. Da es gleichzeitig in mehreren unabhängigen oder wenig relevanten Märkten gehandelt wird, kann ein hoher Trendgewinn in einem oder mehreren Märkten die Verluste in anderen instabilen Märkten ausgleichen. Die Strategie des Eröffnungs-Platzierungs-Strategies ist folgender: Erst die 35-tägige gleitende Durchschnittslinie und die Standarddifferenz des 35-tägigen Schlusskurses nutzen, um die drei oberen, mittleren und unteren Tracks zu ermitteln, bei denen der Schlusskurs eines Bars mehr auf der Spur ist, der untere auf der Spur ist, der untere auf der Spur ist, der untere auf der Spur ist, der untere auf der Mittelstrecke ist, der oberste auf der Mittelstrecke ist. Die Idee der Strategie ist ganz einfach: Man nutzt die gleitenden Mittelwerte und die Standarddifferenzen, um zu jeder Zeit zu entscheiden, ob man den Tunnel durchbrochen hat, um den Trend zu erfassen. Wenn der Trend schrittweise abschwächt, nimmt er zuerst ab, weil die Mittelbahn abklingt. Wenn die K-Linie umgekehrt durch die Mittelbahn geht, kann man den Trend als beendet betrachten und den Ausgang stoppen. Die Strategie wurde früher veröffentlicht und ist in der heutigen Handelsbranche vielleicht nicht mehr sehr anwendbar, aber die Idee, Trends zu erfassen, ist langlebig.
Das Abberation-Trading-System wurde 1986 von Keith Fitschen erfunden und 1993 in der Zeitschrift Future Trust veröffentlicht. Interessanterweise war Keith kein geborener Trader. Das Abberation-Tradingsystem ist charakterisiert durch passives Trendfolgen, mit langfristigen Signalen, das 3-4 Mal pro Jahr in einer Sorte gehandelt wird, die mehr als 60% der gesamten Handelszeit hält, und die Anzahl der Sorten je nach Kapitalgröße aufgeteilt werden kann. Es erzielt große Gewinne, indem es durch langfristige Transaktionen Trends erfasst, während es in mehreren unabhängigen Märkten gehandelt wird, und wenn eine Sorte zurücktritt, kann eine andere Sorte gewinnen. Insbesondere wird das Abberation-System mit 3 Tracks gehandelt. Zuerst wird der arithmetische Durchschnitt des letzten N-Tage-Abschlusspreises der Sorte (MA close) als Mittelstrecke (MID) berechnet, mit dem Standarddifferenzstd (close) als Maß für die Volatilität des Abschlusspreises und berechnet auf der Strecke (MID + m).std ((close) und unterbahn MID-mstd ((close) ); mehr, wenn der Preis die Bahn durchbricht, ausgeglichen, wenn der Preis in die Mitte zurückkehrt; umgekehrt, mehr, wenn der Preis die Bahn durchbricht und ausgeglichen, wenn der Preis in die Mitte zurückkehrt.
Aberration ist auch ein Tunnelbrechersystem, dessen Auf- und Abfahrt jedoch durch die Schwankungsrate bestimmt wird.
1. Feststellung des Auf- und Abfahrts: Aberration besteht aus drei Kanallinien, wobei die Mittelbahn eine bewegliche Durchschnittslinie ("AveMa") für einen bestimmten Zeitraum ist, und die Ober-Unterbahn eine bestimmte Preisstandardabweichung ("StdValue") auf der Basis der Mittelbahn ist, die wir als die bekannten Braun-Linien kennen, und die Systemkonstruktion ist sehr prägnant.
Die Berechnung erfolgt wie folgt: (1) Berechnung der Mittelbahn: AveMa=Average ((Close[1],Length); (2) Berechnung des Standardfehlers: StdValue = StandardDev ((Close[1],Length); (3) Berechnung auf der Strecke: UpperBand=Avema+StdDevUpStdValue; (StdDevUp ist der Bahnparameter) (4) Berechnung der Unterbahn: LowerBand=Avema-StdDevDnStdValue; (StdDevDn ist der Unterbahnparameter)
2. Kauf- und Verkaufsbedingungen: Der Preis für den Schlussprozess ist im Vergleich zu dem für den Vorgang der letzten Woche deutlich niedriger als für den Vorgang der letzten Woche. Der Markt ist in der Lage, sich zu bewegen, wenn die Marktanteile nicht überschritten werden, und die Marktanteile werden nicht überschritten.
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)
}
}
Das System ist so stark, dass es nur durch die Konstruktion eines Portfolios funktioniert.
1. Die Strategie ist sehr vielfältig und zyklisch anpassungsfähig und eignet sich für die meisten Handelsvarianten. 2. Die Strategie des Rückzugs ist groß und erfordert eine strenge Finanzverwaltung und Risikokontrolle.