crowdwisdomtrading 0.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,148 @@
1
+ Metadata-Version: 2.4
2
+ Name: crowdwisdomtrading
3
+ Version: 0.2.0
4
+ Summary: Client for CrowdWisdom Trading crowd data: free weekly crowd score, pay per call with x402 or use a Bearer key; includes an ai-hedge-fund alpha model.
5
+ Author: CrowdWisdom Trading
6
+ License: MIT
7
+ Project-URL: Homepage, https://crowdwisdomtrading.com/x402?utm_source=pypi&utm_medium=package&utm_campaign=crowdwisdomtrading
8
+ Project-URL: Catalog, https://api.crowdwisdomtrading.com/x402/catalog
9
+ Project-URL: Docs, https://api.crowdwisdomtrading.com/docs
10
+ Keywords: x402,trading,crowd,sentiment,ai-hedge-fund,alpha
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: License :: OSI Approved :: MIT License
13
+ Classifier: Topic :: Office/Business :: Financial :: Investment
14
+ Requires-Python: >=3.10
15
+ Description-Content-Type: text/markdown
16
+ Requires-Dist: requests>=2.31
17
+ Provides-Extra: x402
18
+ Requires-Dist: x402[evm,requests]>=2.26; extra == "x402"
19
+ Requires-Dist: eth-account>=0.13; extra == "x402"
20
+ Provides-Extra: aihf
21
+ Requires-Dist: aihf>=2.7; extra == "aihf"
22
+ Provides-Extra: dev
23
+ Requires-Dist: pytest>=8; extra == "dev"
24
+ Requires-Dist: build; extra == "dev"
25
+ Requires-Dist: twine; extra == "dev"
26
+
27
+ # crowdwisdomtrading
28
+
29
+ Python client for [CrowdWisdom Trading](https://crowdwisdomtrading.com/x402?utm_source=pypi&utm_medium=readme&utm_campaign=crowdwisdomtrading) crowd data on US stocks:
30
+ free daily and weekly crowd scores, the per-source crowd consensus, the newest crowd setup (direction, entry,
31
+ targets, stops), today's setups, CrowdMap (crowd support / resistance levels) and point-in-time setup history.
32
+
33
+ Start free with no account. Pay per call with [x402](https://x402.org) (USDC on Base, no account) or use a
34
+ Bearer key from a plan. Includes a ready-made alpha model for [virattt/ai-hedge-fund](https://github.com/virattt/ai-hedge-fund).
35
+
36
+ ## Install
37
+
38
+ ```bash
39
+ pip install crowdwisdomtrading # free daily + weekly scores, Bearer-key mode
40
+ pip install "crowdwisdomtrading[x402]" # pay per call with a wallet
41
+ pip install "crowdwisdomtrading[aihf]" # + ai-hedge-fund model
42
+ ```
43
+
44
+ ## Try it free
45
+
46
+ ```python
47
+ from crowdwisdomtrading import Client
48
+
49
+ Client().daily_sentiment("NVDA") # today's crowd score
50
+ Client().weekly_sentiment("NVDA") # this week's
51
+ # {"data": {"cycle": "weekly", "week_of": "2026-11-02", "score": 42.0, "value": 0.42, "direction": "BULLISH",
52
+ # "confidence": 70, "mentions": 380, "sources_included": ["youtube", "x", "reddit"]}, ...}
53
+ ```
54
+
55
+ No key, no wallet. One crowd score from YouTube, X, StockTwits, Reddit, brokers, podcasts and newsletters: of the people
56
+ who took a side, long versus short (-100 to +100). Direction, confidence and the score per source are paid.
57
+ 50 free calls a day per IP address for each (daily and weekly counted separately), any tickers.
58
+
59
+ ## What it costs
60
+
61
+ | Call | Price | What you get |
62
+ |---|---|---|
63
+ | `daily_sentiment(ticker)` | free | Today's `ProCrowdSentimentScore` (-100 to +100) and `ProTraders` (distinct traders behind it; `low_coverage` under 10) |
64
+ | `weekly_sentiment(ticker)` | free | The same for the week (newest Monday) |
65
+ | `consensus(ticker)` | $0.10 | The score per source (YouTube, X, Reddit, brokers, podcasts, newsletters), mention breakdown, point-in-time history (`as_of`) |
66
+ | `setup_latest(ticker)` | $0.50 | Newest setup: direction, entry, 2 targets, 2 stops, confidence, risk/reward |
67
+ | `setups_today()` | $10.00 | Every setup of the newest day |
68
+ | `crowdmap(ticker)` | $0.30 | CrowdMap, the crowd's support / resistance levels, newest day: every level, role, trader count, impact, horizons |
69
+ | `history(ticker, from, to)` | $0.10 | Up to 200 past setups, as published at the time (backtest-safe) |
70
+ | `catalog()`, `sample()` | free | Price list; one setup at least 7 days old |
71
+
72
+ Live prices: `https://api.crowdwisdomtrading.com/x402/catalog`.
73
+
74
+ ## Paying
75
+
76
+ | Mode | Set | What it uses |
77
+ |---|---|---|
78
+ | wallet (pay per call) | `X402_WALLET_PRIVATE_KEY=0x...` with USDC on Base | `/x402/*` routes, receipt (tx hash) on every answer |
79
+ | key (plan) | `CWT_API_KEY=cwt_live_...` | `/v1/*` routes you already pay for monthly |
80
+
81
+ A key wins over a wallet. Fund the wallet with small amounts; the `exact` scheme pays only the quoted
82
+ price and nothing else.
83
+
84
+ ## Use
85
+
86
+ ```python
87
+ from crowdwisdomtrading import Client
88
+
89
+ c = Client() # reads the env vars above
90
+ c.daily_sentiment("NVDA") # free
91
+ c.weekly_sentiment("NVDA") # free
92
+ c.catalog() # free: prices, schemas, examples
93
+ c.sample() # free: one setup at least 7 days old
94
+ c.consensus("NVDA") # {"data": {"value": 0.42, "direction": "BULLISH", ...}, "as_of": ...}
95
+ c.consensus("NVDA", as_of="2026-11-04") # point-in-time: latest session on or before that day
96
+ c.setup_latest("NVDA") # direction, last_close, targets, stops, confidence, rr
97
+ c.setups_today()
98
+ c.crowdmap("NVDA") # CrowdMap: crowd support / resistance levels
99
+ c.history("NVDA", "2026-10-01", "2026-10-31") # only rows published by `to` (backtest-safe)
100
+ c.last_receipt # {"transaction": "0x...", "payer": ..., "network": ...} in wallet mode
101
+ ```
102
+
103
+ Every answer is `{"data": ..., "as_of": ..., "meta": {...}}`. Answers with `as_of` / `to` are cached on disk
104
+ (`~/.crowdwisdomtrading/cache`), live answers for 10 minutes, so a backtest pays once per (ticker, date). Errors
105
+ are never cached. `Client(cache=False)` disables it.
106
+
107
+ ## ai-hedge-fund
108
+
109
+ ```python
110
+ # hedge_fund/signals/__init__.py
111
+ from crowdwisdomtrading.aihf import CrowdConsensusModel
112
+ ALPHA_MODEL_REGISTRY["crowd"] = CrowdConsensusModel
113
+ ```
114
+
115
+ ```yaml
116
+ # hedge_fund/strategies/crowd-tilt.yaml
117
+ name: crowd-tilt
118
+ display_name: Crowd Tilt
119
+ models:
120
+ - name: crowd
121
+ weight: 1.0
122
+ - name: pead
123
+ blend:
124
+ mode: long_short
125
+ method: conviction_weighted
126
+ gross_target: 1.0
127
+ ```
128
+
129
+ `CrowdConsensusModel.predict(ticker, date, data_client)` returns a `Signal` with `value` in [-1, +1]
130
+ (crowd score / 100), `components` per source, and abstains (`value 0`, `metadata.abstained`) when the
131
+ latest crowd session is older than 10 days. It only asks for sessions dated on or before `date`.
132
+
133
+ ## Command line
134
+
135
+ ```bash
136
+ crowdwisdomtrading daily NVDA # free
137
+ crowdwisdomtrading weekly NVDA # free
138
+ crowdwisdomtrading catalog
139
+ crowdwisdomtrading consensus NVDA --as-of 2026-11-04
140
+ crowdwisdomtrading history NVDA --from 2026-10-01 --to 2026-10-31
141
+ ```
142
+
143
+ ## Notes
144
+
145
+ - Data is aggregated crowd opinion for research. Not investment advice. Payments are final; a failed
146
+ response is not charged.
147
+ - Networks: Base mainnet `eip155:8453` (default). `X402_NETWORK=eip155:84532` for Base Sepolia testing.
148
+ - Docs, prices and the paid plans: https://crowdwisdomtrading.com/x402?utm_source=pypi&utm_medium=readme&utm_campaign=crowdwisdomtrading
@@ -0,0 +1,122 @@
1
+ # crowdwisdomtrading
2
+
3
+ Python client for [CrowdWisdom Trading](https://crowdwisdomtrading.com/x402?utm_source=pypi&utm_medium=readme&utm_campaign=crowdwisdomtrading) crowd data on US stocks:
4
+ free daily and weekly crowd scores, the per-source crowd consensus, the newest crowd setup (direction, entry,
5
+ targets, stops), today's setups, CrowdMap (crowd support / resistance levels) and point-in-time setup history.
6
+
7
+ Start free with no account. Pay per call with [x402](https://x402.org) (USDC on Base, no account) or use a
8
+ Bearer key from a plan. Includes a ready-made alpha model for [virattt/ai-hedge-fund](https://github.com/virattt/ai-hedge-fund).
9
+
10
+ ## Install
11
+
12
+ ```bash
13
+ pip install crowdwisdomtrading # free daily + weekly scores, Bearer-key mode
14
+ pip install "crowdwisdomtrading[x402]" # pay per call with a wallet
15
+ pip install "crowdwisdomtrading[aihf]" # + ai-hedge-fund model
16
+ ```
17
+
18
+ ## Try it free
19
+
20
+ ```python
21
+ from crowdwisdomtrading import Client
22
+
23
+ Client().daily_sentiment("NVDA") # today's crowd score
24
+ Client().weekly_sentiment("NVDA") # this week's
25
+ # {"data": {"cycle": "weekly", "week_of": "2026-11-02", "score": 42.0, "value": 0.42, "direction": "BULLISH",
26
+ # "confidence": 70, "mentions": 380, "sources_included": ["youtube", "x", "reddit"]}, ...}
27
+ ```
28
+
29
+ No key, no wallet. One crowd score from YouTube, X, StockTwits, Reddit, brokers, podcasts and newsletters: of the people
30
+ who took a side, long versus short (-100 to +100). Direction, confidence and the score per source are paid.
31
+ 50 free calls a day per IP address for each (daily and weekly counted separately), any tickers.
32
+
33
+ ## What it costs
34
+
35
+ | Call | Price | What you get |
36
+ |---|---|---|
37
+ | `daily_sentiment(ticker)` | free | Today's `ProCrowdSentimentScore` (-100 to +100) and `ProTraders` (distinct traders behind it; `low_coverage` under 10) |
38
+ | `weekly_sentiment(ticker)` | free | The same for the week (newest Monday) |
39
+ | `consensus(ticker)` | $0.10 | The score per source (YouTube, X, Reddit, brokers, podcasts, newsletters), mention breakdown, point-in-time history (`as_of`) |
40
+ | `setup_latest(ticker)` | $0.50 | Newest setup: direction, entry, 2 targets, 2 stops, confidence, risk/reward |
41
+ | `setups_today()` | $10.00 | Every setup of the newest day |
42
+ | `crowdmap(ticker)` | $0.30 | CrowdMap, the crowd's support / resistance levels, newest day: every level, role, trader count, impact, horizons |
43
+ | `history(ticker, from, to)` | $0.10 | Up to 200 past setups, as published at the time (backtest-safe) |
44
+ | `catalog()`, `sample()` | free | Price list; one setup at least 7 days old |
45
+
46
+ Live prices: `https://api.crowdwisdomtrading.com/x402/catalog`.
47
+
48
+ ## Paying
49
+
50
+ | Mode | Set | What it uses |
51
+ |---|---|---|
52
+ | wallet (pay per call) | `X402_WALLET_PRIVATE_KEY=0x...` with USDC on Base | `/x402/*` routes, receipt (tx hash) on every answer |
53
+ | key (plan) | `CWT_API_KEY=cwt_live_...` | `/v1/*` routes you already pay for monthly |
54
+
55
+ A key wins over a wallet. Fund the wallet with small amounts; the `exact` scheme pays only the quoted
56
+ price and nothing else.
57
+
58
+ ## Use
59
+
60
+ ```python
61
+ from crowdwisdomtrading import Client
62
+
63
+ c = Client() # reads the env vars above
64
+ c.daily_sentiment("NVDA") # free
65
+ c.weekly_sentiment("NVDA") # free
66
+ c.catalog() # free: prices, schemas, examples
67
+ c.sample() # free: one setup at least 7 days old
68
+ c.consensus("NVDA") # {"data": {"value": 0.42, "direction": "BULLISH", ...}, "as_of": ...}
69
+ c.consensus("NVDA", as_of="2026-11-04") # point-in-time: latest session on or before that day
70
+ c.setup_latest("NVDA") # direction, last_close, targets, stops, confidence, rr
71
+ c.setups_today()
72
+ c.crowdmap("NVDA") # CrowdMap: crowd support / resistance levels
73
+ c.history("NVDA", "2026-10-01", "2026-10-31") # only rows published by `to` (backtest-safe)
74
+ c.last_receipt # {"transaction": "0x...", "payer": ..., "network": ...} in wallet mode
75
+ ```
76
+
77
+ Every answer is `{"data": ..., "as_of": ..., "meta": {...}}`. Answers with `as_of` / `to` are cached on disk
78
+ (`~/.crowdwisdomtrading/cache`), live answers for 10 minutes, so a backtest pays once per (ticker, date). Errors
79
+ are never cached. `Client(cache=False)` disables it.
80
+
81
+ ## ai-hedge-fund
82
+
83
+ ```python
84
+ # hedge_fund/signals/__init__.py
85
+ from crowdwisdomtrading.aihf import CrowdConsensusModel
86
+ ALPHA_MODEL_REGISTRY["crowd"] = CrowdConsensusModel
87
+ ```
88
+
89
+ ```yaml
90
+ # hedge_fund/strategies/crowd-tilt.yaml
91
+ name: crowd-tilt
92
+ display_name: Crowd Tilt
93
+ models:
94
+ - name: crowd
95
+ weight: 1.0
96
+ - name: pead
97
+ blend:
98
+ mode: long_short
99
+ method: conviction_weighted
100
+ gross_target: 1.0
101
+ ```
102
+
103
+ `CrowdConsensusModel.predict(ticker, date, data_client)` returns a `Signal` with `value` in [-1, +1]
104
+ (crowd score / 100), `components` per source, and abstains (`value 0`, `metadata.abstained`) when the
105
+ latest crowd session is older than 10 days. It only asks for sessions dated on or before `date`.
106
+
107
+ ## Command line
108
+
109
+ ```bash
110
+ crowdwisdomtrading daily NVDA # free
111
+ crowdwisdomtrading weekly NVDA # free
112
+ crowdwisdomtrading catalog
113
+ crowdwisdomtrading consensus NVDA --as-of 2026-11-04
114
+ crowdwisdomtrading history NVDA --from 2026-10-01 --to 2026-10-31
115
+ ```
116
+
117
+ ## Notes
118
+
119
+ - Data is aggregated crowd opinion for research. Not investment advice. Payments are final; a failed
120
+ response is not charged.
121
+ - Networks: Base mainnet `eip155:8453` (default). `X402_NETWORK=eip155:84532` for Base Sepolia testing.
122
+ - Docs, prices and the paid plans: https://crowdwisdomtrading.com/x402?utm_source=pypi&utm_medium=readme&utm_campaign=crowdwisdomtrading
@@ -0,0 +1,5 @@
1
+ """crowdwisdomtrading: client for CrowdWisdom Trading crowd data (free weekly crowd score, x402 pay-per-call or Bearer key)."""
2
+ from crowdwisdomtrading.client import Client, CrowdWisdomError, PaymentFailed
3
+
4
+ __version__ = "0.2.0"
5
+ __all__ = ["Client", "CrowdWisdomError", "PaymentFailed", "__version__"]
@@ -0,0 +1,138 @@
1
+ """CrowdConsensusModel: an ai-hedge-fund AlphaModel that buys CrowdWisdom crowd consensus per call.
2
+
3
+ Register it in hedge_fund/signals/__init__.py:
4
+ from crowdwisdomtrading.aihf import CrowdConsensusModel
5
+ ALPHA_MODEL_REGISTRY["crowd"] = CrowdConsensusModel
6
+ and add it to a strategy YAML (models: - name: crowd). It pays with the wallet in
7
+ X402_WALLET_PRIVATE_KEY (the same one ai-hedge-fund uses for Financial Datasets) or uses a
8
+ CWT_API_KEY Bearer key. predict() only ever asks for data dated on or before `date`
9
+ (point-in-time), and disk caching means one payment per (ticker, date) in a backtest.
10
+
11
+ Works without ai-hedge-fund installed (a small shim replaces Signal / QuantModel) so the
12
+ package can be tested standalone; with aihf installed the real classes are used.
13
+ """
14
+ from __future__ import annotations
15
+
16
+ from datetime import date, datetime
17
+ from typing import Any, ClassVar
18
+
19
+ from crowdwisdomtrading.client import Client
20
+
21
+ try: # real ai-hedge-fund classes
22
+ from hedge_fund.models import Signal # type: ignore
23
+ from hedge_fund.signals.base import QuantModel # type: ignore
24
+
25
+ HAVE_AIHF = True
26
+ except Exception: # pragma: no cover - shim path is tested explicitly below
27
+ HAVE_AIHF = False
28
+ from dataclasses import dataclass, field
29
+
30
+ @dataclass
31
+ class Signal: # type: ignore[no-redef]
32
+ model_name: str
33
+ ticker: str
34
+ date: str
35
+ value: float
36
+ reasoning: str | None = None
37
+ components: dict[str, float] = field(default_factory=dict)
38
+ metadata: dict[str, Any] = field(default_factory=dict)
39
+ horizon_days: int | None = None
40
+
41
+ class QuantModel: # type: ignore[no-redef]
42
+ investment_approach: ClassVar[str] = "long_short"
43
+ horizon_days: ClassVar[int] = 5
44
+
45
+
46
+ def _as_day(value: date | str) -> str:
47
+ if isinstance(value, datetime):
48
+ return value.date().isoformat()
49
+ if isinstance(value, date):
50
+ return value.isoformat()
51
+ return str(value)[:10]
52
+
53
+
54
+ class CrowdConsensusModel(QuantModel):
55
+ """Crowd consensus (-1..+1) from YouTube, X and Reddit mentions, as of the backtest date."""
56
+
57
+ investment_approach = "long_short"
58
+ horizon_days = 5
59
+
60
+ def __init__(
61
+ self,
62
+ client: Client | None = None,
63
+ *,
64
+ cycle: str | None = None,
65
+ max_staleness_days: int = 10,
66
+ neutral_band: float = 0.0,
67
+ ) -> None:
68
+ self._client = client
69
+ self._cycle = cycle
70
+ self._max_staleness_days = max_staleness_days
71
+ self._neutral_band = neutral_band
72
+
73
+ @property
74
+ def name(self) -> str:
75
+ return "crowd"
76
+
77
+ @property
78
+ def client(self) -> Client:
79
+ if self._client is None:
80
+ self._client = Client()
81
+ return self._client
82
+
83
+ def predict(self, ticker: str, date: date | str, data_client: Any = None) -> Signal: # noqa: A002
84
+ """Signal for `ticker` using only crowd sessions dated on or before `date`. data_client is unused."""
85
+ day = _as_day(date)
86
+ try:
87
+ answer = self.client.consensus(ticker, as_of=day, cycle=self._cycle)
88
+ except Exception as exc:
89
+ return self._abstain(ticker, day, f"crowd data unavailable: {type(exc).__name__}")
90
+ data = answer.get("data") or {}
91
+ session = data.get("session") or {}
92
+ value = data.get("value")
93
+ if value is None or not session.get("date"):
94
+ return self._abstain(ticker, day, "no crowd session on or before this date")
95
+ try:
96
+ age = (datetime.strptime(day, "%Y-%m-%d").date() - datetime.strptime(str(session["date"]), "%Y-%m-%d").date()).days
97
+ except ValueError:
98
+ return self._abstain(ticker, day, "malformed crowd session date")
99
+ if age > self._max_staleness_days:
100
+ return self._abstain(ticker, day, f"latest crowd session {session['date']} is {age} days old")
101
+ if abs(float(value)) < self._neutral_band:
102
+ value = 0.0
103
+ sources = data.get("sources") or {}
104
+ components = {k: float(v) / 100.0 for k, v in sources.items() if v is not None}
105
+ mentions = data.get("mentions") or {}
106
+ receipt = (answer.get("meta") or {}).get("payment") or {}
107
+ return Signal(
108
+ model_name=self.name,
109
+ ticker=ticker,
110
+ date=day,
111
+ value=max(-1.0, min(1.0, float(value))),
112
+ reasoning=(
113
+ f"Crowd {data.get('direction') or 'view'} {float(data.get('score') or 0):+.0f} on {session['date']} "
114
+ f"({session.get('cycle')}) from {mentions.get('total', '?')} mentions"
115
+ ),
116
+ components=components,
117
+ metadata={
118
+ "as_of": session["date"],
119
+ "cycle": session.get("cycle"),
120
+ "confidence": data.get("confidence"),
121
+ "mentions": mentions,
122
+ "latest_setup": data.get("latest_setup"),
123
+ "payment_tx": receipt.get("transaction"),
124
+ "cached": (answer.get("meta") or {}).get("cached"),
125
+ },
126
+ horizon_days=self.horizon_days,
127
+ )
128
+
129
+ def _abstain(self, ticker: str, day: str, reason: str) -> Signal:
130
+ return Signal(
131
+ model_name=self.name,
132
+ ticker=ticker,
133
+ date=day,
134
+ value=0.0,
135
+ reasoning=reason,
136
+ metadata={"abstained": True},
137
+ horizon_days=self.horizon_days,
138
+ )
@@ -0,0 +1,71 @@
1
+ """crowdwisdomtrading command line: quick checks and demos.
2
+
3
+ crowdwisdomtrading catalog
4
+ crowdwisdomtrading sample
5
+ crowdwisdomtrading daily NVDA (free: daily crowd score)
6
+ crowdwisdomtrading weekly NVDA (free: weekly crowd score)
7
+ crowdwisdomtrading consensus NVDA [--as-of 2026-11-04] [--cycle daily]
8
+ crowdwisdomtrading latest NVDA
9
+ crowdwisdomtrading crowdmap NVDA
10
+ crowdwisdomtrading history NVDA --from 2026-10-01 --to 2026-10-31
11
+ Pays with X402_WALLET_PRIVATE_KEY or uses CWT_API_KEY; --base overrides the API host.
12
+ """
13
+ from __future__ import annotations
14
+
15
+ import argparse
16
+ import json
17
+ import sys
18
+
19
+ from crowdwisdomtrading.client import Client, CrowdWisdomError
20
+ from crowdwisdomtrading.payment import PaymentFailed
21
+
22
+
23
+ def main(argv: list[str] | None = None) -> int:
24
+ parser = argparse.ArgumentParser(prog="crowdwisdomtrading", description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
25
+ parser.add_argument("command", choices=["catalog", "sample", "daily", "weekly", "consensus", "latest", "today", "crowdmap", "history"])
26
+ parser.add_argument("ticker", nargs="?")
27
+ parser.add_argument("--as-of", dest="as_of")
28
+ parser.add_argument("--cycle")
29
+ parser.add_argument("--from", dest="date_from")
30
+ parser.add_argument("--to", dest="date_to")
31
+ parser.add_argument("--base")
32
+ parser.add_argument("--no-cache", action="store_true")
33
+ args = parser.parse_args(argv)
34
+
35
+ client = Client(args.base, cache=not args.no_cache)
36
+ try:
37
+ if args.command == "catalog":
38
+ out = client.catalog()
39
+ elif args.command == "sample":
40
+ out = client.sample()
41
+ elif args.command == "today":
42
+ out = client.setups_today(args.cycle)
43
+ else:
44
+ if not args.ticker:
45
+ parser.error("ticker required")
46
+ if args.command == "daily":
47
+ out = client.daily_sentiment(args.ticker)
48
+ elif args.command == "weekly":
49
+ out = client.weekly_sentiment(args.ticker)
50
+ elif args.command == "consensus":
51
+ out = client.consensus(args.ticker, as_of=args.as_of, cycle=args.cycle)
52
+ elif args.command == "latest":
53
+ out = client.setup_latest(args.ticker, cycle=args.cycle)
54
+ elif args.command == "crowdmap":
55
+ out = client.crowdmap(args.ticker)
56
+ else:
57
+ if not (args.date_from and args.date_to):
58
+ parser.error("--from and --to required")
59
+ out = client.history(args.ticker, args.date_from, args.date_to, cycle=args.cycle)
60
+ except PaymentFailed as exc:
61
+ print(f"payment failed: {exc}", file=sys.stderr)
62
+ return 2
63
+ except CrowdWisdomError as exc:
64
+ print(f"error: {exc}", file=sys.stderr)
65
+ return 1
66
+ print(json.dumps(out, indent=2, default=str))
67
+ return 0
68
+
69
+
70
+ if __name__ == "__main__":
71
+ sys.exit(main())