
Ao realizar análises técnicas em negociações, os traders analisam e estudam dados de preços de ações como dados normalmente distribuídos. Entretanto, a distribuição dos dados de preços de ações não está de acordo com a distribuição normal padrão.Fisher TransformationÉ um método que pode transformar dados de preços em uma distribuição normal.Fisher TransformationSuavize os dados de mercado e elimine algumas oscilações bruscas de ciclo pequeno. Sinais de negociação podem ser gerados usando o cruzamento de indicadores do dia atual e do dia anterior.
sobreFisher TransformHá muitas informações sobre Baidu e Zhihu, então não entrarei em detalhes aqui.
mid=(low + high) / 2
lowestLow = 周期内最低价,highestHigh = 周期内最高价。
ratioé uma constante entre 0 e 1, por exemplo, 0,5 ou 0,33):
xusarFisherTransformar, obterFisheríndice:
Implemente-o passo a passo de acordo com o algoritmo do indicador. Vale ressaltar que esse algoritmo é iterativo.preX,preFishInicialmente definido como 0. paraMath.logIsto é para encontrar o logaritmo com a constante natural e como base. Além disso, o algoritmo acima não menciona a correção de x, e quase ignorei essa questão ao escrevê-lo:
Corrija o valor de x. Se for maior que 0,99, ele será forçado para 0,999. O mesmo se aplica se for menor que -0,99.
if (x > 0.99) {
x = 0.999
} else if (x < -0.99) {
x = -0.999
}
A primeira vez que analisei esse algoritmo e indicadores, eu os transplantei de acordo com o algoritmo. Não verifiquei esta implementação. Alunos interessados em pesquisa podem verificar se há algum erro. Muito obrigado por apontar o erro.
Fisher TransformCódigo fonte do algoritmo do indicador:
function getHighest(arr, period) {
if (arr.length == 0 || arr.length - period < 0) {
return null
}
var beginIndex = arr.length - period
var ret = arr[beginIndex].High
for (var i = 0 ; i < arr.length - 1 ; i++) {
if (arr[i + 1].High > ret) {
ret = arr[i + 1].High
}
}
return ret
}
function getLowest(arr, period) {
if (arr.length == 0 || arr.length - period < 0) {
return null
}
var beginIndex = arr.length - period
var ret = arr[beginIndex].Low
for (var i = 0 ; i < arr.length - 1 ; i++) {
if (arr[i + 1].Low < ret) {
ret = arr[i + 1].Low
}
}
return ret
}
function calcFisher(records, ratio, period) {
var preFish = 0
var preX = 0
var arrFish = []
// 当K线长度不足,不满足周期时
if (records.length < period) {
for (var i = 0 ; i < records.length ; i++) {
arrFish.push(0)
}
return arrFish
}
// 遍历K线
for (var i = 0 ; i < records.length ; i++) {
var fish = 0
var x = 0
var bar = records[i]
var mid = (bar.High + bar.Low) / 2
// 当前BAR不足period计算时
if (i < period - 1) {
fish = 0
preFish = 0
arrFish.push(fish)
continue
}
// 计算周期内最高价和最低价
var bars = []
for (var j = 0 ; j <= i ; j++) {
bars.push(records[j])
}
var lowestLow = getLowest(bars, period)
var highestHigh = getHighest(bars, period)
// 价变参数
x = ratio * 2 * ((mid - lowestLow) / (highestHigh - lowestLow) - 0.5) + (1 - ratio) * preX
if (x > 0.99) {
x = 0.999
} else if (x < -0.99) {
x = -0.999
}
preX = x
fish = 0.5 * Math.log((1 + x) / (1 - x)) + 0.5 * preFish
preFish = fish
arrFish.push(fish)
}
return arrFish
}
Desenhar no FMZ é muito simples, Strategy Square:https://www.fmz.com/squareHá muitos exemplos acima para referência ou pesquisa.
Devido ao tamanho do artigo, o código de teste de desenho a seguir precisa adicionar a implementação da função calcFisher acima antes de poder ser executado.
var cfg = { // 用来初始化设置图表的对象(即图表设置)
plotOptions: {
candlestick: {
color: '#d75442', // 颜色值
upColor: '#6ba583' // 颜色值
}
},
title: { text: 'Fisher Transform'}, //标题
subtitle: {text: ''}, //副标题
plotOptions: {
candlestick: {
tooltip: {
pointFormat:
'<span style="color:{point.color}">\u25CF</span> <b> {series.name}</b><br/>' +
'开盘: {point.open}<br/>' +
'最高: {point.high}<br/>' +
'最低: {point.low}<br/>' +
'收盘: {point.close}<br/>'
}
}
},
yAxis: [{
title: {
text: 'K线行情'
},
height: '70%',
lineWidth: 1
}, {
title: {
text: 'Fisher Transform'
},
top: '75%',
height: '30%',
offset: 0,
lineWidth: 1
}],
series: [//系列
{
type: 'candlestick',
yAxis: 0,
name: 'K线',
id: 'KLine',
// 控制走势为跌的蜡烛颜色
color: 'green',
lineColor: 'green',
// 控制走势为涨的蜡烛颜色
upColor: 'red',
upLineColor: 'red',
data: []
},{
type: 'line', // 设置当前的数据序列 类型为: 线
yAxis: 1, // 使用的y轴 为索引为 0 的y轴(highcharts 图表 可以有 多个 y 坐标轴,这里指定索引0的y轴)
showInLegend: true, //
name: 'fish', // 根据 函数传入的 参数 label 设置
lineWidth: 1,
data: [], // 数据序列的数据项
tooltip: { // 工具提示
valueDecimals: 2 // 值的小数点 保留5位
}
},{
type: 'line', // 设置当前的数据序列 类型为: 线
yAxis: 1, // 使用的y轴 为索引为 0 的y轴(highcharts 图表 可以有 多个 y 坐标轴,这里指定索引0的y轴)
showInLegend: true, //
name: 'preFish', // 根据 函数传入的 参数 label 设置
lineWidth: 1,
data: [], // 数据序列的数据项
tooltip: { // 工具提示
valueDecimals: 2 // 值的小数点 保留5位
}
}
]
}
var chart = Chart(cfg)
function main() {
var ts = 0
chart.reset()
while (true) {
var r = exchange.GetRecords()
var fisher = calcFisher(r, 0.33, 10)
if (!r || !fisher) {
Sleep(500)
continue
}
for (var i = 0; i < r.length; i++){
if (ts == r[i].Time) {
chart.add([0,[r[i].Time, r[i].Open, r[i].High, r[i].Low, r[i].Close], -1])
chart.add([1,[r[i].Time, fisher[i]], -1])
if (i - 1 >= 0) {
chart.add([2,[r[i].Time, fisher[i - 1]], -1])
}
}else if (ts < r[i].Time) {
chart.add([0,[r[i].Time, r[i].Open, r[i].High, r[i].Low, r[i].Close]])
chart.add([1,[r[i].Time, fisher[i]]])
if (i - 1 >= 0) {
chart.add([2,[r[i].Time, fisher[i - 1]]])
}
ts = r[i].Time
}
}
}
}

Portanto, é muito conveniente estudar dados, exibir gráficos e criar estratégias no FMZ. Este é apenas um ponto de partida, e professores e alunos podem deixar comentários.