Diário de aprendizagem de química quantitativa do inventor (a)

Autora:Sonhos pequenos, Criado: 2016-05-23 23:10:46, Atualizado: 2019-08-01 10:31:25

Antes, raramente escrevia um diário, agora sinto que preciso registrar algo todos os dias, não posso ver a luz do dia, certo?

Pergunta 1:

  • 1, A linha K do gráfico às vezes está faltando um BAR, está procurando por BUG. O problema foi encontrado, analisado e não recebeu dados quando foi testado com o disco analógico. No momento em que os dados são recebidos, já passaram dois BARs, então os dados mais recentes estão pintados no gráfico, resultando em um ou mais intervalos intermediários.
  • 2, corre por um tempo (ciclo da linha K de 1 minuto) sem problemas, tenta novamente (ciclo da linha K de 30 minutos) e surge um problema estranho:

TypeError: cannot read property length of null duk_hobject_props.c:2258 WToneAndWTtwo __FIL Este erro é reportado.

Veja abaixo o que deveria ser um erro na função WToneAndWTtwo, que lê o nome de um valor null chamado a propriedade length, ou seja, uma variável, como var name = null; então eu O nome.length foi lido, e então o código inteiro encontrou o local onde o nome deve ser chamado.

function isNullAndLog(arr,strArrName){//空数组报错
     if(!arr){
         Log("arr is:",arr,"name:",strArrName);
         return true;
      }
      return false;
}

Pense, oh! agora todas as variáveis usadas para o length eu coloco nesta função para testar, nenhum bug com null é absolutamente impossível de escapar. O teste de 30 minutos do K-Line, e depois de esfregar~~ outra vez:

TypeError: não pode ler a propriedade length de duk_hobject_props.c:2258 WToneAndWTtwoArquivoNão, não é.

O BTS não conseguiu entender!!! paciência! saia e dê uma volta e mude de ideias, ou talvez fique consciente! De volta, eu pensei se o banco de dados estava sendo chamado, o parâmetro de entrada era nulo, um erro ocorreu quando o banco de dados estava sendo executado.

function isNullAndLog(arr,strArrName){//空数组报错
    if(!arr){
        Log("arr is:",arr,"name:",strArrName);
        return true;
    }
    return false;
}

function main(){
   if(typeof(x) === undefined ){
       Log(typeof(x));
   }
    var aaa = null;
    Log(isNullAndLog(aaa));
    /*
    while(!aaa || aaa.length < 9){
        Log("while xunhuan");
        Sleep(5000 * 1000);
    } 
    */
    talib.EMA(aaa,5);
} 

Talib.EMA ((aaa,5); A chave para esta frase aaa é null, que eu definiu intencionalmente, e passei para ver o que acontece. O tipo de erro é TypeError: Cannot read property length of null ~~OK. Provavelmente é esse o problema, continue a modificar o código.

Pergunta 2:

A outra questão é que o que se pensava antes era gravar o código agora:

function DeleteNullEle(initArr){
    var dealArr = [];
    var initArrLen = initArr.length;
    for(var i = 0,j = 0 ; i < initArrLen ; i++,j++){
    //Log("initArr-",i,":",initArr[i]);//ceshi
    if(initArr[i] === null || isNaN(initArr[i]) ){
        j--;
        //Log("i:",i);//ceshi
        continue;
    }
        dealArr[j] = initArr[i];
    }
    //Log("dealArr:",dealArr);//ceshi
return dealArr;
}

A razão para adicionar esta função é que algumas matrizes são como [NaN, NaN, NaN, 22, 3, 56, 78, 4, 23], mas quando o inventor quantificou os testes usando a função Log, mostrou que era zero, o que significa que a função é zero. Deixe-me confuso por um longo tempo, buraco, tenho que lembrar, você vê que é null ou NaN, então julgar o null é impossível.
Outra coisa é que, se o aaa === null, por que não dá erro, porque a expressão para este operador é a seguinte: A expressão aaa é sempre verdadeira, então o aaa.length posterior pode não ter sido executado (apesar de ter sido visto quando aprendemos HTML, CSS, DOM, etc.) A partir de agora, o Google já está usando algumas das suas APIs.

Pergunta 3:

Em seguida, um grupo de amigos pediu para mudar o monitoramento de diferença, na verdade, adicionando um intervalo de diferença de detecção e o WeChat empurrou, muito simples.

 if (diff != __lastDiff) {
//--------------------------------------------------------------------------------------------
        if(openWeixin){
            if( (diff <= price1 || diff >= price2 ) && off_on === true ){
                Log("差价:"+diff+"微信推送@");
                off_on = false;
                Sleep(1000);
            }else{
                off_on = true;
                Sleep(1000);
                }
        }
//---------------------------------------------------------------------------------------------
        // add添加数据到series, 参数格式为[series序号, 数据];
        __chart.add([0, [new Date().getTime(), diff]]);
        __lastDiff = diff;
    }

img

O código que é adicionado entre as linhas vazias do código é muito simples e pode não ser perfeito.

Pergunta 4 (Não é uma questão, mas um pouco de aprendizado)

Hoje em dia, a estratégia de aprendizagem de futuros é muito mais complexa do que a do mercado de ações (graças a um modelo de negociação de futuros grande como o Z, ou escrever detalhes de negociação é suficiente para beber >____

  • exchange.GetPosition ((() // é usado para obter informações de posicionamento. Note que esta função retorna um conjunto de estruturas de posições, todas com informações específicas de posicionamento.
  • exchange.SetMarginLevel (MarginLevel) // Esta função é para definir a alavancagem. Parâmetros específicos MarginLevel seleção ((5 vezes? 10 vezes?)
  • exchange.SetDirection ((Direction) // Esta é uma API muito importante, que deve ser chamada antes do menu abaixo, porque apenas foram introduzidas quatro operações (vendendo e vendendo...), esta função é a que define essas operações (embora haja um pouco de conteúdo adicional), e o segundo parâmetro do CTP ainda não foi estudado.
  • exchange.SetContractType ((ContractType) // Antes da abertura e liquidação, um é para definir a direção do negócio (mais? vazio? plano?), o outro é para definir o contrato (marcado como açúcar branco? algodão?), então use esta função para definir o tipo do contrato. Os parâmetros são específicos em diferentes exchanges. Basicamente, essas funções também são usadas.
  • exchange.Buy ((() // comprar
  • exchange.Sell ((() // vender A seguir, veja o código do meu experimento, selecionando apenas uma seção (que pode ser copiada na função principal) e testando novamente se a troca testada é a troca de commodity futures:img
 if (!manager) {//Z大写的商品期货模板类库,用来管理交易的对象(manager 初始时null)。不明白的可以去看源代码,QQ群共享有注释版。
        if (_C(exchange.GetPosition).length > 0) {
            throw "策略启动前不能有持仓.";
        }
        Log('交易平台:', exchange.GetName(), _C(exchange.GetAccount));  //输出当前交易所 信息
        var insDetail = _C(exchange.SetContractType, ContractTypeName);  // 用容错函数 _C ,容错调用 SetContractType函数  首先明确 设置交易的合约类型。
        Log("合约", insDetail.InstrumentName, "一手", insDetail.VolumeMultiple, "份, 最大下单量", insDetail.MaxLimitOrderVolume, "保证金率:", insDetail.LongMarginRatio.toFixed(4), insDetail.ShortMarginRatio.toFixed(4), "交割日期", insDetail.StartDelivDate);
        // 上面这个Log 显示出合约的一些信息,注意 在回测的时候,与实际运行的结果不一样,可以看图杠杆都是null,保证金率都是0,可以试试看。
        manager = $.NewPositionManager();  // 这个生成管理者 对象
    }
    exchange.SetMarginLevel(10); //不支持       在这里我试着设置了一下杠杆试试,发现  显示 错误:Not support     ,CTP商品期货 应该不能自己调整杠杆
    var positions = exchange.GetPosition();     在所有的操作前 ,我试着调用了一下 GetPosition 函数  获取一下持仓信息,显示的null
    Log(positions[0]);
    exchange.SetDirection("buy"); // 在所有的操作前需要设置  操作方向  ,这里设置 买开仓(做多)。
    var id = exchange.Buy(1911,1); // 执行买入操作  下了一个  限价单,  有兴趣的同学 可以试试 市价单。(嘿嘿!自己动手记得牢)
    positions = _C(exchange.GetPosition); //再获取下 持仓信息 看看
    Log(positions);  //有持仓信息了,  在上面 Buy的时候  有兴趣的同学 试试 用低价格 买入。  Buy(1000,1) 看看。

Pergunta 5: Hoje, um amigo escreveu um código para a função Sleep (), com um erro muito grande, que afetou a política de alta frequência.

function main(){
    for(var i = 0 ; i < 10 ; i++){
        var b1 = 0;
        var b2 = 0;
        var b3 = 15;
        while(b1 < 200){
            var t2s1 = (new Date()).getTime();
            b1++;
            Sleep(b3);
            var t2s6 = (new Date()).getTime();
            b2 += (t2s6 - t2s1);
        }
        Log("Sleep()",b3,"MS",b1,"平均次数",b2/b1);
    }
    throw 2;
}

Eu fiz um teste e descobri que a função Sleep seria executada em um segundo (diferença de tempo antes e depois de 1000), então o erro de tempo do código do teste é grande, mas se for executado em simulação, basicamente é de menos de um milissegundo. Pode ser que o erro seja causado pelo sistema de teste pertencente ao modelo de caixa de areia e pelo algoritmo de tempo de execução no interior. A simulação tem um pequeno erro (diferença de 1 segundo).

Pergunta 6: Hoje de manhã, um amigo meu me disse que o administrador caiu à meia-noite e me enviou o log do sistema.

- Este é o diário.

runtime/cgo: pthread_create failed: Resource temporarily unavailable
SIGABRT: abort
PC=0x7f332c591cc9 m=2

goroutine 0 [idle]:

goroutine 1 [select, 207 minutes]:

A primeira linha mostra que o processo de geração de threads falhou e os recursos estão temporariamente indisponíveis (inadequados). A solução: 1, verifique se o código de política do robô está sendo executado, se os recursos usados não foram liberados, se há uma API que usa vários threads; 2, usando o comando ulimit para verificar as restrições do sistema em que o administrador está (Linux). Este blog pode ser visto em: (endereço do blog)http://smilejay.com/2012/04/fork_resource/Não. 3° - Cuidado com o uso da memória do sistema.

Usando ulimit -a para mostrar:img

Parâmetros do comando ulimit: -H define restrições de recursos. -S define restrições de recursos de software. -a mostra todas as restrições de recursos atuais. -c size: o valor máximo para definir o arquivo do núcleo. Unidade: blocos -d size: valor máximo para definir o segmento de dados. Unidade: kbytes -f size: definir o valor máximo para criar o arquivo. Unidade: blocos -l size: o valor máximo definido para bloquear o processo em memória. Unidade: kbytes -m size: o valor máximo de memória permanente que pode ser definido. Unidade: kbytes -n size: define o valor máximo dos descritores de ficheiros que podem ser abertos simultaneamente no núcleo. Unidade: n -p size: valor máximo para definir a área de buffer do canal. Unidade: kbytes -s size: valor máximo para definir a pilha. Unidade: kbytes -t size: limite máximo de tempo de uso do CPU. Unidade:seconds -v size: valor máximo para a memória virtual. Unidade: kbytes -u < Número de programas > Número máximo de programas que podem ser iniciados por um usuário

Um amigo que teve esse problema descobriu que a função de filtragem errada pode ser a causa do problema e encontrou o que causou o colapso do administrador (memória crescente). SetErrorFilter (( 502: 503: tcp character unexpected network timeout WSARecv Connect GetAddr no such reset httppreceived EOF reused ); Função de uso indevido, a função só precisa ser chamada uma vez e não pode ser escrita em uma estrutura de ciclo. O problema acima ( expansão contínua de memória) é que, como a função é escrita na função onTick, as chamadas contínuas de ciclo do onTick resultam em um colapso final.

Pergunta 7: Uma simples síntese das funções _C (((), _N (((), _G ((();

  • Função _C()

Explicação: Esta função é usada principalmente para API tolerantes a erros, como a função exchange.GetAccount ((), chamada assim: _C ((exchange.GetAccount); note que o nome da função não está entre parênteses, e se a função tolerante a erros requer o acréscimo de parâmetros, ela é escrita no segundo parâmetro da função _C(, em seguida, para trás. Use exemplos.

function main(){
    var account = null;
    var amount = 1;
    var price = 2000;
    account = exchange.GetAccount();
    Log("_C 函数使用前  account :",account);
    //exchange = null; 
    _C(exchange.Buy,price,amount);
    //exchange.Buy(price,1);
    account = exchange.GetAccount();
    Log("_C 函数使用后  account :",account);
}

A função_C deve parecer-se com:

 function ___C(functionName,p1){
    functionName("执行需要容错的函数,传入的测试参数为:",p1);
    Log("__C 容错函数启动,容错完毕");
}
function main(){
    pstr = "测试参数--hello";
    ___C(Log,pstr);
}

Resultados da execução:img

  • Função _N( Explicação: Esta função é usada para lidar com o excesso de dígitos pós-minúsculas, mantendo alguns dígitos mínimos. Exemplos de uso:
function main(){
    var pi = 3.1415926535897;
    Log("使用_N函数 前pi:",pi);
    var piOfDeal = _N(pi,2);
    Log("使用_N函数后 pi:",piOfDeal);
}

Resultados da execução:img

  • Função _G() Descrição: Esta é uma lista de dicionários globais que podem ser salvos com uma introdução na documentação API. Tabela KV, permanentemente armazenada em arquivos locais, com um banco de dados separado para cada robô, que permanece após o reinicio ou saída do administrador K deve ser escrito como um número ou uma string, independentemente do tamanho e da letra, e V pode ser escrito como qualquer coisa que possa ser serializada no JSON. _G ((num, 1); // define uma variável global num, com um valor de 1 _G ((num, ok); // Mudança de uma variável global num para ok _G ((num, null); // Elimina a variável global num _G ((num); // Retorna o valor da variável global num _G(); // Retorna o ID do bot atual _G(null); // Elimina todas as variáveis globais
function main(){
    Log("totalYLMoney 初始赋值 0");
    var totalYLMoney = 0;
    Log("totalYLMoney 已赋,  = ",totalYLMoney);
    if(typeof(_G("totalYLMoney_save")) !== "object"){
        totalYLMoney = _G("totalYLMoney_save"); 
        Log("读取 totalYLMoney 本地数据库 名称为totalYLMoney_save 的值 赋给 totalYLMoney ");
    }else{
        totalYLMoney = 100.12546328765458;
        _G("totalYLMoney_save",totalYLMoney.toString());
        Log("记录 totalYLMoney 保存到本地数据库");
    }
    Log("totalYLMoney",totalYLMoney);
    Log("typeof\(_G(\"totalYLMoney_save\"))",typeof(_G("totalYLMoney_save")));
}

O código de teste para a função _G ((() acima requer testes em robôs, e o retest não é suportado. O método de teste, se você implementar um programa no robô, na primeira vez que inicia o robô, o robô registrará 100.12546328765458; esse valor será registrado no dicionário global "totalYLMoney_save" e, novamente, você verá que o valor da variável totalYLMoney = 0, que, após a inicialização, ainda lê do dicionário o valor armazenado na primeira execução da política.

Pergunta 8: Uma pequena ideia sobre estratégias de lucro e prejuízo:

Muitas vezes, vemos novos alunos no grupo, perguntando sobre algoritmos de estratégia de ganho e perda. Em geral, há vários métodos de tratamento, aqui um pouco simples, as ideias também são fornecidas pelo grande deus do grupo, aqui eu sou responsável por explicar.

  • Os lucros flutuantes:

O lucro flutuante é: dividido por (dinheiro atual - dinheiro inicial) x preço atual + (dinheiro atual - dinheiro inicial)

Exemplo: Por exemplo, o preço inicial é de 10 dólares, a conta começa com 5 dólares, 100 dólares. Durante um período de tempo, eu comprei 3 moedas a um preço médio de 15 dólares. Ao final deste período, o preço da moeda sobe para 20 dólares. Neste momento, minha conta é de 8 dólares, 55 dólares. Profit = (8 - 5) * 20 + (55 - 100) = 60 + (-45) = 15 Este método de cálculo O lucro é de 15 yuans. (Nota: neste momento seu ganho é flutuante, porque se o preço da moeda cair muito neste momento, talvez você não só não tenha ganho, mas também perca dinheiro, claro que o seu ganho também flutuará, porque seu ganho neste momento segue o preço da moeda flutuando, a razão é fazer um desfalque muito plano, cair no saco) Além disso, se no momento em que o preço da moeda é de 20 yuan / a, o equilíbrio, ou seja, 20 dólares para vender 3 moedas compradas por 15 dólares, neste momento a conta é: 5 moedas, 115 moedas. Profit = (5 - 5) * 20 + (115 - 100) = 15, o ganho ainda é de 15 yuan, a diferença é que, se não considerarmos a depreciação inicial da moeda, o ganho não varia com o preço.

  • Lucro de conta:

O lucro da conta: (curso de moeda x preço atual + dinheiro atual) - (curso de moeda x preço inicial + dinheiro inicial)

Use também o exemplo acima: por exemplo, o preço inicial é de US$ 10 / moeda, a conta começa com 5 moedas, US$ 100. Durante um período de tempo, eu comprei 3 moedas a um preço médio de US$ 15 / moeda. Ao final deste período, o preço da moeda subiu para US$ 20 / moeda. Neste momento, a minha conta é: 8 moedas, US$ 55. Profit = (8 * 20 + 55) - (5 * 10 + 100) = 215 - 150 = 65 Este método de cálculo é o lucro de 65 dólares. Profit = (5 * 20 + 115) - (5 * 10 + 100) = 215 - 150 = 65 da mesma forma.

Comparando as duas formas acima, uma ganha 15 e outra ganha 65, não é difícil de ver. A primeira abordagem ignora os ganhos e perdas causados pela valorização do deprecio da moeda inicial. O segundo algoritmo calcula os ganhos e perdas incluindo os ganhos e perdas causados pela valorização do deprecio da moeda inicial. O cálculo do lucro da conta é usado para liquidar o dinheiro retirado. Os lucros flutuantes são aplicados aos lucros e perdas gerados por transações durante um período de tempo. Essas são algumas experiências de analise de sonhos pequenos, como erros, por favor deixe um apontamento correto, obrigado por antecedência ^-^

Pergunta 9: Um membro do grupo viu um plano de estado aberto e mostrou um formulário, então ele passou pela API abaixo e descobriu que parece ter sido adicionado um novo recurso, a função LogStatus na API. O membro do grupo queria que eu fizesse um teste, e eu também lembrei, por acaso, para facilitar a aprendizagem de novos alunos.

A primeira coisa a fazer é ver a API da plataforma:

LogStatus(Msg); //	此信息不保存到日志列表里, 只更新当前机器人的状态信息, 在日志上方显示, 可多次调用, 更新状态
LogStatus('这是一个普通的状态提示');
LogStatus('这是一个红色字体的状态提示 #ff0000');
LogStatus('这是一个多行的状态信息\n我是第二行');
var table = {type: 'table', title: '持仓信息', cols: ['列1', '列2'], rows: [ ['abc', 'def'], ['ABC', 'support color #ff0000']]};
LogStatus('`' + JSON.stringify(table)+'`'); // JSON序列化后两边加上`字符, 视为一个复杂消息格式(当前支持表格)
LogStatus('第一行消息\n`' + JSON.stringify(table)+'`\n第三行消息'); // 表格信息也可以在多行中出现
LogStatus('`' + JSON.stringify([table, table])+'`'); // 支持多个表格同时显示, 将以TAB显示到一组里

Código de teste:

function main(){
    var value1 = 99;
    var value2 ="ceshi 01";
    var table1 = { type : "table", title : "ceshi1", cols : ["列1","列2","列3"] , rows : [ ["abc","def","ghi"] , ["1","2","3"] ] };
    var table2 = { type : "table", title : "ceshi2", cols : ["列1","列2","列3"] , rows : [ ["abc",value1,"ghi"] , [value2,"2","3"] ] };
    LogStatus("测试文本1\n`" + JSON.stringify([table1,table2]) + "`");
}

imgO primeiro diagrama mostra que, dentro da tabela ceshi1, o formato de dados da tabela é var table1 e var table2, ambas variáveis declaradas. É importante notar que a função JSON.stringify (([table1, table2]) deve ser precedida pela função `. Caso contrário, a tabela não será exibida. É claro que nós devemos mostrar dados dinâmicos com tabelas, mas não sempre o conteúdo estático do texto. A table2 tem dois dados de teste, value1 e value2, dentro desta divisão.imgOs novos alunos podem copiar o código, experimentá-lo e modificá-lo sozinhos.

Pergunta 10: Um usuário que deseja um gráfico de retorno pode ter uma narrativa mais simples do que a narrativa do documento de API quantificado pelo inventor.

Para testar isso diretamente, eu usei um número aleatório para simular a variação dinâmica do rendimento para mostrar a curva de rendimento no gráfico.

var ChartObj = {//画图
    tooltip: {xDateFormat: '%Y-%m-%d %H:%M:%S, %A',enabled:true,valueDecimals:2,valueSuffix:'%'}, //提示框  就是鼠标在线上时 显示的一个 框框 里面有一些内容,这里是设置提示框的格式
    chart: { zoomType:'x',panning:true },//图表缩放  
    title: { text: '收益率 %'}, //标题
    rangeSelector: { //范围 区域 选择 
            buttons:  [{type: 'hour',count: 1, text: '1h'}, {type: 'hour',count: 3, text: '3h'}, {type: 'hour', count: 8, text: '8h'}, {type: 'all',text: 'All'}],
            selected: 0,
            inputEnabled: false
        },
    subtitle: {text: " 显示瞬时收益率 % "},//副标题
    xAxis:{type: 'datetime'}, //设置 X轴  的数值为时间类型
    yAxis: [{
            title: {text: '收益率 %'},//标题
            style: {color: '#4572A7'},//样式 
            //opposite: false  //生成右边Y轴
        }
    ],
    series: [//系列
        {name:'收益率',dataLables:{enabled:true,format:'{y} %'},type:'spline',yAxis:0,data:[]} //该图标只用到一条曲线  ,所以 只用设置一个数据序列
        ]                  
};
var chart = Chart(ChartObj);  //初始化

function main(){ //测试用的主函数
    chart.update(ChartObj); //更新
    chart.reset(); //清空图表
    var i = 0; //初始一个 i 值 , 后面循环用,   用来限制循环次数
    var randomNum = 0; //声明一个  随机数 初始化 0
    while(i < 5000){ //限制循环次数
        randomNum = Math.random() * 10;  // 生产随机数 0  -  9.9999
        //chart.add([0,[(new Date()),randomNum]]);
        chart.add(0,[(new Date()).getTime(),randomNum + 5]);  //把生成的随机数  按照时间(X 坐标)     把随机数 画在图表上(Y坐标)     
        Sleep(1000*60); // 程序 每次循环暂停60秒
        //chart.update(ChartObj);
        //chart.reset(500);
    }
    Log("over");
}
  • Um problema aqui me deixou confuso durante meio dia, e também registrado. Quando escrevi o tempo, ele tinha que ser de milissegundos, assim: new Date (().getTime (() Este é o milissegundos, se for assim new Date (()) então há um pequeno problema, como o tempo, e a escalação do eixo X não pode ser usada. Também há uma ferramenta: {xDateFormat: %Y-%m-%d %H:%M:%S, %A, enabled:true,valueDecimals:2,valueSuffix:%}, esta configuração é vista no consultório.

Mais.

LiuxinghuiMinha filha, por favor, diga-me como fazer para cancelar todos os pedidos que não foram concluídos depois de fazer o pedido.

Louis?Este deve ser um elogio!

Chuva terrívelO que é bom... muitas coisas que a documentação da API não diz.

Aí está o outono.O que é bom que a Shirin tem organizado?

A estratégia de venda de preços elevadosÉ bom!

Sonhos pequenosSeja simpático. https://dn-filebox.qbox.me/bf52888dc68aba5326c403f2280994e81fbce2ee.png Os tutoriais estão disponíveis em: https://www.botvs.com/bbs-topic/475

Sonhos pequenosÉ fácil de aprender!