Metadata-Version: 2.4
Name: wq-alphagen
Version: 0.1.0
Summary: Random and template-based alpha expression generator for WorldQuant Brain.
Author-email: Tanakrit <9tanakrit.work@gmail.com>
License: MIT
License-File: LICENSE
Keywords: alpha,brain,factor,quant,trading,worldquant
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Financial and Insurance Industry
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Office/Business :: Financial :: Investment
Requires-Python: >=3.10
Provides-Extra: dev
Requires-Dist: build>=1.0; extra == 'dev'
Requires-Dist: pytest>=7.0; extra == 'dev'
Requires-Dist: twine>=4.0; extra == 'dev'
Description-Content-Type: text/markdown

# wq-alphagen

Random and template-based alpha expression generator for [WorldQuant Brain](https://platform.worldquantbrain.com/).

Generates Brain-syntax alpha expressions like `rank(ts_delta(close, 5))` from your own data field catalog and operator reference. Built-in deduplication, type-safe sampling, and syntax validation.

## Install

```bash
pip install wq-alphagen
```

## What you need to supply

This package does **not** ship WorldQuant Brain's data — you bring your own:

- `data_fields.csv` — your Brain data fields with columns: `field, type, coverage, dataset_category, alpha_count`
- `wq_operators.json` — your Brain operator reference in the schema expected by `alphagen` (see `examples/example_operators.json` for the shape)

See the `examples/` directory for tiny demo files you can use to try the package immediately.

## Quick start

### Template mode (inline)

```python
from alphagen import AlphaGenerator

with AlphaGenerator(
    fields_path="data_fields.csv",
    operators_path="wq_operators.json",
    history_path="alpha_history.jsonl",   # or None to skip persistence
) as gen:
    result = gen.from_template_strings([
        "rank(ts_delta({x:MATRIX}, {d:int=5,10,20}))",
        "zscore(ts_mean({x:MATRIX}, {d:int=20,60}))",
        "group_neutralize({x:MATRIX}, {g:GROUP})",
    ], per_template=50)

    print(result.summary())
    for expr in result.alphas:
        print(expr)
```

### Template mode (from file)

```python
result = gen.from_templates("alpha_templates.txt", per_template=50)
```

A template file is plain text — one expression per line, `#` for comments. Placeholders use `{name:TYPE}` or `{name:TYPE=value1,value2,...}`:

| Placeholder            | Picks                                          |
| ---------------------- | ---------------------------------------------- |
| `{x:MATRIX}`           | a random MATRIX field                          |
| `{x:MATRIX=close,vwap}`| from this explicit allow-list                  |
| `{g:GROUP}`            | a random GROUP field                           |
| `{d:int}`              | from `[5, 10, 20, 60, 120, 250]`               |
| `{d:int=5,10,20}`      | from this explicit list                        |
| `{a:float=0.5,1.0,2.0}`| random float pick                              |
| `{f:bool}`             | random `true`/`false`                          |
| `{s:string=a,b,c}`     | random string pick (explicit values required)  |

Same `{name:...}` repeated in one expression reuses the same value.

### Random mode

```python
with AlphaGenerator(
    fields_path="data_fields.csv",
    operators_path="wq_operators.json",
) as gen:
    result = gen.random(count=100, max_depth=3, min_operators=2)
```

### One-liners

```python
from alphagen import generate_random, generate_from_template_strings

result = generate_random(
    count=100,
    fields_path="data_fields.csv",
    operators_path="wq_operators.json",
    seed=42,
)

result = generate_from_template_strings(
    ["rank({x:MATRIX})", "zscore({x:MATRIX})"],
    per_template=20,
    fields_path="data_fields.csv",
    operators_path="wq_operators.json",
)
```

## Result object

Every generator method returns a `GenerationResult`:

```python
result.alphas       # list[str] — NEW unique alpha expressions
result.invalid      # [(expr, [errors]), ...] from validator
result.attempts     # total samples drawn
result.duplicates   # how many were already in history
result.seconds      # wall-clock time
result.summary()    # one-line stat string
```

Iterate directly: `for expr in result: ...`.

## Filtering the field pool

```python
gen = AlphaGenerator(
    fields_path="data_fields.csv",
    operators_path="wq_operators.json",
    min_coverage=0.7,                           # require coverage >= 70%
    max_alpha_count=1000,                       # avoid heavily-mined fields
    datasets=("pv1", "fnd6"),                   # only these datasets
    exclude_datasets=("analyst1", "analyst4"),  # never these datasets
    validate=True,                              # auto syntax-check (default)
    seed=42,                                    # reproducible
)
```

## Standalone validator

```python
from alphagen import AlphaValidator

v = AlphaValidator("wq_operators.json", "data_fields.csv")
errors = v.validate("rank(ts_delta(close, 5))")    # [] = OK
```

## History store

The dedup store can be used on its own:

```python
from alphagen import AlphaHistory

with AlphaHistory("alpha_history.jsonl") as h:
    h.add("rank(close)")           # True — new
    h.add("rank( close )")         # False — same expression, whitespace-insensitive
    print(len(h), "unique alphas")
```

## License

MIT — see [LICENSE](LICENSE).

## Disclaimer

This is an independent open-source tool. It is not affiliated with, endorsed by, or sponsored by WorldQuant.
