Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/build_test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ jobs:
python-version-file: ".python-version"

- name: Install uv
uses: astral-sh/setup-uv@v7
uses: astral-sh/setup-uv@v8.1.0

- name: Install dependencies and build package
run: |
Expand Down Expand Up @@ -54,7 +54,7 @@ jobs:
python-version: ${{ matrix.python-version }}

- name: Install uv
uses: astral-sh/setup-uv@v7
uses: astral-sh/setup-uv@v8.1.0
with:
enable-cache: true
python-version: ${{ matrix.python-version }}
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@ __pycache__
/.idea/
.claude/
.vscode/
.fresh/
273 changes: 103 additions & 170 deletions exabel/client/api/export_api.py

Large diffs are not rendered by default.

43 changes: 43 additions & 0 deletions exabel/examples/entity_search_example.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
"""Resolve company resource names with the SDK's entity search helpers.

Most Data API calls take a resource_name like
entityTypes/company/entities/F_XXXXXX-E.
The SDK exposes a search service on client.entity_api.search that maps
common external identifiers onto the matching entity.

This example demonstrates the three lookups callers reach for most:

1. By Bloomberg ticker — exact, returns one entity per ticker.
2. By MIC and ticker — disambiguates a plain ticker across exchanges.
3. By free text — fuzzy match across name and ticker fields, sorted by
relevance. Returns multiple candidates per query.

See client.api.search_service for other search methods.
"""

from pprint import pprint

from exabel import ExabelClient


def main() -> None:
"""Run the three search variants and pretty-print the raw mappings each returns."""
client = ExabelClient()

print("\n# Bloomberg ticker")
pprint(client.entity_api.search.company_by_bloomberg_ticker("AAPL US", "GOOGL US"))

print("\n# MIC and ticker")
pprint(
client.entity_api.search.company_by_mic_and_ticker(
("XNAS", "AAPL"),
("XNAS", "GOOGL"),
)
)

print("\n# Free text (fuzzy, can match multiple candidates per query)")
pprint(client.entity_api.search.companies_by_text("Apple, Inc.", "Alphabet"))


if __name__ == "__main__":
main()
16 changes: 8 additions & 8 deletions exabel/scripts/export_signals_v2.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,14 +70,14 @@ class ExportSignalsV2(BaseScript):
def __init__(self, argv: Sequence[str], description: str):
super().__init__(argv, description)
self.parser.add_argument(
"--signal",
"--signals",
nargs="+",
required=False,
default=[],
type=str,
help=(
"Signal label(s) to export from the library. "
"At least one of --signal or --expression must be given."
"At least one of --signals or --expression must be given."
),
)
self.parser.add_argument(
Expand All @@ -95,13 +95,13 @@ def __init__(self, argv: Sequence[str], description: str):
)
entity_group = self.parser.add_mutually_exclusive_group(required=True)
entity_group.add_argument(
"--resource-name",
"--entities",
nargs="+",
type=str,
help="Entity resource name(s) to evaluate the signal(s) for.",
)
entity_group.add_argument(
"--tag",
"--tags",
nargs="+",
type=str,
help="Tag(s) whose entities should be evaluated.",
Expand Down Expand Up @@ -136,9 +136,9 @@ def __init__(self, argv: Sequence[str], description: str):

def run_script(self, client: ExabelClient, args: argparse.Namespace) -> None:
start_time = time()
signals: list[str | DerivedSignal] = [*args.signal, *args.expression]
signals: list[str | DerivedSignal] = [*args.signals, *args.expression]
if not signals:
self.parser.error("at least one of --signal or --expression must be provided")
self.parser.error("at least one of --signals or --expression must be provided")
signal_labels = [s if isinstance(s, str) else s.label for s in signals]
print("Downloading signal(s):", ", ".join(signal_labels))

Expand All @@ -148,8 +148,8 @@ def run_script(self, client: ExabelClient, args: argparse.Namespace) -> None:
content = client.export_api.export_signals_v2_bytes(
signals,
file_format=file_format,
resource_name=args.resource_name,
tag=args.tag,
entities=args.entities,
tags=args.tags,
start_time=args.start_date,
end_time=args.end_date,
version=args.known_time,
Expand Down
Loading