Skip to main content

AGuAlpha Python Client

Official Python library for accessing AGuAlpha Investment Platform data.

Installation

pip install agualphacn

For async support:

pip install agualphacn[async]

For pandas integration:

pip install agualphacn[pandas]

Quick Start

Synchronous Usage

from agualphacn import AGuAlphaClient

# Initialize client
client = AGuAlphaClient(api_key="sk-your-api-key-here")

# Get positions data
positions = client.get_positions()
print(f"Total positions: {positions.total}")

for position in positions.data:
    print(f"Date: {position.date}, Outstanding: {position.outstanding}")

# Get ideas data
ideas = client.get_ideas(status="active")
print(f"Total active ideas: {ideas.total}")

for idea in ideas.data:
    print(f"Symbol: {idea.ticker_symbol}, Status: {idea.status}")

# Close the connection
client.close()

Using Context Manager

from agualphacn import AGuAlphaClient

with AGuAlphaClient(api_key="sk-your-api-key-here") as client:
    positions = client.get_positions(
        start_date="2024-01-01",
        end_date="2024-12-31"
    )
    print(f"Found {positions.total} positions")

Asynchronous Usage

import asyncio
from agualphacn import AGuAlphaAsyncClient

async def main():
    async with AGuAlphaAsyncClient(api_key="sk-your-api-key-here") as client:
        # Fetch data concurrently
        positions, ideas = await asyncio.gather(
            client.get_positions(),
            client.get_ideas(status="active")
        )

        print(f"Positions: {positions.total}, Ideas: {ideas.total}")

asyncio.run(main())

Pandas Integration

from agualphacn import AGuAlphaClient
from agualphacn.utils import positions_to_dataframe, export_to_csv

client = AGuAlphaClient(api_key="sk-your-api-key-here")

# Get positions and convert to DataFrame
positions_response = client.get_positions()
df = positions_to_dataframe(positions_response.data)

# Export to CSV
export_to_csv(positions_response.data, "positions.csv")

CSI Weights

Read csi_weights rows from the prices database filtered by index. The index parameter is required and must be one of these semantic names:

Value Index
CSI300 CSI 300
CSI500 CSI 500
CSI1000 CSI 1000
CSI2000 CSI 2000

Numeric codes (e.g. 000300) are rejected with HTTP 400.

Three mutually-exclusive date filters are supported:

from agualphacn import AGuAlphaClient

with AGuAlphaClient(api_key="sk-your-api-key-here") as client:
    # 1) Single day
    df = client.get_csi_weights_dataframe(index="CSI300", date="2026-07-15")

    # 2) Inclusive range
    df = client.get_csi_weights_dataframe(
        index="CSI300",
        start_date="2026-07-01",
        end_date="2026-07-15",
    )

    # 3) Rolling window — last 30 days up to today
    df = client.get_csi_weights_dataframe(index="CSI300", days=30)

    print(df.head())
    print(f"Shape: {df.shape}")

If you don't need pandas, drop the _dataframe suffix to get a list of dicts:

with AGuAlphaClient(api_key="sk-your-api-key-here") as client:
    rows = client.get_csi_weights(index="CSI300", days=30)
    print(f"Total records: {len(rows)}")

Adjusted Close Prices

Read adj_close rows from the prices database. membership and a date filter are both required. The membership selects a universe of tickers; choose from:

Value Universe
csi300 CSI 300 constituents
csi500 CSI 500 constituents
csi1000 CSI 1000 constituents
csi2000 CSI 2000 constituents
csi800 CSI 800 universe
csi1800 CSI 1800 universe
csi2800 CSI 2800 universe
x-csi Cross-listed / uncategorized (NULL membership)
a-shares All A-shares (tickers ending .SZ, .SH, .BJ)
hk Hong Kong listed (tickers ending .HK)
etf ETFs
from agualphacn import AGuAlphaClient

with AGuAlphaClient(api_key="sk-your-api-key-here") as client:
    # Single day for CSI 300 constituents
    df = client.get_adj_close_dataframe(membership="csi300", date="2026-07-15")

    # Inclusive range for HK tickers
    df = client.get_adj_close_dataframe(
        membership="hk",
        start_date="2026-07-01",
        end_date="2026-07-15",
    )
    print(df.head())

P-CIES (HK / CN)

Read p_cies rows from the prices database filtered by zone. zone is required and must be exactly "hk" or "cn".

from agualphacn import AGuAlphaClient

with AGuAlphaClient(api_key="sk-your-api-key-here") as client:
    df_hk = client.get_p_cies_dataframe(zone="hk")
    df_cn = client.get_p_cies_dataframe(zone="cn")

SP Rolling Index (Commodities)

Read commodity rolling-index data from the sp_rolling_index table (prices database). At least one filter is required: a product and/or a date filter.

from agualphacn import AGuAlphaClient

with AGuAlphaClient(api_key="sk-your-api-key-here") as client:
    # List available product codes first (e.g. ["CU", "RB", ...])
    products = client.get_sp_rolling_index_products()

    # All rows for one product
    rows = client.get_sp_rolling_index(product="CU")

    # Multiple products at once (no count limit)
    rows = client.get_sp_rolling_index(products=["CU", "RB"])

    # All products in a date range (no product = all commodities)
    rows = client.get_sp_rolling_index(start_date="2025-06-01", end_date="2025-06-30")

    # Product + date range (intersection)
    df = client.get_sp_rolling_index_dataframe(
        product="CU", start_date="2025-06-01", end_date="2025-06-30",
    )

    # Single day
    rows = client.get_sp_rolling_index(date="2025-06-15")

date and start_date/end_date are mutually exclusive. With no product and no date filter, the server returns 400 Bad Request.

Limit Events

Read limit_evts rows (daily limit-up / limit-down events) from the prices database. A date filter is required — either a single day or an inclusive range.

from agualphacn import AGuAlphaClient

with AGuAlphaClient(api_key="sk-your-api-key-here") as client:
    # Single day
    rows = client.get_limit_evts(date="2024-06-15")

    # Inclusive range as a pandas DataFrame
    df = client.get_limit_evts_dataframe(
        start_date="2024-06-01",
        end_date="2024-06-30",
    )
    print(df.head())

date and start_date/end_date are mutually exclusive. With no date filter, the server returns 400 Bad Request.

API Reference

AGuAlphaClient

__init__(api_key: str, base_url: str = "https://www.agualpha.cn/api")

Initialize the client with your API key.

get_positions(start_date: Optional[str] = None, end_date: Optional[str] = None) -> PositionsResponse

Get position data from subscribed analysts.

Parameters:

  • start_date (str): Filter by start date (YYYY-MM-DD format)
  • end_date (str): Filter by end date (YYYY-MM-DD format)

Returns: PositionsResponse

get_ideas(status: Optional[str] = None, direction: Optional[str] = None) -> IdeasResponse

Get trade ideas from subscribed analysts.

Parameters:

  • status (str): Filter by status ("active", "closed")
  • direction (str): Filter by direction ("long", "short")

Returns: IdeasResponse

get_csi_weights(index: str, date=None, start_date=None, end_date=None, days=None, page=None, page_size=None) -> list

Get CSI weights data filtered by index. index is required and must be one of CSI1000, CSI2000, CSI300, CSI500. At most one of the date filters may be applied: date (single day), start_date+end_date (range), or days (rolling window). Auto-paginates unless page is given.

Returns: list of dicts, each representing a row from the csi_weights table.

get_csi_weights_dataframe(index: str, date=None, start_date=None, end_date=None, days=None, page=None, page_size=None) -> pandas.DataFrame

Same parameters as get_csi_weights. Returns a DataFrame. Requires the pandas extra (pip install agualphacn[pandas]).

Returns: pandas.DataFrame

get_revision_fy2(date=None, start_date=None, end_date=None, days=None, ticker=None, type=None, page=None, page_size=None) -> list

Get revision_fy2 data from the cn_af database. A date filter is required — exactly one of date (single day), start_date+end_date (range), or days (rolling window). Optional: ticker (e.g. "000009.SZ") and type ("eps"/"np"/"sales", no value = all types). Auto-paginates unless page is given.

Returns: list of dicts, each representing a row from the revision_fy2 table.

get_revision_fy2_dataframe(date=None, start_date=None, end_date=None, days=None, ticker=None, type=None, page=None, page_size=None) -> pandas.DataFrame

Same parameters as get_revision_fy2. A date filter is required. Requires the pandas extra (pip install agualphacn[pandas]).

Returns: pandas.DataFrame

get_adj_close(membership: str, date=None, start_date=None, end_date=None, page=None, page_size=None) -> list

Get adj_close data from the prices database. membership is required (universe selector — see the table above); a date filter is required — either date (single day) or start_date+end_date (inclusive range, either bound optional). Auto-paginates unless page is given.

Returns: list of dicts, each representing a row from adj_close.

get_adj_close_dataframe(membership: str, date=None, start_date=None, end_date=None, page=None, page_size=None) -> pandas.DataFrame

Same parameters as get_adj_close. membership and a date filter are required. Requires the pandas extra (pip install agualphacn[pandas]).

Returns: pandas.DataFrame

get_p_cies(zone: str, page=None, page_size=None) -> list

Get p_cies data from the prices database. zone is required and must be "hk" or "cn". Auto-paginates unless page is given.

Returns: list of dicts, each representing a row from p_cies.

get_p_cies_dataframe(zone: str, page=None, page_size=None) -> pandas.DataFrame

Same parameters as get_p_cies. zone is required. Requires the pandas extra (pip install agualphacn[pandas]).

get_sp_rolling_index(product=None, products=None, date=None, start_date=None, end_date=None, page=None, page_size=None) -> list

Get commodity rolling-index rows from the prices database. At least one of product(s) or a date filter is required. date and start_date/end_date are mutually exclusive.

  • product (single string) and products (list) are merged; you can pass either or both.
  • With no product(s) and no date filter, the server returns 400.

Returns: list of dicts, each representing a row from sp_rolling_index.

get_sp_rolling_index_dataframe(product=None, products=None, date=None, start_date=None, end_date=None, page=None, page_size=None) -> pandas.DataFrame

Same parameters as get_sp_rolling_index. Requires the pandas extra.

get_sp_rolling_index_products() -> list

Return all distinct product codes available in sp_rolling_index, sorted ascending. Useful for discovering which values are valid for the product(s) parameter.

Returns: pandas.DataFrame

get_limit_evts(date=None, start_date=None, end_date=None, page=None, page_size=None) -> list

Get limit_evts rows (daily limit-up / limit-down events) from the prices database. A date filter is required: either date (single day) or start_date/end_date (inclusive range). date and start_date/end_date are mutually exclusive.

Returns: list of dicts, each representing a row from limit_evts.

get_limit_evts_dataframe(date=None, start_date=None, end_date=None, page=None, page_size=None) -> pandas.DataFrame

Same parameters as get_limit_evts. Requires the pandas extra.

Response Models

PositionsResponse

  • success (bool): Request success status
  • total (int): Total number of records
  • data (List[Position]): List of position objects
  • error (str, optional): Error message if failed

IdeasResponse

  • success (bool): Request success status
  • total (int): Total number of records
  • data (List[Idea]): List of idea objects
  • error (str, optional): Error message if failed

Error Handling

from agualphacn import AGuAlphaClient
from agualphacn.exceptions import APIError, AuthenticationError, RateLimitError

try:
    client = AGuAlphaClient(api_key="invalid-key")
    positions = client.get_positions()
except AuthenticationError:
    print("Invalid API key")
except RateLimitError as e:
    print(f"Too many requests: {e}")
except APIError as e:
    print(f"API error: {e}")

Rate Limiting

The data API limits each API key to 4 requests per second (sliding 1-second window). When the limit is exceeded, the server returns HTTP 429 Too Many Requests with a Retry-After header indicating how many seconds to wait. The SDK surfaces this as a RateLimitError (subclass of APIError), so you can catch it and back off:

import time
from agualphacn import AGuAlphaClient
from agualphacn.exceptions import RateLimitError

client = AGuAlphaClient(api_key="your-api-key")
while True:
    try:
        data = client.get_positions()
        break
    except RateLimitError as e:
        time.sleep(1)

Pagination

The server caps each request at 2000 rows. By default, the SDK auto-paginates — calling get_positions(), get_ideas(), get_csi_weights(index=...), or get_revision_fy2(date=...) with no page argument walks every page and returns the full result set in one call. Each underlying page request counts against your 4 req/s limit, so large tables cost multiple requests.

If you want a single page, pass page (1-indexed) and optionally page_size (server caps at 2000):

# Fetch only the first 500 rows of revision_fy2 in the last 30 days
rows = client.get_revision_fy2(days=30, page=1, page_size=500)

When paginating manually, the response object exposes page, page_size, total_pages, and has_more so you can loop pages yourself:

page = 1
all_rows = []
while True:
    resp = client.get_positions(page=page, page_size=1000)
    all_rows.extend(resp.data)
    if not resp.has_more:
        break
    page += 1

Requirements

  • Python 3.8+
  • requests 2.28.0+

License

MIT License

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

agualphacn-0.1.0.tar.gz (22.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

agualphacn-0.1.0-py3-none-any.whl (21.1 kB view details)

Uploaded Python 3

File details

Details for the file agualphacn-0.1.0.tar.gz.

File metadata

  • Download URL: agualphacn-0.1.0.tar.gz
  • Upload date:
  • Size: 22.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.5

File hashes

Hashes for agualphacn-0.1.0.tar.gz
Algorithm Hash digest
SHA256 5bf102a3d2d84f816fb090282cfd72cb8dc485f82cbddd28b8040d2b99e1f827
MD5 3c1fda524b7d6badd5007211ee6add86
BLAKE2b-256 eea52a4bc01095c1fab25edfd9ea25c93f51884dc418efbc4c8113fae068049a

See more details on using hashes here.

File details

Details for the file agualphacn-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: agualphacn-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 21.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.5

File hashes

Hashes for agualphacn-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 84d81d99a3597c86ae435814dfdf3233b25f0bc4698b4d4e8ae285f9cfb97483
MD5 20d731dc8a4bcdbae3c38ef7844670ff
BLAKE2b-256 442d508c3a424f8e492644ee40c36f7ef8e481a25f6c728bad7b2f6691f4a59f

See more details on using hashes here.

Release history Release notifications | RSS feed

0.2.0

2 files

This release

0.1.0 This release

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page