Brasa Template Writer
Write new templates from scratch or migrate legacy templates to modern pipeline-based format.
Mode Detection
- Write new: User asks to create/write/add a new template
- Migrate: User asks to migrate/convert/update a legacy template (one with
reader.function or handler: field blocks)
Workflow
Write New Template
Determine template type:
- Single-dataset reader: one set of fields, reads a single file format
- Multi-dataset reader: multiple datasets from one source (e.g., XML with multiple tags)
- ETL pipeline: transforms data from upstream datasets using SQL or steps
If user provides a full spec (URL, format, fields), generate directly
If info is missing, ask one question at a time:
- What data source? (URL, institution, file format)
- What file format? (CSV, FWF, JSON, XML, Excel)
- What fields? (names, types, descriptions)
- What layer? (input, staging, curated)
- Partitioning? (typically
[refdate])
Generate the template YAML
Save to templates/ in appropriate subdirectory based on data source:
templates/b3/ for B3 data (subdirs: equities, futures, indexes, raw, options)
templates/anbima/ for ANBIMA
templates/bcb/ for BCB/SGS
templates/cvm/ for CVM
templates/td/ for Tesouro Direto
Migrate Legacy Template
- Read the legacy template from
templates/legacy/ or wherever it lives
- Analyze the reader function (see "Analyzing the Reader Function" below) to understand how fields are parsed
- Apply all transformations (see Migration Rules below)
- Save the new template to the appropriate
templates/ subdirectory
- Add a YAML comment at top noting it was migrated from the legacy version
Analyzing the Reader Function
The legacy reader.function contains valuable information about field parsing that should inform your field type definitions. Always examine the function implementation in brasa/readers/ before migrating.
Common patterns to look for:
| Code Pattern |
Field Type |
pd.to_numeric(df[col].str.replace(",", "."), ...) |
type: numeric(decimal=",") |
pd.to_numeric(df[col].str.replace(".", "").str.replace(",", "."), ...) |
type: numeric(decimal=",", thousands=".") |
pd.to_datetime(df[col], format='%d/%m/%Y', ...) |
type: date(format='%d/%m/%Y') |
pd.to_datetime(df[col], dayfirst=True, ...) |
type: date (with dayfirst in reader context) |
pd.to_numeric(df[col], ...) |
type: numeric (plain numeric parsing) |
str.replace(",", ".") on numeric field |
indicates comma as decimal separator → use decimal="," |
str.replace(".", "").str.replace(",", ".") |
indicates European format (dot=thousands, comma=decimal) → use thousands=".", decimal="," |
Example: If the reader function has:
df["volume"] = pd.to_numeric(df["volume"].str.replace(",", "."), errors="coerce")
df["price"] = pd.to_numeric(df["price"].str.replace(",", "."), errors="coerce")
Then in the YAML, these should be:
- name: volume
type: numeric(decimal=",")
- name: price
type: numeric(decimal=",")
Not just type: numeric with no parameters.
Migration Rules
Field Type Migration
Legacy (handler:) |
Modern (type:) |
handler: {type: numeric, dec: 2.0} |
type: numeric(dec=2.0) |
handler: {type: numeric, dec: 0.0} |
type: integer |
handler: {type: Date, format: '%Y%m%d'} |
type: date(format='%Y%m%d') |
handler: {type: POSIXct, format: '%H%M%S'} |
type: datetime(format='%H%M%S') |
handler: {type: character} |
type: character |
handler: {type: factor, ...} |
type: character |
- Remove the
handler: block entirely from each field
- Keep
name:, description:, width: (if FWF), and any tag: attributes
- If
handler.dec is a field reference (e.g., dec: num_casas_decimais_2), add a comment noting the dynamic decimal and use type: numeric without dec parameter
Sign Field Migration
For numeric fields with sign: some_column:
- Convert the field to
type: numeric(dec=N) (without sign)
- Add a YAML comment:
# sign: originally from <sign_column>
- After the
apply_fields step in the pipeline, add steps:
# Apply sign columns to their target numeric fields
- step: custom_simple
code: |
import numpy as np
sign_map = {
'cot_primeiro_negocio': 'sinal_cot_primeiro_negocio',
# ... list all sign->target pairs
}
for target, sign_col in sign_map.items():
if target in df.columns and sign_col in df.columns:
mask = df[sign_col].str.strip() == '-'
df.loc[mask, target] = -df.loc[mask, target]
# Drop sign columns (no longer needed)
- step: drop_columns
columns: [sinal_cot_primeiro_negocio, sinal_cot_menor_negocio, ...]
Also remove the sign fields from the fields: list.
Structural Migration
- Replace
reader: { function: ... } with reader: { pipeline: [...] }
- Choose pipeline steps based on
filetype:
FWF → read_fwf (dtype: str) → filter if needed → apply_fields
CSV → read_csv → apply_fields
JSON → read_json → apply_fields
Excel/XLS → read_excel → apply_fields
- Add
writer: block with layer: input and partitioning: [refdate]
- Add
downloader: block if the legacy template has URL info or if user provides it
- Remove
filename: and filetype: top-level keys (these are inferred by the pipeline)
Field Type Reference
| Type |
Parameters |
Example |
character / string / char |
none |
type: character |
integer / int |
none |
type: integer |
numeric / number |
dec, sign, thousands, decimal |
type: numeric(dec=2.0) |
date |
format (default: %Y-%m-%d) |
type: date(format='%Y%m%d') |
datetime / posixct |
format (default: %Y-%m-%d %H:%M:%S) |
type: datetime(format='%H%M%S') |
time |
format (default: %H:%M:%S) |
type: time(format='%H%M') |
boolean / bool |
none |
type: boolean |
Syntax Rules
- Parameters in parentheses:
typename(key=value)
- String values in single quotes:
date(format='%Y%m%d')
- Multiple params comma-separated:
numeric(dec=2, decimal=',')
numeric(dec=0.0) for integers stored as fixed-width numbers → prefer integer in new templates
Pipeline Steps Reference
Comprehensive reference of all registered pipeline steps organized by category.
I/O Steps (Reading Data)
| Step |
Parameters |
Description |
read_csv |
separator, skip, header, names, converters |
Read CSV file with optional custom separator and header |
read_fwf |
colspecs, names, skip, dtype |
Read fixed-width format files (plain or gzip); derives column specs from field widths |
read_json |
orient, path |
Read JSON file (supports gzip) into DataFrame |
read_excel |
sheet, skip, header |
Read Excel file into DataFrame |
Column Manipulation Steps
| Step |
Parameters |
Description |
set_columns |
names (required) |
Set column names for DataFrame |
rename_columns |
mapping (required) |
Rename columns using dict mapping |
select_columns |
columns (required) |
Select specific columns to keep |
drop_columns |
columns (required) |
Drop columns from data |
add_column |
name, value, from (with where and key), only_if_missing |
Add new column with static or dynamic value |
reorder_columns |
order (required), keep_rest |
Reorder columns in DataFrame |
Data Transformation Steps
| Step |
Parameters |
Description |
apply_fields |
errors (coerce/raise/ignore), set_columns |
Apply field type definitions using Fieldset |
apply_fields_multi |
errors |
Apply field definitions to multiple DataFrames in dict |
parse_numeric |
columns (required), errors |
Parse string columns as numeric using context settings |
parse_date |
columns (required), format, errors |
Parse string columns as dates |
parse_datetime |
columns (required), format, errors |
Parse string columns as datetime values |
fill_na |
columns, value, method (ffill/bfill) |
Fill NA/NaN values |
drop_duplicates |
subset, keep (first/last/False) |
Remove duplicate rows |
drop_na |
columns, how (any/all) |
Drop rows with NA/NaN values |
filter_rows |
column, operator (eq/ne/gt/lt/etc), value |
Filter rows based on conditions |
forward_fill_column |
column (required), condition |
Forward fill values in column |
extract_regex |
column, pattern (required), output, group |
Extract values using regex capture groups |
concat_columns |
columns, output (required), separator |
Concatenate multiple columns into one |
melt |
id_vars, value_vars, var_name, value_name |
Unpivot DataFrame from wide to long format |
sort |
by (required), ascending, descending, na_position |
Sort data by columns |
make_date |
year_column, month_column, day_column (required), output, errors |
Create date column from components |
str_replace |
column, pattern (required), replacement, output, regex |
Replace pattern in string column |
cast |
column, dtype (required), errors |
Cast column(s) to specific type |
ETL Pipeline Steps
| Step |
Parameters |
Description |
load |
template OR (input, layer) |
Load a dataset as PyArrow Dataset |
concat_datasets |
inputs (required), layer (required), columns |
Concatenate multiple datasets vertically |
dataset_filter |
where (required) |
Filter rows by equality conditions |
dataset_select |
columns (required) |
Select columns from dataset |
select_fields |
(uses context.fields) |
Select columns based on field names |
dataset_sort |
by (required), descending |
Sort PyArrow dataset |
dataset_drop_columns |
columns (required) |
Drop columns from dataset |
dataset_rename_columns |
mapping (required) |
Rename columns in dataset |
dataset_drop_duplicates |
subset, keep |
Remove duplicate rows from dataset |
dataset_fill_na |
value, method, columns |
Fill missing values in dataset |
to_dataframe |
(none) |
Convert PyArrow Dataset/Table to pandas DataFrame |
sql_query |
datasets (required), query (required) |
Execute SQL on datasets in in-memory DuckDB |
future_maturity_to_date |
code_column, date_column (required), maturity_day, calendar |
Convert future maturity codes to dates |
following_bizday |
date_column, adjusted_column (required), calendar |
Adjust dates to following business day |
bizdays |
from_column, to_column, output_column (required), calendar |
Calculate business days between dates |
implied_rate |
price_column, rate_column, days_to_maturity_column (required), compounding, forward_price |
Calculate implied interest rate from price |
flatten_columns |
columns (required), separator |
Flatten delimited values into separate rows |
B3-Specific Steps
| Step |
Parameters |
Description |
b3_read_bvbg028_xml |
(uses datasets config) |
Read/parse B3 BVBG028 gzipped XML file (returns Dict[str, DataFrame]) |
b3_read_bvbg086_xml |
(uses field tags) |
Read/parse B3 BVBG086 gzipped XML file |
b3_read_bvbg087_xml |
(uses datasets config) |
Read/parse B3 BVBG087 gzipped XML file |
b3_read_company_info_json |
(uses datasets config) |
Read B3 company info gzipped JSON (returns Dict[str, DataFrame]) |
b3_read_company_details_json |
(none) |
Read B3 company details JSON, expands otherCodes array |
b3_add_columns_from_json_fields |
mapping (required) |
Parse B3 JSON fields and add as columns |
b3_parse_refdate_from_html |
xpath, attribute, store_as |
Parse reference date from B3 HTML page |
b3_forward_fill_commodity |
column |
Forward fill commodity names in B3 settlement prices |
b3_extract_commodity_code |
column |
Extract commodity code from commodity name |
b3_create_symbol |
commodity_column, maturity_column, output_column |
Create futures symbol by concatenating commodity and maturity |
Canonical Examples
These templates serve as models for creating new templates of each type.
Example 1: Single-Dataset FWF Reader
Fixed-width format (FWF) file with type filtering and field conversion.
id: b3-cotahist-daily
description: Cotações Históricas do Pregão de Ações - Arquivo Diário
downloader:
verify_ssl: false
function: brasa.downloaders.datetime_download
url: https://bvmf.bmfbovespa.com.br/InstDados/SerHist/COTAHIST_D%d%m%Y.ZIP
format: zip
args:
refdate: ~
reader:
encoding: latin1
locale: en
pipeline:
- step: read_fwf
dtype: str
- step: filter_rows
column: regtype
operator: eq
value: '01'
- step: apply_fields
errors: coerce
writer:
layer: input
partitioning: [refdate]
fields:
- name: regtype
description: Tipo de registro
type: character
width: 2
- name: refdate
description: Data do pregão
type: date(format='%Y%m%d')
width: 8
- name: symbol
description: Código de negociação
type: character
width: 12
- name: open
description: Preço de abertura
type: numeric(dec=2.0)
width: 13
- name: high
description: Preço máximo
type: numeric(dec=2.0)
width: 13
- name: low
description: Preço mínimo
type: numeric(dec=2.0)
width: 13
- name: close
description: Preço último negócio
type: numeric(dec=2.0)
width: 13
- name: volume
description: Volume total negociado
type: numeric(dec=2.0)
width: 18
- name: traded_contracts
description: Quantidade negociada
type: integer
width: 18
Key features:
read_fwf reads fixed-width format (widths derived from field definitions)
filter_rows keeps only type "01" records
apply_fields with errors: coerce converts to proper types
datetime_download with refdate parameter
Example 2: Single-Dataset CSV Reader
CSV with custom separator, encoding, column renaming, and context variable injection.
id: cvm-companies-registration
description: Cadastro de companhias abertas da CVM
downloader:
function: brasa.downloaders.simple_download
verify_ssl: false
extra-key: date
url: https://dados.cvm.gov.br/dados/CIA_ABERTA/CAD/DADOS/cad_cia_aberta.csv
format: csv
reader:
locale: pt
encoding: latin1
pipeline:
- step: read_csv
separator: ";"
- step: add_column
from:
where: extra_key
name: refdate
- step: rename_columns
mapping:
CNPJ_CIA: cnpj_cia
DENOM_SOCIAL: denom_social
DT_REG: dt_reg
SETOR: setor
SUBSETOR: subsetor
- step: apply_fields
errors: coerce
writer:
layer: input
partitioning: [refdate]
fields:
- name: cnpj_cia
description: CNPJ da companhia
type: character
- name: denom_social
description: Denominação social
type: character
- name: dt_reg
description: Data de registro
type: date(format='%Y-%m-%d')
- name: setor
description: Setor econômico
type: character
- name: subsetor
description: Subsetor econômico
type: character
- name: refdate
description: Data de referência
type: date
Key features:
read_csv with custom separator (semicolon)
add_column from extra_key (download metadata)
rename_columns mapping for CSV headers
encoding: latin1 for non-UTF8 files
locale: pt for Portuguese number formatting
Example 3: Multi-Dataset XML Reader
XML file with multiple datasets (equities and options) extracted from different tags.
id: b3-bvbg028
description: Arquivo de Preços de Mercado
downloader:
function: brasa.downloaders.datetime_download
url: https://www.b3.com.br/pesquisapregao/download?filelist=IN%y%m%d.zip
format: zip
args:
refdate: ~
reader:
locale: en
pipeline:
- step: b3_read_bvbg028_xml
- step: apply_fields_multi
writer:
partitioning: [refdate]
datasets:
equities:
tag: EqtyInf
fields:
- name: refdate
description: Data de referência
tag: RptParams/RptDtAndTm/Dt
type: date
- name: symbol
description: Código de negociação
tag: InstrmInf/EqtyInf/TckrSymb
type: character
- name: isin
description: Código ISIN
tag: InstrmInf/EqtyInf/ISIN
type: character
- name: corporation_name
description: Razão social
tag: InstrmInf/EqtyInf/CrpnNm
type: character
- name: open
description: Preço de abertura
tag: InstrmInf/EqtyInf/FrstPric
type: numeric
- name: close
description: Preço de fechamento
tag: InstrmInf/EqtyInf/LastPric
type: numeric
options_on_equities:
tag: OptnOnEqtsInf
fields:
- name: refdate
description: Data de referência
tag: RptParams/RptDtAndTm/Dt
type: date
- name: symbol
description: Código de negociação
tag: InstrmInf/OptnOnEqtsInf/TckrSymb
type: character
- name: exercise_price
description: Preço de exercício
tag: InstrmInf/OptnOnEqtsInf/ExrcPric
type: numeric
- name: maturity_date
description: Data de vencimento
tag: InstrmInf/OptnOnEqtsInf/XprtnDt
type: date
Key features:
b3_read_bvbg028_xml is a B3-specific step that parses XML into multiple DataFrames
datasets: block defines multiple output datasets with different XML tags
- Each dataset has its own
fields: with tag: attributes for XPath extraction
apply_fields_multi applies field conversions to all datasets
Example 4: ETL with SQL
ETL template that loads upstream datasets and transforms via SQL query.
id: b3-equities-returns
description: Dataset de retornos de ações
etl:
pipeline:
- step: sql_query
datasets:
- staging.b3-cotahist
- staging.b3-equities-spot-market
query: |
WITH equity_symbols AS (
SELECT DISTINCT symbol
FROM 'staging.b3-equities-spot-market'
WHERE security_category IN (1, 11, 13)
)
SELECT
t.refdate,
t.symbol,
(t.close / LAG(t.close) OVER (PARTITION BY t.symbol ORDER BY t.refdate)) - 1 AS pct_return,
LN(t.close / LAG(t.close) OVER (PARTITION BY t.symbol ORDER BY t.refdate)) AS log_return
FROM 'staging.b3-cotahist' t
INNER JOIN equity_symbols s ON t.symbol = s.symbol
WHERE ROW_NUMBER() OVER (PARTITION BY t.symbol ORDER BY t.refdate) > 1
ORDER BY t.refdate, t.symbol
- step: apply_fields
errors: coerce
writer:
layer: staging
fields:
- name: refdate
description: Data de referência
type: date
- name: symbol
description: Símbolo do ativo
type: character
- name: pct_return
description: Retorno percentual
type: numeric
- name: log_return
description: Retorno logarítmico
type: numeric
Key features:
etl: block with pipeline instead of reader:
sql_query loads upstream datasets and executes SQL
- Uses CTEs, window functions, and JOINs for transformations
- Writes to
staging layer instead of input
- No
downloader: needed (data from upstream templates)
1---2name: brasa-template-writer3description: Write new brasa YAML templates from scratch or migrate legacy templates (with reader.function and handler-based fields) to the modern pipeline-based format. Use when the user asks to create a new template, write a template, migrate a legacy template, convert an old template, or work with YAML template definitions. Also trigger when the user mentions template creation, template migration, or refers to legacy/old templates.4---56# Brasa Template Writer78Write new templates from scratch or migrate legacy templates to modern pipeline-based format.910## Mode Detection1112- **Write new**: User asks to create/write/add a new template13- **Migrate**: User asks to migrate/convert/update a legacy template (one with `reader.function` or `handler:` field blocks)1415## Workflow1617### Write New Template18191. Determine template type:20 - **Single-dataset reader**: one set of fields, reads a single file format21 - **Multi-dataset reader**: multiple datasets from one source (e.g., XML with multiple tags)22 - **ETL pipeline**: transforms data from upstream datasets using SQL or steps23242. If user provides a full spec (URL, format, fields), generate directly253. If info is missing, ask one question at a time:26 - What data source? (URL, institution, file format)27 - What file format? (CSV, FWF, JSON, XML, Excel)28 - What fields? (names, types, descriptions)29 - What layer? (input, staging, curated)30 - Partitioning? (typically `[refdate]`)31324. Generate the template YAML335. Save to `templates/` in appropriate subdirectory based on data source:34 - `templates/b3/` for B3 data (subdirs: equities, futures, indexes, raw, options)35 - `templates/anbima/` for ANBIMA36 - `templates/bcb/` for BCB/SGS37 - `templates/cvm/` for CVM38 - `templates/td/` for Tesouro Direto3940### Migrate Legacy Template41421. Read the legacy template from `templates/legacy/` or wherever it lives432. **Analyze the reader function** (see "Analyzing the Reader Function" below) to understand how fields are parsed443. Apply all transformations (see Migration Rules below)454. Save the new template to the appropriate `templates/` subdirectory465. Add a YAML comment at top noting it was migrated from the legacy version4748### Analyzing the Reader Function4950The legacy `reader.function` contains valuable information about field parsing that should inform your field type definitions. Always examine the function implementation in `brasa/readers/` before migrating.5152**Common patterns to look for:**5354| Code Pattern | Field Type |55|---|---|56| `pd.to_numeric(df[col].str.replace(",", "."), ...)` | `type: numeric(decimal=",")` |57| `pd.to_numeric(df[col].str.replace(".", "").str.replace(",", "."), ...)` | `type: numeric(decimal=",", thousands=".")` |58| `pd.to_datetime(df[col], format='%d/%m/%Y', ...)` | `type: date(format='%d/%m/%Y')` |59| `pd.to_datetime(df[col], dayfirst=True, ...)` | `type: date` (with dayfirst in reader context) |60| `pd.to_numeric(df[col], ...)` | `type: numeric` (plain numeric parsing) |61| `str.replace(",", ".")` on numeric field | indicates comma as decimal separator → use `decimal=","` |62| `str.replace(".", "").str.replace(",", ".")` | indicates European format (dot=thousands, comma=decimal) → use `thousands=".", decimal=","` |6364**Example:** If the reader function has:65```python66df["volume"] = pd.to_numeric(df["volume"].str.replace(",", "."), errors="coerce")67df["price"] = pd.to_numeric(df["price"].str.replace(",", "."), errors="coerce")68```6970Then in the YAML, these should be:71```yaml72- name: volume73 type: numeric(decimal=",")74- name: price75 type: numeric(decimal=",")76```7778Not just `type: numeric` with no parameters.7980## Migration Rules8182### Field Type Migration8384| Legacy (`handler:`) | Modern (`type:`) |85|---|---|86| `handler: {type: numeric, dec: 2.0}` | `type: numeric(dec=2.0)` |87| `handler: {type: numeric, dec: 0.0}` | `type: integer` |88| `handler: {type: Date, format: '%Y%m%d'}` | `type: date(format='%Y%m%d')` |89| `handler: {type: POSIXct, format: '%H%M%S'}` | `type: datetime(format='%H%M%S')` |90| `handler: {type: character}` | `type: character` |91| `handler: {type: factor, ...}` | `type: character` |9293- Remove the `handler:` block entirely from each field94- Keep `name:`, `description:`, `width:` (if FWF), and any `tag:` attributes95- If `handler.dec` is a field reference (e.g., `dec: num_casas_decimais_2`), add a comment noting the dynamic decimal and use `type: numeric` without dec parameter9697### Sign Field Migration9899For numeric fields with `sign: some_column`:1001011. Convert the field to `type: numeric(dec=N)` (without sign)1022. Add a YAML comment: `# sign: originally from <sign_column>`1033. After the `apply_fields` step in the pipeline, add steps:104105```yaml106# Apply sign columns to their target numeric fields107- step: custom_simple108 code: |109 import numpy as np110 sign_map = {111 'cot_primeiro_negocio': 'sinal_cot_primeiro_negocio',112 # ... list all sign->target pairs113 }114 for target, sign_col in sign_map.items():115 if target in df.columns and sign_col in df.columns:116 mask = df[sign_col].str.strip() == '-'117 df.loc[mask, target] = -df.loc[mask, target]118119# Drop sign columns (no longer needed)120- step: drop_columns121 columns: [sinal_cot_primeiro_negocio, sinal_cot_menor_negocio, ...]122```123124Also remove the sign fields from the `fields:` list.125126### Structural Migration127128- Replace `reader: { function: ... }` with `reader: { pipeline: [...] }`129- Choose pipeline steps based on `filetype`:130 - `FWF` → `read_fwf` (dtype: str) → filter if needed → `apply_fields`131 - `CSV` → `read_csv` → `apply_fields`132 - `JSON` → `read_json` → `apply_fields`133 - `Excel/XLS` → `read_excel` → `apply_fields`134- Add `writer:` block with `layer: input` and `partitioning: [refdate]`135- Add `downloader:` block if the legacy template has URL info or if user provides it136- Remove `filename:` and `filetype:` top-level keys (these are inferred by the pipeline)137138## Field Type Reference139140| Type | Parameters | Example |141|---|---|---|142| `character` / `string` / `char` | none | `type: character` |143| `integer` / `int` | none | `type: integer` |144| `numeric` / `number` | `dec`, `sign`, `thousands`, `decimal` | `type: numeric(dec=2.0)` |145| `date` | `format` (default: `%Y-%m-%d`) | `type: date(format='%Y%m%d')` |146| `datetime` / `posixct` | `format` (default: `%Y-%m-%d %H:%M:%S`) | `type: datetime(format='%H%M%S')` |147| `time` | `format` (default: `%H:%M:%S`) | `type: time(format='%H%M')` |148| `boolean` / `bool` | none | `type: boolean` |149150### Syntax Rules151152- Parameters in parentheses: `typename(key=value)`153- String values in single quotes: `date(format='%Y%m%d')`154- Multiple params comma-separated: `numeric(dec=2, decimal=',')`155- `numeric(dec=0.0)` for integers stored as fixed-width numbers → prefer `integer` in new templates156157## Pipeline Steps Reference158159Comprehensive reference of all registered pipeline steps organized by category.160161### I/O Steps (Reading Data)162163| Step | Parameters | Description |164|---|---|---|165| `read_csv` | `separator`, `skip`, `header`, `names`, `converters` | Read CSV file with optional custom separator and header |166| `read_fwf` | `colspecs`, `names`, `skip`, `dtype` | Read fixed-width format files (plain or gzip); derives column specs from field widths |167| `read_json` | `orient`, `path` | Read JSON file (supports gzip) into DataFrame |168| `read_excel` | `sheet`, `skip`, `header` | Read Excel file into DataFrame |169170### Column Manipulation Steps171172| Step | Parameters | Description |173|---|---|---|174| `set_columns` | `names` (required) | Set column names for DataFrame |175| `rename_columns` | `mapping` (required) | Rename columns using dict mapping |176| `select_columns` | `columns` (required) | Select specific columns to keep |177| `drop_columns` | `columns` (required) | Drop columns from data |178| `add_column` | `name`, `value`, `from` (with `where` and `key`), `only_if_missing` | Add new column with static or dynamic value |179| `reorder_columns` | `order` (required), `keep_rest` | Reorder columns in DataFrame |180181### Data Transformation Steps182183| Step | Parameters | Description |184|---|---|---|185| `apply_fields` | `errors` (coerce/raise/ignore), `set_columns` | Apply field type definitions using Fieldset |186| `apply_fields_multi` | `errors` | Apply field definitions to multiple DataFrames in dict |187| `parse_numeric` | `columns` (required), `errors` | Parse string columns as numeric using context settings |188| `parse_date` | `columns` (required), `format`, `errors` | Parse string columns as dates |189| `parse_datetime` | `columns` (required), `format`, `errors` | Parse string columns as datetime values |190| `fill_na` | `columns`, `value`, `method` (ffill/bfill) | Fill NA/NaN values |191| `drop_duplicates` | `subset`, `keep` (first/last/False) | Remove duplicate rows |192| `drop_na` | `columns`, `how` (any/all) | Drop rows with NA/NaN values |193| `filter_rows` | `column`, `operator` (eq/ne/gt/lt/etc), `value` | Filter rows based on conditions |194| `forward_fill_column` | `column` (required), `condition` | Forward fill values in column |195| `extract_regex` | `column`, `pattern` (required), `output`, `group` | Extract values using regex capture groups |196| `concat_columns` | `columns`, `output` (required), `separator` | Concatenate multiple columns into one |197| `melt` | `id_vars`, `value_vars`, `var_name`, `value_name` | Unpivot DataFrame from wide to long format |198| `sort` | `by` (required), `ascending`, `descending`, `na_position` | Sort data by columns |199| `make_date` | `year_column`, `month_column`, `day_column` (required), `output`, `errors` | Create date column from components |200| `str_replace` | `column`, `pattern` (required), `replacement`, `output`, `regex` | Replace pattern in string column |201| `cast` | `column`, `dtype` (required), `errors` | Cast column(s) to specific type |202203### ETL Pipeline Steps204205| Step | Parameters | Description |206|---|---|---|207| `load` | `template` OR (`input`, `layer`) | Load a dataset as PyArrow Dataset |208| `concat_datasets` | `inputs` (required), `layer` (required), `columns` | Concatenate multiple datasets vertically |209| `dataset_filter` | `where` (required) | Filter rows by equality conditions |210| `dataset_select` | `columns` (required) | Select columns from dataset |211| `select_fields` | (uses context.fields) | Select columns based on field names |212| `dataset_sort` | `by` (required), `descending` | Sort PyArrow dataset |213| `dataset_drop_columns` | `columns` (required) | Drop columns from dataset |214| `dataset_rename_columns` | `mapping` (required) | Rename columns in dataset |215| `dataset_drop_duplicates` | `subset`, `keep` | Remove duplicate rows from dataset |216| `dataset_fill_na` | `value`, `method`, `columns` | Fill missing values in dataset |217| `to_dataframe` | (none) | Convert PyArrow Dataset/Table to pandas DataFrame |218| `sql_query` | `datasets` (required), `query` (required) | Execute SQL on datasets in in-memory DuckDB |219| `future_maturity_to_date` | `code_column`, `date_column` (required), `maturity_day`, `calendar` | Convert future maturity codes to dates |220| `following_bizday` | `date_column`, `adjusted_column` (required), `calendar` | Adjust dates to following business day |221| `bizdays` | `from_column`, `to_column`, `output_column` (required), `calendar` | Calculate business days between dates |222| `implied_rate` | `price_column`, `rate_column`, `days_to_maturity_column` (required), `compounding`, `forward_price` | Calculate implied interest rate from price |223| `flatten_columns` | `columns` (required), `separator` | Flatten delimited values into separate rows |224225### B3-Specific Steps226227| Step | Parameters | Description |228|---|---|---|229| `b3_read_bvbg028_xml` | (uses datasets config) | Read/parse B3 BVBG028 gzipped XML file (returns Dict[str, DataFrame]) |230| `b3_read_bvbg086_xml` | (uses field tags) | Read/parse B3 BVBG086 gzipped XML file |231| `b3_read_bvbg087_xml` | (uses datasets config) | Read/parse B3 BVBG087 gzipped XML file |232| `b3_read_company_info_json` | (uses datasets config) | Read B3 company info gzipped JSON (returns Dict[str, DataFrame]) |233| `b3_read_company_details_json` | (none) | Read B3 company details JSON, expands otherCodes array |234| `b3_add_columns_from_json_fields` | `mapping` (required) | Parse B3 JSON fields and add as columns |235| `b3_parse_refdate_from_html` | `xpath`, `attribute`, `store_as` | Parse reference date from B3 HTML page |236| `b3_forward_fill_commodity` | `column` | Forward fill commodity names in B3 settlement prices |237| `b3_extract_commodity_code` | `column` | Extract commodity code from commodity name |238| `b3_create_symbol` | `commodity_column`, `maturity_column`, `output_column` | Create futures symbol by concatenating commodity and maturity |239240## Canonical Examples241242These templates serve as models for creating new templates of each type.243244### Example 1: Single-Dataset FWF Reader245246Fixed-width format (FWF) file with type filtering and field conversion.247248```yaml249id: b3-cotahist-daily250description: Cotações Históricas do Pregão de Ações - Arquivo Diário251252downloader:253 verify_ssl: false254 function: brasa.downloaders.datetime_download255 url: https://bvmf.bmfbovespa.com.br/InstDados/SerHist/COTAHIST_D%d%m%Y.ZIP256 format: zip257 args:258 refdate: ~259260reader:261 encoding: latin1262 locale: en263 pipeline:264 - step: read_fwf265 dtype: str266 - step: filter_rows267 column: regtype268 operator: eq269 value: '01'270 - step: apply_fields271 errors: coerce272273writer:274 layer: input275 partitioning: [refdate]276277fields:278 - name: regtype279 description: Tipo de registro280 type: character281 width: 2282 - name: refdate283 description: Data do pregão284 type: date(format='%Y%m%d')285 width: 8286 - name: symbol287 description: Código de negociação288 type: character289 width: 12290 - name: open291 description: Preço de abertura292 type: numeric(dec=2.0)293 width: 13294 - name: high295 description: Preço máximo296 type: numeric(dec=2.0)297 width: 13298 - name: low299 description: Preço mínimo300 type: numeric(dec=2.0)301 width: 13302 - name: close303 description: Preço último negócio304 type: numeric(dec=2.0)305 width: 13306 - name: volume307 description: Volume total negociado308 type: numeric(dec=2.0)309 width: 18310 - name: traded_contracts311 description: Quantidade negociada312 type: integer313 width: 18314```315316**Key features:**317- `read_fwf` reads fixed-width format (widths derived from field definitions)318- `filter_rows` keeps only type "01" records319- `apply_fields` with `errors: coerce` converts to proper types320- `datetime_download` with `refdate` parameter321322---323324### Example 2: Single-Dataset CSV Reader325326CSV with custom separator, encoding, column renaming, and context variable injection.327328```yaml329id: cvm-companies-registration330description: Cadastro de companhias abertas da CVM331332downloader:333 function: brasa.downloaders.simple_download334 verify_ssl: false335 extra-key: date336 url: https://dados.cvm.gov.br/dados/CIA_ABERTA/CAD/DADOS/cad_cia_aberta.csv337 format: csv338339reader:340 locale: pt341 encoding: latin1342 pipeline:343 - step: read_csv344 separator: ";"345 - step: add_column346 from:347 where: extra_key348 name: refdate349 - step: rename_columns350 mapping:351 CNPJ_CIA: cnpj_cia352 DENOM_SOCIAL: denom_social353 DT_REG: dt_reg354 SETOR: setor355 SUBSETOR: subsetor356 - step: apply_fields357 errors: coerce358359writer:360 layer: input361 partitioning: [refdate]362363fields:364 - name: cnpj_cia365 description: CNPJ da companhia366 type: character367 - name: denom_social368 description: Denominação social369 type: character370 - name: dt_reg371 description: Data de registro372 type: date(format='%Y-%m-%d')373 - name: setor374 description: Setor econômico375 type: character376 - name: subsetor377 description: Subsetor econômico378 type: character379 - name: refdate380 description: Data de referência381 type: date382```383384**Key features:**385- `read_csv` with custom separator (semicolon)386- `add_column` from `extra_key` (download metadata)387- `rename_columns` mapping for CSV headers388- `encoding: latin1` for non-UTF8 files389- `locale: pt` for Portuguese number formatting390391---392393### Example 3: Multi-Dataset XML Reader394395XML file with multiple datasets (equities and options) extracted from different tags.396397```yaml398id: b3-bvbg028399description: Arquivo de Preços de Mercado400401downloader:402 function: brasa.downloaders.datetime_download403 url: https://www.b3.com.br/pesquisapregao/download?filelist=IN%y%m%d.zip404 format: zip405 args:406 refdate: ~407408reader:409 locale: en410 pipeline:411 - step: b3_read_bvbg028_xml412 - step: apply_fields_multi413414writer:415 partitioning: [refdate]416417datasets:418 equities:419 tag: EqtyInf420 fields:421 - name: refdate422 description: Data de referência423 tag: RptParams/RptDtAndTm/Dt424 type: date425 - name: symbol426 description: Código de negociação427 tag: InstrmInf/EqtyInf/TckrSymb428 type: character429 - name: isin430 description: Código ISIN431 tag: InstrmInf/EqtyInf/ISIN432 type: character433 - name: corporation_name434 description: Razão social435 tag: InstrmInf/EqtyInf/CrpnNm436 type: character437 - name: open438 description: Preço de abertura439 tag: InstrmInf/EqtyInf/FrstPric440 type: numeric441 - name: close442 description: Preço de fechamento443 tag: InstrmInf/EqtyInf/LastPric444 type: numeric445446 options_on_equities:447 tag: OptnOnEqtsInf448 fields:449 - name: refdate450 description: Data de referência451 tag: RptParams/RptDtAndTm/Dt452 type: date453 - name: symbol454 description: Código de negociação455 tag: InstrmInf/OptnOnEqtsInf/TckrSymb456 type: character457 - name: exercise_price458 description: Preço de exercício459 tag: InstrmInf/OptnOnEqtsInf/ExrcPric460 type: numeric461 - name: maturity_date462 description: Data de vencimento463 tag: InstrmInf/OptnOnEqtsInf/XprtnDt464 type: date465```466467**Key features:**468- `b3_read_bvbg028_xml` is a B3-specific step that parses XML into multiple DataFrames469- `datasets:` block defines multiple output datasets with different XML tags470- Each dataset has its own `fields:` with `tag:` attributes for XPath extraction471- `apply_fields_multi` applies field conversions to all datasets472473---474475### Example 4: ETL with SQL476477ETL template that loads upstream datasets and transforms via SQL query.478479```yaml480id: b3-equities-returns481description: Dataset de retornos de ações482483etl:484 pipeline:485 - step: sql_query486 datasets:487 - staging.b3-cotahist488 - staging.b3-equities-spot-market489 query: |490 WITH equity_symbols AS (491 SELECT DISTINCT symbol492 FROM 'staging.b3-equities-spot-market'493 WHERE security_category IN (1, 11, 13)494 )495 SELECT496 t.refdate,497 t.symbol,498 (t.close / LAG(t.close) OVER (PARTITION BY t.symbol ORDER BY t.refdate)) - 1 AS pct_return,499 LN(t.close / LAG(t.close) OVER (PARTITION BY t.symbol ORDER BY t.refdate)) AS log_return500 FROM 'staging.b3-cotahist' t501 INNER JOIN equity_symbols s ON t.symbol = s.symbol502 WHERE ROW_NUMBER() OVER (PARTITION BY t.symbol ORDER BY t.refdate) > 1503 ORDER BY t.refdate, t.symbol504505 - step: apply_fields506 errors: coerce507508writer:509 layer: staging510511fields:512 - name: refdate513 description: Data de referência514 type: date515 - name: symbol516 description: Símbolo do ativo517 type: character518 - name: pct_return519 description: Retorno percentual520 type: numeric521 - name: log_return522 description: Retorno logarítmico523 type: numeric524```525526**Key features:**527- `etl:` block with pipeline instead of `reader:`528- `sql_query` loads upstream datasets and executes SQL529- Uses CTEs, window functions, and JOINs for transformations530- Writes to `staging` layer instead of `input`531- No `downloader:` needed (data from upstream templates)