From 73b349671c3f2cdd13544166889096e77b8a1399 Mon Sep 17 00:00:00 2001 From: Julio Biason Date: Wed, 12 Jan 2022 12:44:11 -0300 Subject: [PATCH] WIP: Examples of FAST --- content/research/decoding-fast-examples.md | 62 ++++++-- content/research/decoding-fast-examples.pt.md | 139 ++++++++++++++++++ content/research/decoding-fast.md | 5 +- content/research/decoding-fast.pt.md | 5 +- 4 files changed, 196 insertions(+), 15 deletions(-) create mode 100644 content/research/decoding-fast-examples.pt.md diff --git a/content/research/decoding-fast-examples.md b/content/research/decoding-fast-examples.md index 3d0fc3e..66e593a 100644 --- a/content/research/decoding-fast-examples.md +++ b/content/research/decoding-fast-examples.md @@ -1,6 +1,6 @@ +++ title = "Decoding the FAST Protocol: Examples" -date = 2022-01-11 +date = 2022-01-12 draft = true [taxonomies] @@ -13,11 +13,17 @@ understand. +{% note() %} +Same disclaimer as before: Because this is based on my personal experience, +some things may be out of place. I tried my best to keep things correctly, but +I may have misunderstood something, or maybe I just typed the value wrong here. +{% end %} + # Simple Hello World This example is basically the same one in [JetTek](https://jettekfix.com/education/fix-fast-tutorial/) but it is really -simple, so here we go: +simple to explain, so here we go: ## Template @@ -52,12 +58,12 @@ far; there is no information whatsoever about that second bit in the Presence Map -- we need to find out which template should be used first. The next byte is read: `1000_0001`. As mentioned above, this is the Template -ID. Being a signed integer (and probably mandatory, but don't ask me how that -works), we read the value, it has the stop bit, so that's the whole integer. -Dropping the high order bit, we get the Integer "1", which is the exactly same -ID we have in the template, so now we know which fields are here. +ID. Being an unsigned integer (and probably mandatory, but don't ask me how +that works) and dropping high order bit, we get the Integer "1", which is the +exactly same ID we have in the template; now we know which fields should be +processed. -The first field in the template is the string with a default value. Because the +The first field in the template is a string with a default value. Because the field uses the Default operator, we need to check if the value is in the data or we should use the default value. The bit in the Presence Map for this field is `1` meaning the value for the string is in the incoming data and we should @@ -69,7 +75,7 @@ letter in the ASCII table. The sequence is `100_1000` (72), `110_0101` (101), `110_1100` (108), `110_1100` (108), `100_1111` (79), `101_0111` (87), `110_1111` (79), `111_0010` (114), `110_1100` (108) and `110_0100` (100). Notice that we consumed all the bytes, and the last one have the stop, so -that's the end of string. Converting the bytes using the ASCII string, we get +that's the end of string. Converting the bytes using the ASCII table, we get "HelloWorld". So, there we have it: We received a record of the "HelloWorld" type, with the @@ -119,7 +125,10 @@ list of users and their IDs. 1100_0000 0101_0101 0111_0011 0110_0101 0111_0010 1011_0001 1000_0100 1000_0000 0101_0101 0111_0011 0110_0101 0111_0010 -1011_0010 +1011_0010 1111_1111 1000_0001 1100_0000 +0101_0101 1011_0001 1111_1111 0000_1000 +1000_0000 1000_0010 1100_0000 1100_1001 +1011_0110 1000_0000 0100_1101 1110_0101 ``` ## Processing @@ -191,3 +200,38 @@ for the Presence Map, but for the "Username". The bytes for the field are `0101_0101` (85), `0111_0011` (115), `0110_0101` (101), `0111_0010` (114) and `1011_0001` (50), which is "User2". +This second record have an empty presence map (`1000_0000`) meaning that the ID +is not present in the incoming data. Because the field has the Increment +operator, we should use the previous value -- 3 -- and increment by 1. So +"User2" have the ID 4. + +That ends the "InnerSequence" for the first record of "OuterSequence". Going +faster now: + +- `1111_1111`: The second "GroupID" (only one byte due the stop bit), which is + 127. +- `1000_0001`: The length of "InnerSequence"; it is just 1 element. +- `1100_0000`: The presence map for the first record of "InnerSequence"; it + means the "ID" is present. +- `0101_0101`, `1011_0001`: The username. "U1". +- `1111_1111`: The "ID" for user "U1" is 126 (it reads as 127, but because the + field is optional, we decrement the value by 1). +- `0000_1000`, `1000_0000`: The third "GroupID". Removing the stop bit and + joining the bits we have `1000_0000_0000` which is 2048. +- `1000_0010`: Length of the "InnerSequence" in the 3rd group; 2 elements. +- `1100_0000`: Presence Map of the first record of "InnerSequence"; ID is + present. +- `1100_1001`: Username. "I". +- `1011_0110`: The "ID" for user "I". 53. +- `1000_0000`: Presence Map for the second record of "InnerSequence"; ID is not + present. +- `0100_1101`, `1110_0101`: Username. "Me". +- Not reading any bytes now 'cause the Presence Map pointed that the "ID" is + not present, but because the previous value was 53, the ID for username "Me" + is 54. + +--- + +Changelog: + +- 2022-01-12: First release. diff --git a/content/research/decoding-fast-examples.pt.md b/content/research/decoding-fast-examples.pt.md new file mode 100644 index 0000000..a9455c0 --- /dev/null +++ b/content/research/decoding-fast-examples.pt.md @@ -0,0 +1,139 @@ ++++ +title = "Decodificando o Protocolo FAST: Exemplos" +date = 2022-01-12 +draft = true + +[taxonomies] +tags = ["finanças", "binário", "protocolo", "fix", "fast", "exemplos"] ++++ + +Depois de toda a explicação sobre a definição do protocolo FAST, eu notei que +tinha uma coisa faltando: Exemplos, para que fique mais fácil de entender. + + + +{% note() %} +Mesmo aviso do post anterior: Como isso tudo é baseado na minha experiência +pessoal, algumas coisas podem estar erradas. Eu tentei o meu melhor para deixar +tudo correto, mas eu posso ter entendido alguma coisa errada, ou digitei errado +aqui. +{% end %} + +# Hello World + +Este exemplo é basicamente o mesmo da +[JetTek](https://jettekfix.com/education/fix-fast-tutorial/) mas é realmente +simples de explicar, então vamos nós: + +## Template + +```xml + + + + +``` + +## Dados de Entrada + +Bytes: + +``` +1110_0000 1000_0001 0100_1000 0110_0101 +0110_1100 0110_1100 0100_1111 0101_0111 +0110_1111 0111_0010 0110_1100 1110_0100 +``` + +## Processamento + +O primeiro byte é o Mapa de Presença. Removendo o bit de parada, temos +`110_0000`. Esse Mapa de Presença tem um campo que não é descrito no template: +O ID do Template. Como o primeiro bit está ligado, nós sabemos que o ID está +lá. Ainda, tenha em mente que o ID do Template é o único campo que nós sabemos +que existe até agora; não existe nenhuma outra informação sobre o que é aquele +segundo bit no Mapa de Presença -- nós precisamos encontrar qual template vamos +usar antes de mais nada. + +O próximo byte é lido: `1000_0001`. Como mencionado acima, isso é o ID do +Template. Sendo um inteiro sem sinal (e provavelmente mandatório, mas não me +pergunte como isso funciona) e removendo o bit de parada, temos o inteiro "1", +que é exatamente o mesmo ID que temos no nosso template; agora nós sabemos +quais campos devem ser processados. + +O primeiro campo do template é uma string com um valor default. Como o campo +usa o operador Default, nós precisamos verificar se o valor está presente nos +dados de entrada ou se devemos usar esse valor default. O bit no Mapa de +Presença para este campo é `1`, o que indica que a string está presente nos +dados de entrada e que nós devemos lê-la. + +O campo é uma string, então vamos ler todos os bytes até encontrarmos um com o +bit de parada. Ainda, sendo string, nós não precisamos "juntar" os bits: cada +byte é uma letra da tabela ASCIII. A sequência é `100_10000` (72), `110_0101` +(101), `110_1100` (108), `110_1100` (108), `100_1111` (79), `101_0111` (87), +`110_1111` (79), `111_0010` (114), `110_1100` (108) e `110_0100` (100). Observe +que nós consumimos todos os bites e o último tinha o bit de parada, então +terminamos o pacote com a string. Convertendo os bytes usando a tabela ASCII, +temos "HelloWorld". + +Assim, temos o resultado: Nós recebemos um registro do tipo "HelloWorld" cujo +campo com ID "1" (chamado "String") tem o valor "HelloWorld". + +# Sequências + +Vamos expandir nosso exemplo adicionando uma sequência e alguns operadores: + +## Template + +```xml + + + + + + +``` + +Apesar do FAST ser criado para trabalhar com FIX e o mercado financeiro, não +existe nada que iniba o mesmo de ser usado para outras coisas. O novo template +descreve um group de usuários, então nós temos uma lista de grupos e, para cada +grupo, uma lista de usuários e seus IDs. + +## Dados de Entrada + +``` +1100_0000 1000_0010 1000_0011 0000_0011 +0010_0011 0001_1000 1110_0111 1000_0010 +1100_0000 0101_0101 0111_0011 0110_0101 +0111_0010 1011_0001 1000_0100 1000_0000 +0101_0101 0111_0011 0110_0101 0111_0010 +1011_0010 1111_1111 1000_0001 1100_0000 +0101_0101 1011_0001 1111_1111 0000_1000 +1000_0000 1000_0010 1100_0000 1100_1001 +1011_0110 1000_0000 0100_1101 1110_0101 +``` + +## Processamento + + diff --git a/content/research/decoding-fast.md b/content/research/decoding-fast.md index 6505793..9c6f9ca 100644 --- a/content/research/decoding-fast.md +++ b/content/research/decoding-fast.md @@ -587,6 +587,5 @@ mandatory sequences. ### Changelog: -2022-01-10: First release. - -2022-01-10: Added information about the template versioning. +- 2022-01-10: First release. +- 2022-01-10: Added information about the template versioning. diff --git a/content/research/decoding-fast.pt.md b/content/research/decoding-fast.pt.md index 203008b..c9271e9 100644 --- a/content/research/decoding-fast.pt.md +++ b/content/research/decoding-fast.pt.md @@ -600,9 +600,8 @@ sequências mandatórias e opcionais. Changelog: -2022-01-10: Primeira versão. - -2022-01-10: Adicionada informações sobre o versionamento de templates. +- 2022-01-10: Primeira versão. +- 2022-01-10: Adicionada informações sobre o versionamento de templates.