Monday 12 March 2018

Máquina de estado finito do sistema de negociação


Paul Lam.


Impacto social de engenharia.


Impacto social de engenharia.


Máquina de estado finito orientada a eventos para um sistema de comércio distribuído.


Um problema que eu tive ao construir meu sistema de comércio distribuído é gerenciar estados de forma assíncrona de múltiplos desencadeantes. Por exemplo, quando o motor alfa diz comprar, ele precisa de confirmação do motor de posição para ver se é seguro entrar em uma nova posição. Eu poderia encadear um cheque após outro de forma imperativa ou através de retorno de chamada. No entanto, a restrição subjacente é que estes desencadeiam:


são intensivos em recursos para gerar, talvez precisem compor muitos deles, não seqüenciais ou têm uma dependência individual, e, o mais importante, estão em programas separados ou em máquinas diferentes.


Assim, optei por abstrair esse problema em seu próprio módulo do sistema como uma máquina de estados finitos (FSM) dirigida a eventos para acompanhar transições de estado. Termo de intimidação, mas minha primeira implementação foi apenas declarações if-else para se qualificar como tal. O benefício é que cada um dos componentes do meu sistema só precisa empurrar sinais e extrair estados de uma interface central sem ter que se preocupar com o que deveria chamar a seguir ou pesquisar qualquer outra coisa para ver se as estrelas estão alinhadas. Isso simplificou drasticamente o desenvolvimento e a manutenção.


As responsabilidades do meu módulo FSM são:


ouça todos os sinais, descubra todas as transições e publique os estados mais recentes para o resto do sistema.


Manipulação de eventos assíncronos.


Eu uso RabbitMQ como a camada de transporte de mensagens entre os módulos do meu sistema. Tudo o que preciso fazer aqui é associar um manipulador de mensagens apropriado a cada entrada de disparo para o FSM. Aqui está um exemplo dos manipuladores de eventos usando a biblioteca Clojure RabbitMQ, Langohr. O resto desta parte é apenas o padrão RabbitMQ publicar / inscrever-se.


Isso é chamado quando um evento de posição é recebido com informações como usuário, instrumento e quantidade. Este manipulador iria encaminhar essas informações buscando estados atuais para esse usuário, avaliando o próximo estado com entrada e, em seguida, armazene os novos estados para o usuário.


Transições do estado.


Abaixo está um dos diagramas de transição de estado do meu sistema.


Existem 4 estados representados por 4 cores com 4 estados de sinalização de transição de estado. Espera-se que o programa atenda até centenas de estados independentes simultaneamente com os disparadores de eventos que chegam em algumas ocasiões por segundo.


Como eu dizia, minha primeira implementação é apenas um conjunto de métodos if-else. Por exemplo, um gatilho de engate chamaria o método envolvente para determinar o próximo estado, dado o envolvimento implícito e o estado atual.


Havia um punhado desse código de referência. Então, depois de implantar o sistema, voltei a refatorá-los. Eu tenho significado dar uma experiência no core. logic por um tempo, então isso parece ser um bom lugar para começar a usá-lo.


Antes de podermos perguntar a questão do solucionador de lógica, precisamos definir as relações. Aqui eu defino uma relação de transição para especificar toda a definição de transição de estado convenientemente em um só lugar.


E os métodos do manipulador de eventos são apenas invólucros para uma expressão de lógica de um verso, perguntando a pergunta - dado o estágio atual, cur-state e a entrada de entrada, entrada, que estado pode tomar para satisfazer essa restrição?


Não é o exemplo core. logic mais ilustrativo, mas faz o trabalho.


Começar com o core. logic é surpreendentemente fácil. Eu passei pelo Primer e tutorial e consegui isso trabalhando em uma tentativa.


Armazenamento em cache e compartilhamento de estado.


Agora que a transição do estado foi atendida, os estados são armazenados em cache e são atendidos no Redis para outras partes do sistema. Eu uso o Redis para isso porque é rápido e fácil. Os valores são armazenados em formato edn em vez de algo mais popular como o JSON para manter a estrutura de dados através do fio.


Esta é a minha primeira vez usando o edn em produção. Todas as mensagens interprocessamento neste sistema comercial são formatadas em formato edn. Funciona perfeitamente com Clojure simplesmente usando str para escrever e clojure. edn / read-string para ler. Além dos meus outros componentes do Clojure no sistema, minha interface do corretor comercial está escrita em Java. O meu programa Java usa o edn-java para analisar e desproporcionar estruturas complexas de dados Clojure (por exemplo, mapas aninhados com palavras-chave).


Eu acho que o acoplamento edn com a Redis é uma escolha fantástica, pois é quase como trabalhar com as estruturas de dados de concorrência originais de Clojure, como átomo, mas também permitir que programas externos acessem os dados.


Simples e rápidos.


Todo o programa FSM dirigido por eventos é inferior a 200 linhas do código Clojure e não levou mais do que algumas horas para fazer. No entanto, fiz alguns momentos de reflexão por alguns dias. Não fiz qualquer referência para estimar o resultado do desempenho. Então, tudo o que posso dizer é que esta configuração pode lidar com meu caso de uso simplista com quase nenhuma carga no servidor, então eu estou feliz com isso.


Alguns anos atrás, eu teria definido um monte de bandeiras para mudar estados. Na verdade, é isso que eu fiz. A maior satisfação aqui para mim não é a implementação ou tecnologias, é ver através do problema subjacente em questão e resolvê-lo com um padrão comum que tornou meu trabalho mais simples.


Aprenda-lhe alguns Erlang.


Rage Against The Finite-State Machines.


O que eles são?


Uma máquina de estados finitos (FSM) não é realmente uma máquina, mas tem um número finito de estados. Eu sempre encontrei máquinas de estados finitos mais fáceis de entender com gráficos e diagramas. Por exemplo, o seguinte seria um diagrama simplista para um cão (muito burro) como uma máquina de estado:


Aqui, o cão tem 3 estados: sentado, latindo ou abanando a cauda. Diferentes eventos ou entradas podem forçá-lo a mudar seu estado. Se um cão está calmamente sentado e vê um esquilo, ele começará a latir e não vai parar até você acariciá-lo de novo. No entanto, se o cão estiver sentado e você pet, não temos idéia do que pode acontecer. No mundo de Erlang, o cão pode entrar em colisão (e, eventualmente, ser reiniciado por seu supervisor). No mundo real, seria um evento estranho, mas seu cão voltaria depois de ser atropelado por um carro, então não é tudo ruim.


Aqui está o diagrama de estado de um gato para uma comparação:


Este gato tem um único estado, e nenhum evento pode alterá-lo.


Implementar a máquina de estado de gato em Erlang é uma tarefa divertida e simples:


Podemos tentar o módulo para ver que o gato realmente nunca dá uma porcaria:


O mesmo pode ser feito para o cão FSM, exceto que mais estados estão disponíveis:


Deve ser relativamente simples combinar cada um dos estados e as transições para o que estava no diagrama acima. Aqui está o FSM em uso:


Você pode acompanhar o esquema se quiser (eu costumo fazer, ajuda a ter certeza de que nada está errado).


Esse é realmente o núcleo dos FSMs implementados como processos Erlang. Há coisas que poderiam ter sido feitas de forma diferente: poderíamos ter estado passado nos argumentos das funções do estado de forma semelhante ao que fazemos com o loop principal dos servidores. Também poderíamos ter adicionado funções de inicialização e término, manipulações de código, etc.


Outra diferença entre o cão eo gato FSMs é que os eventos do gato são síncronos e os eventos do cão são assíncronos. Em um FSM real, ambos poderiam ser usados ​​de forma mista, mas eu fui para a representação mais simples da pura preguiça inexplorada. Existem outras formas de evento que os exemplos não mostram: eventos globais que podem acontecer em qualquer estado.


Um exemplo de tal evento pode ser quando o cão recebe um cheiro de comida. Uma vez que o evento de comida de cheiro é desencadeado, não importa o estado em que o cão está, ele iria procurar a fonte de alimento.


Agora, não vamos gastar muito tempo implementando tudo isso em nosso FSM 'escrito em um guardanapo'. Em vez disso, nos moveremos diretamente para o comportamento gen_fsm.


Máquinas genéricas de finito-estado.


O comportamento gen_fsm é algo semelhante ao gen_server na medida em que é uma versão especializada dele. A maior diferença é que, ao invés de lidar com chamadas e lançamentos, estamos lidando com eventos síncronos e assíncronos. Como nos exemplos de cães e gatos, cada estado é representado por uma função. Novamente, passaremos pelas devoluções de chamada que nossos módulos precisam implementar para funcionar.


Este é o mesmo init / 1 usado para servidores genéricos, exceto os valores de retorno aceitos são, e. A ups da parada funciona da mesma maneira que para o gen_server s, e hibernar e Timeout mantêm a mesma semântica.


O que há de novo é a variável StateName. StateName é um átomo e representa a próxima função de retorno de chamada a ser chamada.


As funções StateName / 2 e StateName / 3 são nomes de espaço reservado e você deve decidir o que serão. Vamos supor que a função init / 1 retorna a tupla. Isso significa que a máquina de estados finitos ficará sentada. Este não é o mesmo tipo de estado que vimos com o gen_server; é bastante equivalente aos estados de sentar-se, cascarão e wag_tail do anterior cão FSM. Esses estados determinam um contexto em que você lida com um determinado evento.


Um exemplo disso seria alguém que o chamasse no seu telefone. Se você estiver no estado "dormindo em uma manhã de sábado", sua reação pode ser gritar no telefone. Se o seu estado está "esperando uma entrevista de emprego", é provável que você escolha o telefone e responda educadamente. Por outro lado, se você estiver no estado 'morto', então estou surpreso por você mesmo ler esse texto.


De volta ao nosso FSM. A função init / 1 disse que devemos estar no estado sentado. Sempre que o processo gen_fsm recebe um evento, será chamada a função sentada / 2 ou a sessão / 3. A função assento / 2 é chamada para eventos assíncronos e sessão / 3 para sincronizados.


Os argumentos para sentar / 2 (ou geralmente StateName / 2) são Evento, a mensagem real enviada como um evento e StateData, os dados que foram transferidos para as chamadas. sentado / 2 pode então retornar as tuplas, e.


Os argumentos para sentar / 3 são semelhantes, exceto que existe uma variável De entre o evento e StateData. A variável From é usada exatamente da mesma maneira que foi para gen_server s, incluindo gen_fsm: reply / 2. As funções StateName / 3 podem retornar as seguintes tuplas:


Observe que não há limite em quantas dessas funções você pode ter, desde que sejam exportadas. Os átomos retornados como NextStateName nas tuplas determinarão se a função será chamada ou não.


handle_event.


Na última seção, mencionei eventos globais que desencadeariam uma reação específica, independentemente do estado em que estivéssemos (o alimento de cheiro de cachorro vai soltar o que quer que esteja fazendo e, em vez disso, buscará comida). Para esses eventos que devem ser tratados da mesma maneira em todos os estados, o retorno de chamada handle_event / 3 é o que deseja. A função leva argumentos semelhantes a StateName / 2 com a exceção de que ele aceita uma variável StateName entre eles, informando qual o estado quando o evento foi recebido. Ele retorna os mesmos valores que StateName / 2.


handle_sync_event.


O retorno de chamada handle_sync_event / 4 é para StateName / 3 que handle_event / 2 é para StateName / 2. Ele lida com eventos globais síncronos, leva os mesmos parâmetros e retorna o mesmo tipo de tuplas que StateName / 3.


Agora, pode ser um bom momento para explicar como sabemos se um evento é global ou se pretende ser enviado para um estado específico. Para determinar isso, podemos observar a função usada para enviar um evento para o FSM. Os eventos assíncronos destinados a qualquer função StateName / 2 são enviados com send_event / 2, os eventos síncronos a serem capturados pelo StateName / 3 devem ser enviados com sync_send_event / 2-3.


As duas funções equivalentes para eventos globais são send_all_state_event / 2 e sync_send_all_state_event / 2-3 (um nome bastante longo).


code_change.


Isso funciona exatamente o mesmo que para o gen_server s, exceto que é necessário um parâmetro de estado extra quando chamado como code_change (OldVersion, StateName, Data, Extra) e retorna uma tupla do formulário.


Isso deve, novamente, agir um pouco como o que temos para servidores genéricos. terminar / 3 deve fazer o oposto do init / 1.


Uma especificação do sistema de negociação.


É hora de colocar tudo isso em prática. Muitos tutoriais Erlang sobre máquinas finitas utilizam exemplos que contêm interruptores telefônicos e coisas similares. É meu palpite que a maioria dos programadores raramente terá que lidar com telefones para máquinas de estado. Por isso, vamos olhar para um exemplo mais apropriado para muitos desenvolvedores: vamos projetar e implementar um sistema de negociação de itens para alguns jogos de vídeo fictícios e não-existentes.


O design que escolhi é um pouco desafiador. Ao invés de usar um corretor através do qual os jogadores rodam itens e confirmações (o que, francamente, seria mais fácil), vamos implementar um servidor onde ambos os jogadores se falam diretamente (o que teria a vantagem de ser distribuível).


Porque a implementação é complicada, vou passar um bom tempo ao descrevê-lo, o tipo de problemas a serem enfrentados e as formas de corrigi-los.


Em primeiro lugar, devemos definir as ações que podem ser feitas pelos nossos jogadores ao negociar. O primeiro está pedindo a criação de um comércio. O outro usuário também deve ser capaz de aceitar esse comércio. Não vamos dar-lhes o direito de negar um comércio, no entanto, porque queremos manter as coisas simples. Serão fáceis de adicionar esse recurso uma vez que tudo for feito.


Uma vez que o comércio é configurado, nossos usuários devem ser capazes de negociar uns com os outros. Isso significa que eles devem ser capazes de fazer ofertas e depois retraí-las se quiserem. Quando ambos os jogadores estão satisfeitos com a oferta, eles podem se declarar todos prontos para finalizar o comércio. Os dados devem então ser guardados em algum lugar dos dois lados. Em qualquer momento, também deve ter sentido para qualquer um dos jogadores cancelar todo o comércio. Alguns pleb poderiam oferecer apenas itens considerados indignos para a outra parte (quem pode estar muito ocupado) e, portanto, deveria ser possível revistá-los com um merecido cancelamento.


Em suma, as seguintes ações devem ser possíveis:


pedir um comércio aceitar uma oferta comercial itens retrair uma oferta declarar-se como pronto cancelar brutalmente o comércio.


Agora, quando cada uma dessas ações é tomada, o FSM do outro jogador deve ser informado. Isso faz sentido, porque quando Jim conta ao FSM para enviar um item para o Carl, o FSM da Carl deve ser informado disso. Isso significa que ambos os jogadores podem conversar com seus próprios FSM, que falarão com o FSM do outro. Isso nos dá algo assim:


A primeira coisa a notar quando temos dois processos idênticos que se comunicam entre si é que devemos evitar chamadas síncrona tanto quanto possível. A razão para isso é que se o FSM de Jim envia uma mensagem para o FSM de Carl e então espera sua resposta enquanto, ao mesmo tempo, o FSM de Carl envia uma mensagem para o FSM de Jim e aguarda sua própria resposta específica, ambos acabam esperando o outro sem responder nunca. Isso efetivamente congela ambos os EFMs. Temos um impasse.


Uma solução para isso é aguardar um tempo limite e, em seguida, seguir em frente, mas haverá sobras de mensagens nas caixas de correio de ambos os processos e o protocolo será desarrumado. Isso certamente é uma lata de vermes, e então queremos evitá-lo.


A maneira mais simples de fazê-lo é evitar todas as mensagens síncronas e ficar totalmente assíncrono. Note que Jim ainda pode fazer uma chamada síncrona para o seu próprio FSM; não há risco aqui porque o FSM não precisará chamar Jim e, portanto, não pode ocorrer nenhum impasse entre eles.


Quando dois desses FSMs se comunicam entre si, toda a troca pode parecer um pouco assim:


Ambos os FSM estão em estado ocioso. Quando você pede que o Jim troque, Jim tem que aceitar antes que as coisas mudem. Então, ambos podem oferecer itens ou retirá-los. Quando você está se declarando preparado, o comércio pode ocorrer. Esta é uma versão simplificada de tudo o que pode acontecer e veremos todos os casos possíveis com mais detalhes nos próximos parágrafos.


Aqui vem a parte difícil: definir o diagrama de estado e como as transições de estados acontecem. Normalmente, um bom pensamento reflete isso, porque você tem que pensar em todas as pequenas coisas que podem dar errado. Algumas coisas podem dar errado, mesmo depois de terem sido revisadas muitas vezes. Por isso, vou simplesmente colocar o que eu decidi implementar aqui e depois explicá-lo.


Em primeiro lugar, ambas as máquinas de estado finito começam no estado ocioso. Neste ponto, uma coisa que podemos fazer é pedir a algum outro jogador para negociar conosco:


Nós entramos no modo idle_wait para aguardar uma eventual resposta após o FSM encaminhar a demanda. Uma vez que o outro FSM envia a resposta, o nosso pode mudar para negociar:


O outro jogador também deve estar em negociação depois disso. Obviamente, se pudermos convidar o outro, o outro pode nos convidar. Se tudo correr bem, isso deve acabar ficando assim:


Então, isso é praticamente o oposto, como os dois diagramas de estados anteriores empacotados em um. Note que esperamos que o jogador aceite a oferta neste caso. O que acontece se, por pura sorte, pedimos ao outro jogador trocar conosco, ao mesmo tempo em que nos pede que troquemos?


O que acontece aqui é que ambos os clientes perguntam ao seu próprio FSM para negociar com o outro. Assim que as mensagens de negociação for enviada, ambos os FSMs mudam para o estado idle_wait. Então eles serão capazes de processar a questão da negociação. Se analisarmos os diagramas de estados anteriores, vemos que essa combinação de eventos é a única vez que receberemos pergunte negociar mensagens enquanto estiver no estado idle_wait. Consequentemente, sabemos que obter essas mensagens em idle_wait significa que atingimos a condição de corrida e podemos assumir que ambos os usuários querem conversar um com o outro. Podemos mover os dois para negociar o estado. Hooray.


Então, agora estamos negociando. De acordo com a lista de ações que listei anteriormente, devemos apoiar os usuários que oferecem itens e depois retrair a oferta:


Tudo isso faz é encaminhar a mensagem do nosso cliente para o outro FSM. As duas máquinas de estados finitos precisarão manter uma lista de itens oferecidos por qualquer jogador, para que eles possam atualizar essa lista ao receber essas mensagens. Nós ficamos no estado de negociação depois disso; talvez o outro jogador também ofereça itens:


Aqui, nosso FSM basicamente age de forma semelhante. Isto é normal. Uma vez que nos cansamos de oferecer coisas e achamos que somos generosos o suficiente, temos que dizer que estamos prontos para oficializar o comércio. Como temos que sincronizar ambos os jogadores, teremos que usar um estado intermediário, como fizemos para ocioso e idle_wait:


O que fazemos aqui é que, assim que nosso jogador estiver pronto, nosso FSM pede o FSM de Jim se ele estiver pronto. Enquanto aguarda a resposta, nosso próprio FSM cai no seu estado de espera. A resposta que receberemos dependerá do estado do FSM de Jim: se estiver em espera, ele nos informará que está pronto. Caso contrário, ele vai nos dizer que ainda não está pronto. É exatamente isso que nosso FSM responde automaticamente a Jim, se ele nos perguntar se estamos prontos quando estamos no estado de negociação:


Nossa máquina de estado finito permanecerá no modo de negociação até que nosso jogador diga que está pronto. Vamos assumir que ele fez e estamos agora no estado de espera. No entanto, Jim ainda não está. Isso significa que, quando nos declararmos como prontos, teremos perguntado a Jim se ele também estava pronto e seu FSM terá respondido "ainda não":


Ele não está pronto, mas nós somos. Não podemos fazer muito, mas continuar aguardando. Enquanto espera por Jim, que ainda está negociando, é possível que ele tente nos enviar mais itens ou talvez cancele suas ofertas anteriores:


Claro, queremos evitar Jim removendo todos os seus itens e depois clicando em "Estou pronto!", Nos aparecendo no processo. Assim que ele muda os itens oferecidos, voltamos para negociar o estado para que possamos modificar nossa própria oferta, ou examinar a atual e decidir que estamos prontos. Enxague e repita.


Em algum momento, Jim estará pronto para finalizar o comércio também. Quando isso acontece, sua máquina de estados finitos perguntará a nós se estivermos prontos:


O que o FSM faz é responder que estamos realmente prontos. Nós ficamos no estado de espera e nos recusamos a mudar para o estado pronto. Por que é isso? Porque existe uma condição de corrida potencial! Imagine que a seguinte sequência de eventos ocorre, sem fazer este passo necessário:


Isso é um pouco complexo, então vou explicar. Por causa da maneira como as mensagens são recebidas, possamos apenas processar a oferta do item depois de nos declararmos prontos e também depois que Jim se declarou pronto. Isso significa que assim que lemos a mensagem da oferta, voltamos para negociar o estado. Durante esse tempo, Jim nos contará que está pronto. Se ele mudasse os estados ali mesmo e se movesse para pronto (como ilustrado acima), ele seria pego esperando indefinidamente enquanto não saberíamos o que diabos fazer. Isso também pode acontecer ao contrário Ugh.


Uma maneira de resolver isso é adicionando uma camada de indireção (Obrigado a David Wheeler). É por isso que ficamos no modo de espera e enviamos 'pronto!' (como mostrado em nosso diagrama de estado anterior). Veja como lidamos com isso "pronto". mensagem, supondo que já estávamos no estado pronto porque dissemos ao nosso FSM que estávamos preparados de antemão:


Quando recebemos 'pronto!' dos outros FSM, enviamos 'pronto!' de volta. Isto é para se certificar de que não teremos a "condição de corrida dupla" mencionada acima. Isso criará um "pronto" supérfluo! mensagem em um dos dois FSMs, mas teremos que ignorá-lo neste caso. Em seguida, enviamos uma mensagem "ack" (e o FSM do Jim fará o mesmo) antes de mudar para o estado pronto. A razão pela qual essa mensagem 'ack' existe é devido a alguns detalhes de implementação sobre sincronização de clientes. Coloquei o diagrama por razões de correção, mas não vou explicar isso até mais tarde. Esqueça disso por enquanto. Finalmente conseguimos sincronizar ambos os jogadores. Whew.


Então agora está o estado pronto. Este é um pouco especial. Ambos os jogadores estão prontos e, basicamente, têm dado às máquinas finitas todo o controle de que precisam. Isso nos permite implementar uma versão bastardizada de um compromisso de duas fases para garantir que as coisas funcionem bem ao fazer o funcionário oficial:


Nossa versão (como descrito acima) será bastante simplista. Escrever um commit de duas fases verdadeiramente correto exigiria muito mais código do que o que é necessário para que possamos entender as máquinas de estados finitos.


Finalmente, só temos que permitir que o comércio seja cancelado a qualquer momento. Isso significa que, de alguma forma, independentemente do estado em que estejamos, vamos ouvir a mensagem "cancelar" dos dois lados e sair da transação. Também deve ser uma cortesia comum para que o outro lado saiba que nos foi antes de partir.


Bem! É uma grande quantidade de informações para absorver de uma só vez. Não se preocupe se demorar um pouco para compreendê-lo completamente. Levou um monte de pessoas para examinar meu protocolo para ver se estava certo e, mesmo assim, todos nós perdemos algumas condições de corrida que eu peguei alguns dias depois ao revisar o código ao escrever este texto. É normal ter que lê-lo mais de uma vez, especialmente se você não está acostumado a protocolos assíncronos. Se for esse o caso, eu encorajo você a tentar projetar seu próprio protocolo. Então, pergunte-se "o que acontece se duas pessoas fizerem as mesmas ações de forma muito rápida? E se encadearem outros dois eventos rapidamente? O que eu faço com as mensagens que eu não lido quando mudo estados?" Você verá que a complexidade cresce muito rápido. Você pode encontrar uma solução semelhante à minha, possivelmente melhor (deixe-me saber se este é o caso!) Não importa o resultado, é uma coisa muito interessante para trabalhar e nossos FSMs ainda são relativamente simples.


Depois de ter digerido tudo isso (ou antes, se você é um leitor rebelde), você pode ir para a próxima seção, onde implementamos o sistema de jogos. Por enquanto, você pode fazer uma boa pausa para o café se você quiser fazê-lo.


Negociação de jogos entre dois jogadores.


A primeira coisa que precisa ser feita para implementar nosso protocolo com o gen_fsm da OTP é criar a interface. Haverá 3 chamadores para o nosso módulo: o jogador, o comportamento gen_fsm e o FSM do outro jogador. Só precisamos exportar a função do jogador e as funções gen_fsm. Isso ocorre porque o outro FSM também será executado dentro do módulo trade_fsm e pode acessá-los de dentro:


Então essa é a nossa API. Você pode ver que estou planejando que algumas funções sejam síncronas e assíncronas. Isso é principalmente porque queremos que nosso cliente nos ligue de forma síncrona em alguns casos, mas o outro FSM pode fazê-lo de forma assíncrona. Ter o cliente síncrono simplifica muito nossa lógica, limitando o número de mensagens contraditórias que podem ser enviadas uma após a outra. Vamos lá. Vamos primeiro implementar a API pública real de acordo com o protocolo definido acima:


Isso é bastante padrão; Todas estas funções 'gen_fsm' foram cobertas antes (exceto start / 3-4 e start_link / 3-4 que eu acredito que você pode descobrir) neste capítulo.


Em seguida, implementaremos as funções FSM para FSM. Os primeiros têm a ver com as configurações de comércio, quando queremos primeiro pedir ao outro usuário que se junte a nós em um comércio:


A primeira função pede ao outro pid se eles querem trocar, e o segundo é usado para responder (de forma assíncrona, é claro).


Podemos então escrever as funções para oferecer e cancelar ofertas. De acordo com o nosso protocolo acima, é como eles deveriam ser:


Então, agora que temos essas chamadas feitas, precisamos nos concentrar no resto. As chamadas restantes dizem respeito a estarem prontas ou não e ao tratamento da confirmação final. Novamente, dado nosso protocolo acima, temos três chamadas: are_you_ready, que pode ter as respostas não_yet ou pronto! :


As únicas funções restantes são aquelas que devem ser usadas por ambos os FSMs ao fazer o commit no estado pronto. Seu uso preciso será descrito mais detalhadamente mais adiante, mas, por enquanto, os nomes e o diagrama de seqüência / estado anteriores devem ser suficientes. No entanto, você ainda pode transcrevê-los para sua própria versão do trade_fsm:


Ah, e também há a função de cortesia que nos permite avisar o outro FSM que cancelamos o comércio:


Agora podemos mudar para a parte realmente interessante: as devoluções de retorno gen_fsm. O primeiro retorno de chamada é init / 1. No nosso caso, queremos que cada FSM segure um nome para o usuário que representa (dessa forma, nossa saída será mais agradável) nos dados que ele continua transmitindo para si próprio. O que mais queremos manter na memória? No nosso caso, queremos o pid do outro, os itens que oferecemos e os itens que o outro oferece. Nós também vamos adicionar a referência de um monitor (então sabemos que abortar se o outro morre) e um de campo, costumavam fazer respostas atrasadas:


No caso do init / 1, só nos importaremos com o nosso nome por agora. Observe que vamos começar no estado ocioso:


As próximas devoluções a serem consideradas seriam os próprios estados. Até agora descrevi as transições de estado e as chamadas que podem ser feitas, mas precisamos de uma maneira de garantir que tudo esteja bem. Em primeiro lugar, escreveremos algumas funções de utilidade:


E podemos começar com o estado ocioso. Por uma questão de convenção, abordarei a versão assíncrona primeiro. Este não precisa se preocupar com nada, exceto o outro jogador que pede uma troca com o nosso próprio jogador, se você olhar para as funções da API, usará uma chamada síncrona:


Um monitor é configurado para nos permitir lidar com o outro morrendo, e sua referência é armazenada nos dados do FSM junto com o pid do outro, antes de passar para o estado idle_wait. Tenha em atenção que informaremos todos os eventos inesperados e ignorá-los ao permanecer no estado em que já estávamos. Podemos ter algumas mensagens fora da banda aqui e ali que poderiam ser o resultado de condições de corrida. Geralmente é seguro ignorá-los, mas não podemos facilmente livrar-se deles. É melhor não bater todo o FSM nestas mensagens desconhecidas, mas um pouco esperadas.


Quando nosso próprio cliente solicita ao FSM que entre em contato com outro jogador para um comércio, ele enviará um evento síncrono. O retorno de marcha lenta / inactiva será necessário:


Procedemos de forma semelhante à versão assíncrona, exceto que precisamos realmente perguntar ao outro lado se eles querem negociar conosco ou não. Você notará que ainda não respondemos ao cliente. Isso porque não temos nada de interessante para dizer, e queremos que o cliente fique trancado e aguarde que o comércio seja aceito antes de fazer qualquer coisa. A resposta só será enviada se o outro lado aceitar uma vez que estamos em idle_wait.


Quando estamos lá, temos que lidar com a outra aceitar negociar e a outra pedindo para negociar (o resultado de uma condição de corrida, conforme descrito no protocolo):


Isso nos dá duas transições para o estado de negociação, mas lembre-se de que devemos usar o gen_fsm: responda / 2 responda ao nosso cliente para dizer que está certo começar a oferecer itens. Há também o caso do cliente do nosso FSM aceitar o comércio sugerido pela outra parte:


Mais uma vez, este avança para o estado de negociação. Aqui, devemos lidar com consultas assíncronas para adicionar e remover itens provenientes tanto do cliente quanto do outro FSM. No entanto, ainda não decidimos como armazenar itens. Porque eu sou um pouco preguiçoso e suponho que os usuários não troquem esses itens, listas simples irão fazê-lo por enquanto. No entanto, podemos mudar de idéia em um ponto posterior, por isso seria uma boa idéia para embrulhar operações de itens em suas próprias funções. Adicione as seguintes funções na parte inferior do arquivo com aviso / 3 e inesperado / 2:


Simples, mas eles têm o papel de isolar as ações (adicionar e remover itens) de sua implementação (usando listas). Poderíamos facilmente mudar para proplistas, arrays ou qualquer outra estrutura de dados sem interromper o resto do código.


Usando ambas as funções, podemos implementar a oferta e remoção de itens:


Este é um aspecto feio de usar mensagens assíncronas em ambos os lados. Um conjunto de mensagens tem a forma 'make' e 'retract', enquanto o outro 'faz' e 'desfazha'. Isso é inteiramente arbitrário e apenas usado para diferenciar entre comunicações de jogador-para-FSM e comunicações de FSM para FSM. Note-se que, naqueles que vêm de nosso próprio jogador, temos que dizer ao outro lado sobre as mudanças que estamos fazendo.


Outra responsabilidade é lidar com a mensagem are_you_ready que mencionamos no protocolo. Este é o último evento assíncrono a manipular no estado de negociação:


Conforme descrito no protocolo, sempre que não estamos no estado de espera e recebemos esta mensagem, devemos responder com not_yet. Foram também a saída de detalhes do comércio para o usuário para que uma decisão possa ser tomada.


Quando essa decisão for tomada e o usuário estiver pronto, o evento pronto será enviado. Este deve ser síncrono porque não queremos que o usuário continue modificando sua oferta, adicionando itens ao alegar que ele está pronto:


Neste ponto, uma transição para o estado de espera deve ser feita. Note que apenas esperar o outro não é interessante. Nós salvamos a variável From para que possamos usá-la com gen_fsm: reply / 2 quando tivermos algo a dizer ao cliente.


O estado de espera é uma besta engraçada. Novos itens podem ser oferecidos e retraídos porque o outro usuário pode não estar pronto. Faz sentido, então, reverter automaticamente para o estado de negociação. Seria bom para oferecer excelentes itens para nós, apenas para o outro para removê-los e declarar-se pronto, roubando nossa pilhagem. Voltando à negociação é uma boa decisão:


Agora, isso é algo significativo e nós respondemos ao jogador com as coordenadas que armazenamos em S # state. from. O próximo conjunto de mensagens com as quais precisamos nos preocupar são aqueles relacionados com a sincronização de ambos os EFM para que eles possam mudar para o estado pronto e confirmar o comércio. Para este, devemos realmente nos concentrar no protocolo definido anteriormente.


As três mensagens que podemos ter são are_you_ready (porque o outro usuário se declarou pronto), not_yet (porque pedimos ao outro se ele estava pronto e ele não estava) e pronto! (porque pedimos ao outro se ele estava pronto e ele estava).


Começaremos com are_you_ready. Lembre-se que, no protocolo, dissemos que poderia haver uma condição de corrida escondida. A única coisa que podemos fazer é enviar o pronto! mensagem com am_ready / 1 e lide com o resto mais tarde:


We'll be stuck waiting again, so it's not worth replying to our client yet. Similarly, we won't reply to the client when the other side sends a not_yet to our invitation:


On the other hand, if the other is ready, we send an extra ready! message to the other FSM, reply to our own user and then move to the ready state:


You might have noticed that I've used ack_trans/1 . In fact, both FSMs should use it. Por que é isso? To understand this we have to start looking at what goes on in the ready! state.


When in the ready state, both players' actions become useless (except cancelling). We won't care about new item offers. This gives us some liberty. Basically, both FSMs can freely talk to each other without worrying about the rest of the world. This lets us implement our bastardization of a two-phase commit. To begin this commit without either player acting, we'll need an event to trigger an action from the FSMs. The ack event from ack_trans/1 is used for that. As soon as we're in the ready state, the message is treated and acted upon; the transaction can begin.


Two-phase commits require synchronous communications, though. This means we can't have both FSMs starting the transaction at once, because they'll end up deadlocked. The secret is to find a way to decide that one finite state machine should initiate the commit, while the other will sit and wait for orders from the first one.


It turns out that the engineers and computer scientists who designed Erlang were pretty smart (well, we knew that already). The pids of any process can be compared to each other and sorted. This can be done no matter when the process was spawned, whether it's still alive or not, or if it comes from another VM (we'll see more about this when we get into distributed Erlang).


Knowing that two pids can be compared and one will be greater than the other, we can write a function priority/2 that will take two pids and tell a process whether it's been elected or not:


And by calling that function, we can have one process starting the commit and the other following the orders.


Here's what this gives us when included in the ready state, after receiving the ack message:


This big try . catch expression is the leading FSM deciding how the commit works. Both ask_commit/1 and do_commit/1 are synchronous. This lets the leading FSM call them freely. You can see that the other FSM just goes and wait. It will then receive the orders from the leading process. The first message should be ask_commit . This is just to make sure both FSMs are still there; nothing wrong happened, they're both dedicated to completing the task:


Once this is received, the leading process will ask to confirm the transaction with do_commit . That's when we must commit our data:


And once it's done, we leave. The leading FSM will receive ok as a reply and will know to commit on its own end afterwards. This explains why we need the big try . catch : if the replying FSM dies or its player cancels the transaction, the synchronous calls will crash after a timeout. The commit should be aborted in this case.


Just so you know, I defined the commit function as follows:


Pretty underwhelming, eh? It's generally not possible to do a true safe commit with only two participants—a third party is usually required to judge if both players did everything right. If you were to write a true commit function, it should contact that third party on behalf of both players, and then do the safe write to a database for them or rollback the whole exchange. We won't go into such details and the current commit/1 function will be enough for the needs of this book.


We're not done yet. We have not yet covered two types of events: a player cancelling the trade and the other player's finite state machine crashing. The former can be dealt with by using the callbacks handle_event/3 and handle_sync_event/4 . Whenever the other user cancels, we'll receive an asynchronous notification:


When we do it we must not forget to tell the other before quitting ourselves:


And voilà! The last event to take care of is when the other FSM goes down. Fortunately, we had set a monitor back in the idle state. We can match on this and react accordingly:


Note that even if the cancel or DOWN events happen while we're in the commit, everything should be safe and nobody should get its items stolen.


Note: we used io:format/2 for most of our messages to let the FSMs communicate with their own clients. In a real world application, we might want something more flexible than that. One way to do it is to let the client send in a Pid, which will receive the notices sent to it. That process could be linked to a GUI or any other system to make the player aware of the events. The io:format/2 solution was chosen for its simplicity: we want to focus on the FSM and the asynchronous protocols, not the rest.


Only two callbacks left to cover! They're code_change/4 and terminate/3 . For now, we don't have anything to do with code_change/4 and only export it so the next version of the FSM can call it when it'll be reloaded. Our terminate function is also really short because we didn't handle real resources in this example:


We can now try it. Well, trying it is a bit annoying because we need two processes to communicate to each other. To solve this, I've written the tests in the file trade_calls. erl, which can run 3 different scenarios. The first one is main_ab/0 . It will run a standard trade and output everything. The second one is main_cd/0 and will cancel the transaction halfway through. The last one is main_ef/0 and is very similar to main_ab/0 , except it contains a different race condition. The first and third tests should succeed, while the second one should fail (with a crapload of error messages, but that's how it goes). You can try it if you feel like it.


That Was Quite Something.


If you've found this chapter a bit harder than the others, I must remind you that it's entirely normal. I've just gone crazy and decided to make something hard out of the generic finite-state machine behaviour. If you feel confused, ask yourself these questions: Can you understand how different events are handled depending on the state your process is in? Do you understand how you can transition from one state to the other? Do you know when to use send_event/2 and sync_send_event/2-3 as opposed to send_all_state_event/2 and sync_send_all_state_event/3 ? If you answered yes to these questions, you understand what gen_fsm is about.


The rest of it with the asynchronous protocols, delaying replies and carrying the From variable, giving a priority to processes for synchronous calls, bastardized two-phase commits and whatnot are not essential to understand . They're mostly there to show what can be done and to highlight the difficulty of writing truly concurrent software, even in a language like Erlang. Erlang doesn't excuse you from planning or thinking, and Erlang won't solve your problems for you. It'll only give you tools.


That being said, if you understood everything about these points, you can be proud of yourself (especially if you had never written concurrent software before). You are now starting to really think concurrently.


Fit for the Real World?


In a real game, there is a lot more stuff going on that could make trading even more complex. Items could be worn by the characters and damaged by enemies while they're being traded. Maybe items could be moved in and out of the inventory while being exchanged. Are the players on the same server? If not, how do you synchronise commits to different databases?


Our trade system is sane when detached from the reality of any game. Before trying to fit it in a game (if you dare), make sure everything goes right. Test it, test it, and test it again. You'll likely find that testing concurrent and parallel code is a complete pain. You'll lose hair, friends and a piece of your sanity. Even after this, you'll have to know your system is always as strong as its weakest link and thus potentially very fragile nonetheless.


Don't Drink Too Much Kool-Aid:


While the model for this trade system seems sound, subtle concurrency bugs and race conditions can often rear their ugly heads a long time after they were written, and even if they've been running for years. While my code is generally bullet proof (yeah, right), you sometimes have to face swords and knives. Beware the dormant bugs.


Fortunately, we can put all of this madness behind us. We'll next see how OTP allows you to handle various events, such as alarms and logs, with the help of the gen_event behaviour.


Except where otherwise noted, content on this site is licensed under a Creative Commons Attribution Non-Commercial No Derivative License.


State Machines For Trading.


A finite state machine is a model of a system that shows the different possible states the system can attain and the transitions that occur as the system moves from one state to another. You can use it in modeling your trading system.


A state machine may be the mechanism that you need to organize your model of the market into a winning system. I will explain how a finite state machine (FSM) works and show you a model for a trading system. State machines can be easily created in most programming languages to automate your trading decisions. You can also operate the strategy manually if you wish.


State machines explained.


A finite state machine, also referred to as a finite automaton, is a model of a system that shows the different possible states the system can attain and the transitions that occur as the system moves from one state to another. FSMs are used by engineers to model both hardware and software systems. They can also be used to advantage in modeling your trading system.


A simple stoplight will be used to illustrate the key elements of a finite state machine. Figure 1 illustrates the state machine diagram of the stoplight. There are three valid states for the light — red, yellow, and green. The light can be in only one of those states at any given time. The states are represented by the circles and the arrows show the transitions from one state to the next. The states can only move from red to green, from green to yellow, and from yellow to red.


Figure 1: Stoplight state diagram.


An event initiates a move from the current state to a next valid state. For our stoplight, we define two types of events that can cause transitions to occur. The most common transition event occurs after the light has been on for a specified period. The red light and green light have on-time periods of 30 seconds each and the yellow light has an on-time of five seconds. A timer keeps track of how long a light has been on and will initiate a transition when the time period has elapsed.


A second event type is defined by the push of a crosswalk button. If a person presses the crosswalk button while the light is red and the light has been on for less than 25 seconds, the timer is advanced to 25 seconds of elapsed time. This causes the transition from red to green to occur sooner to allow the pedestrian to cross.


This is a very simple model that assumes the system has been running eternally, as there is no start state or stop state mentioned. The diagram shown in Figure 1 does not tell us anything about the events that cause transitions. The program that implements the finite state machine must include the rules that trigger events. The rules can be simple, as shown, or quite complex. The sidebar, "Programming a state machine," shows how the stoplight can be implemented using a BASIC-like language. Take a look at the code example to see how the rules are implemented to shift from one state to the next.


A state machine for trading.


Figure 2 illustrates a diagram of a finite state machine for a possible trading system. A start state and a stop state have been included to represent entering a position and exiting from it. Let's walk through the state diagram to describe the different states and the events that might trigger a transition.


Figure 2: Trading system state diagram.


This trading system assumes that a series of trades will start by triggering a buy order. Transitions between states are initiated by the rules being used to make investment decisions. We will assume that a set of technical indicators has been chosen to be evaluated in each state to decide what action to take. The rules would typically be evaluated each time we receive a new set of data. A daily system would be evaluated with end-of-day data. If the system is connected to a real-time data source, then the current state rules would be evaluated with each new data point.


A daily system would be evaluated with end-of-day data. The design of the state machine incorporates within its structure the dependencies between the rules for each state. The resulting actions depend not only on what the system indicators show but where the system is (that is, the current state). The system does not have to be designed to use the same rules or indicators in each state, so the rules and indicators can be optimized for each state. This combination of flexibility and trading discipline that can be programmed into the state machine can bring power to your trading.


Let's use a simple example based on moving averages. A signal to sell occurs when the closing price falls below the moving average. A signal to buy occurs when the closing price falls above the moving average. Further, we will add to the position if the price falls back by 5% and then rebounds without penetrating the moving average. If you sold and the price recovers by 5% without penetrating the moving average, you can use this as an opportunity to place a short.


Suppose you start with a decision to trade a given issue. In this model, the start rule triggers the event that moves the system to the buy state. The rule for the buy state is quite simple: Make a purchase and transition to the buy hold state. The buy is a transitory state and the system moves to the buy hold state as soon as the purchase is complete. The system can stay in the buy hold state as long as the rules do not indicate a move to a new state.


The rules for a new data point stipulate that no change in state is called for as long as the closing price remains above the moving average. This is illustrated by the transition arrow that loops back to the buy hold state.


As we watch the market and chart the moving average, we see the price drop back, but not enough to trigger a transition to the sell state. Our model rules indicate that this retreat exceeds 5% so the system triggers a transition to the buy add state. Like the buy, this is a transitory state and the system moves back to the buy hold state when the purchase is complete.


At some point, the closing price drops below the moving average, indicating that the move has topped out and a transition occurs to the sell event. This event moves the system to the transitory sell state. From the sell state, two decisions are possible. We may decide to stop trading in this issue completely, or we may decide to continue tracking this stock and move to the sell hold state when the sale is complete. From the sell hold state, the system waits for a penetration of the moving average for a buy signal. A short opportunity could also occur if the price moves up by 5% without penetrating the moving average.


Figure 3 shows a chart and the different states of this model during a selected time period, as might be indicated by rules as I have described. As you can see, most of the time is spent in the buy hold (B) or sell hold (E) states.


Figure 3: Stock closing price with moving average.


This is a model representative of a simple stock trading system. Other systems, such as option trading, might be more complex because of the many possible kinds of positions that can be taken, resulting in more states and possible transitions. The state machine provides a logical control structure for organizing the rules of your trading system and an easily programmed method for automating those rules. It is then easy to backtest the system by applying the historical data to the state machine.


A state machine can be used to provide discipline to your trading system. You can incorporate any number of decision rules for each state. The structure you design can automatically incorporate dependency relationships that might not be obvious or easily modeled by other approaches. As I have shown in the sidebar, the programming of a state machine is not difficult once you have defined the rules you wish to use. However, the idea of the state machine can just as easily be applied to a discretionary trading method.


Glenn Barlis is a system design consultant. He has a master's degree in business administration and a master's degree in computer science.


Programming a State Machine.


A state machine can be implemented in any language that provides the IF-THEN-ELSE control structure. The language must also provide for a variable that can hold the current machine state between events. Here is the traffic light example shown in a BASIC-like language. We are assuming that the state machine is run once per second and the machine is started in a known valid state.


Traffic Light State Machine.


Static Current_State; holds the machine state.


Static Timer; keeps track of how long the.


light has been on.


Constant green_time = 30; define on-time for lights.


IF Current_State = Green THEN.


IF Timer >= green_time THEN.


Timer = Timer + 1.


ELSE IF Current_State = Yellow THEN.


IF Timer >= yellow_time THEN.


Timer = Timer + 1.


ELSE IF Current_State = Red THEN.


IF Timer < (red_time - 5) AND Cross_Button_Pushed THEN.


Timer = red_time - 5.


IF Timer >= red_time THEN.


Timer = Timer + 1.


State Machine Using CASE Statement.


Keeping track of all the IF-THEN-ELSE statements can get confusing and makes the program more prone to bugs. Many programming languages offer a form of Case statement to simplify writing this kind of code. Here is the same example using a CASE statement with the Visual BASIC syntax.


Select Case Current_State.


IF Timer >= green_time THEN.


Timer = Timer + 1.


IF Timer >= yellow_time THEN.


Timer = Timer + 1.


IF Timer < (red_time - 5) AND.


Timer = red_time - 5.


IF Timer >= red_time THEN.


Timer = Timer + 1.


The Select Case structure will only select one of the cases based on the value of Current_State. As you can see, this program segment is much easier to understand than the IF-THEN-ELSE example and less likely to have bugs.


A third option for implementing a finite state machine is to use a table-driven state machine engine. This is a more sophisticated method that would be used for complex machines or for commercial software that needs to provide an easy method for user-defined state rules.


Direitos autorais e cópia; 1982 & ndash; 2017 Technical Analysis, Inc. Todos os direitos reservados. Leia nosso aviso e amp; declaração de privacidade.


algotrading.


71 пользователь находится здесь.


МОДЕРАТОРЫ.


Bem-vindo ao Reddit,


a primeira página da internet.


e inscreva-se em uma das milhares de comunidades.


Это архивированный пост. Você está interessado em иолосовать или комментировать.


Quer adicionar à discussão?


помощь правила сайта центр поддержки вики реддикет mod guidelines связаться с нами.


приложенияи инструменты Reddit para iPhone Reddit para o site móvel Android кнопки.


Использование данного сайта означает, что вы принимаете & # 32; пользовательского соглашения & # 32; и & # 32; Политика конфиденциальности. &cópia de; 2017 reddit инкорпорейтед. Все права защищены.


REDDIT e o logotipo ALIEN são marcas registradas da reddit inc.


& pi; Rendered by PID 94724 on app-09 at 2017-12-26 00:56:02.073972+00:00 running a84abeb country code: UA.


Trading System Design & Coding Services.


AlgorithmicTrading provides design & coding services. We can implement your trading strategy using the tradestation platform. All code is delivered in an open source format. If you have a need to hire an experienced developer give us a call. Our lead developer has a Bachelors of Science in Electrical Engineering and spent over 10 years in the semiconductor industry as a Logic Design Engineer.


Specializing In Algorithmic Trading Design Architecture & Implementação.


Our team is capable of implementing your idea in Easy Language for use in automated trading on platforms such as Tradestation. We have designed and implemented over 300 trading strategies and is our number one core competency. We are a software development company with a heart for implementing trading systems. If you have an idea or project – we might be able to help you implement this idea.


Logic Design Experience Includes.


Our team has experience coding in Perl, VHDL, Verilog, C, C++, Java, Matlab, TCL/TK and Easy Language. In our experience, utilizing tradestations Easy Language is the best option for most retail traders. This language is capable of object oriented programming and has numerous predefined functions that make implementing most trading strategies quite simple. Our lead designer has designed DMA’s, PCI-Express Layers, Snoop Logic and more. While implementing a trading system is quite a bit different than coding a block of logic, there are numerous similarities. For example, in a block of synchronous logic running in an asic, new events happen on each clock cycle. In trading, events typically occur when a new candle is created on a chart. Logic design engineers are well versed in Finite State Machines and commonly used data structures which can be used in trading systems.


Quantitative Trading Experience Includes.


AlgorithmicTrading is capable of coding your design, performing a back-test, running optimizations and cross optimizing inputs, monte carlo simulations and performing walk-forward analysis on out-of-sample data. In many ways, coding the design is the easy part. Much of the post coding tasks center around verifying the idea by back-testing it first, second optimizing it and third running a walk-forward analysis on out of sample data.


Depending on your budget and needs, AlgorithmicTrading will run all of the above tests and provide reports and commentary on each stage of the analysis.


Your Idea Implemented.


If your trading idea relies on a sequence of events, we will more than likely implement your trading system using a finite state machine in order to simplify the code. For example, perhaps your strategy waits for a gap up when the equity markets open, followed by a bearish cross on a MACD. Once this happens your strategy goes SHORT the market. The BUY occurs when you have a gap up followed by a bullish cross. The following bubble diagram shows what your state machine might look like.


Step 1: Fill Out Our Questionnaire & NDA.


Give us a call or shoot us an email and we can send you our questionnaire. This form allows us to provide a quote to you based on the complexity of your idea. We might exchange a few emails and/or schedule a phone call to clarify your intent. If needed, AlgorithmicTrading will sign a Non Disclosure Agreement prior to you emailing us the filled out questionnaire.


Step 2: Receive A Quote.


Based on the complexity of the design, our Lead Designer will provide an estimate of time involved and a quote. If you are satisfied with the price and expectations are clear we will move forward with the design. You will provide a non-refundable down-payment of 50% and the balance will be due once the design is completed. Included in the price is up-to 2 hours of modifications post installation to ensure that the code is working as you expected.


Step 3: Implementation Phase.


Our designer will be in close contact with you throughout the coding and design phase to ensure that the architecture and implementation is consistent with your idea. This is done to avoid any surprises once the code is complete.


Step 4: Analysis Phase (optional)


Depending on your needs as identified in the questionnaire, we will back-test the trading system, run optimizations on the inputs, cross-optimize the inputs and run a matrix of walk-forward tests with varying in-sample and out of sample periods. At each phase of this process, we will provide reports on our findings so that you are kept in the loop.


Step 5: Design Hand-Off & Instalação.


Once the design is completed, the designer will schedule a time to perform the installation. The remaining balance is due prior to the design hand-off. During the installation, the designer will remotely login to your PC and install the Easy Language code onto your Tradestation platform. This usually takes less than an hour. The designer will review the code with you and show you how to adjust the inputs and other settings.


Step 6: Maintenance Phase.


After the code is loaded and running, you might require a few changes to it. Included in the quote is up to 2 hours of post installation coding. In our experience, once the customer has the code running they might require a few modifications or bug fixes. This is extra time is included to ensure that the code is running as you expected.


Pronto para começar?


Visit our contact us page and fill out the form or give us a call at 1.866.759.6546. We will be happy to discuss our coding services in more detail with you. Just keep in mind, coding a trading system can be accompanied with either great joy or tremendous disappointment. We will code your idea and deliver the code, however there are no guarantees that your idea will be a reliable trading strategy. Designing and developing trading systems is not an easy task. Once an idea is implemented and back-tested, the results may or may not represent a profitable trading strategy. Trading futures & amp; as opções envolvem um risco substancial de perda e não é apropriado para todos os investidores.

No comments:

Post a Comment