Metadata-Version: 2.4
Name: ganaka-sdk
Version: 0.1.2
Summary: Python SDK for Ganaka - broker access and strategy tracking
Project-URL: Homepage, https://github.com/ganakadev/sdk
Project-URL: Repository, https://github.com/ganakadev/sdk
Project-URL: Issues, https://github.com/ganakadev/sdk/issues
Author-email: Ganaka Dev <dev@ganaka.dev>
License-Expression: MIT
License-File: LICENSE
Keywords: broker,dhan,sdk,strategy,trading
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Office/Business :: Financial :: Investment
Requires-Python: >=3.11
Requires-Dist: httpx>=0.27
Description-Content-Type: text/markdown

# Ganaka Python SDK

Python SDK for [Ganaka](https://github.com/ganakadev/sdk) — trade through brokers like Dhan, track strategy execution on the Ganaka platform, and store run results for analysis.

## Requirements

- Python 3.11+
- [uv](https://docs.astral.sh/uv/) (recommended) or pip

## Install

From this repository (development):

```bash
cd sdk
uv sync
```

Editable install:

```bash
uv pip install -e .
```

## Configuration

| Variable / argument | Description |
|---------------------|-------------|
| `api_key` | Ganaka platform API key (Bearer token) |
| `broker` | Broker adapter name (`dhan`) |
| `broker_config.client_id` | Dhan client ID |
| `broker_config.access_token` | Dhan access token (refreshed daily) |
| `base_url` | Ganaka API URL (default: `http://localhost:3000`) |

## Usage

```python
import asyncio

from ganaka import Ganaka


async def main() -> None:
    async with Ganaka(
        api_key="gk_your_key",
        broker="dhan",
        broker_config={
            "client_id": "1100000001",
            "access_token": "eyJ...",
        },
    ) as client:
        # Broker: portfolio and orders
        positions = await client.broker.get_positions()
        holdings = await client.broker.get_holdings()

        order = await client.broker.place_order(
            security_id="1333",
            exchange_segment="NSE_EQ",
            transaction_type="BUY",
            quantity=1,
            product_type="INTRADAY",
            order_type="LIMIT",
            price=2500.0,
        )

        # Strategy tracking: log the flow of a run
        run_id = await client.strategy.start_run(
            strategy_id="breakout-nifty",
            metadata={"timeframe": "5m"},
        )
        await client.strategy.log_entry(
            signal="BUY",
            instrument="RELIANCE",
            reason="breakout above resistance",
            extra={"price": 2500.0},
        )
        await client.strategy.end_run(status="completed")

        # Persist final results to Ganaka database
        await client.results.save(
            strategy_id="breakout-nifty",
            pnl=1200.50,
            run_id=run_id,
            trades=[{"symbol": "RELIANCE", "side": "BUY", "qty": 1}],
            metrics={"win_rate": 0.62},
        )


if __name__ == "__main__":
    asyncio.run(main())
```

## Project layout

```
src/ganaka/
├── client.py          # Ganaka main client
├── broker/            # Broker adapters (Dhan)
├── strategy/          # Strategy run tracking
├── storage/           # Result persistence
└── exceptions.py      # SDK error types
```

## Development

```bash
uv sync
uv run pre-commit install --hook-type commit-msg
```

If hook install fails with `core.hooksPath` set (e.g. after removing Husky), run `git config --local --unset-all core.hooksPath` and retry.

```bash
uv run python -c "from ganaka import Ganaka; print(Ganaka)"
```

### Commit messages

This project uses [Conventional Commits](https://www.conventionalcommits.org/). After installing pre-commit hooks, every commit message is validated locally:

```bash
feat: add Dhan order book helper
fix: handle expired access token
chore: update dependencies
```

Dry-run a release locally (no changes made):

```bash
uv run semantic-release -v --noop version
```

## Releasing

Releases are triggered manually via the **Release** GitHub Actions workflow (`workflow_dispatch`).

1. Seed a baseline tag before the first release: `git tag v0.1.0 && git push origin v0.1.0`
2. Merge conventional commits to `main`
3. Run the **Release** workflow in GitHub Actions

The workflow uses [python-semantic-release](https://python-semantic-release.readthedocs.io/) to bump `pyproject.toml`, update `CHANGELOG.md`, create a git tag and GitHub Release, then publish to PyPI with `uv publish`.

### GitHub secrets

| Secret | Purpose |
|--------|---------|
| `GITHUB_TOKEN` | Auto-provided; tags and GitHub Releases |
| `UV_PUBLISH_TOKEN` | PyPI API token for `uv publish` |

Optional: configure [PyPI Trusted Publisher](https://docs.pypi.org/trusted-publishers/) to avoid storing a token.

## License

MIT
