This stock Twitter ticker pulse builds a daily Markdown and CSV board for a small stock watchlist from public X posts. It searches each cashtag, merges the latest and top posts, and drops spam and off-topic posts. This page shows a stored sample; there is no hosted demo.
The problem
Cashtag searches on X mix useful posts with invite-link spam, paid group pitches and long watchlist posts that tag a dozen tickers. Reading every ticker by hand each morning takes time, and it is hard to compare tickers when the noise level differs. You need one board with counts per ticker, the posts worth opening and a clear note on what was dropped.
What the app does
- Searches X once for the latest posts and once for the top posts of each ticker.
- Merges duplicate posts and sorts each one into kept, spam or off-topic.
- Reports per ticker the returned, spam, off-topic and kept counts, the most-liked and most-viewed post and co-mentioned cashtags.
- Adds a rough count of bullish and bearish words, labelled as a word count, not a signal.
- Writes a Markdown board, board and posts CSV files, a cost CSV and the raw responses.
The board is a sample of recent posts, not total volume. It is not investment advice.
How it works
- Normalize the watchlist. Tickers come from the command line or a file. They are uppercased, deduplicated and limited to 1 to 6 letters, with up to 10 tickers per run.
- Plan the calls. Each ticker gets a
Latestcall and aTopcall toGET /twitterwith the query$TICKER. The Top call adds a start date (3 days back by default) and a minimum of 50 likes. - Merge and filter. Posts are deduplicated by ID. Invite links, group pitches and posts with 5 or more distinct cashtags count as spam. A post without the searched cashtag counts as off-topic. Spam wins when both apply.
- Build the board. Kept posts feed the counts, the Latest time span, the Top window and the word tilt. Every unique post, with its drop reasons, goes to the posts CSV.
- Record cost. Each call reads
X-Desearch-Cost-Usd. Calls are not retried automatically, because a retry could be billed again.
The code
This verbatim excerpt from ticker_pulse.py applies the spam and off-topic rules to one post:
def spam_reasons(post, ticker, max_cashtags=5):
"""List matching spam rules and the off-topic rule."""
text = (post.get('text') or '').lower()
urls = (post.get('entities') or {}).get('urls') or []
searchable = text + ' ' + ' '.join((str(u.get('expanded_url') or '').lower() for u in urls))
tags = cashtags(post)
reasons = []
if any((link in searchable for link in INVITE_LINKS)):
reasons.append('invite_link')
if any((phrase in text for phrase in GROUP_PHRASES)):
reasons.append('group_pitch')
if len(tags) >= max_cashtags:
reasons.append('watchlist_spam')
if ticker.upper() not in tags:
reasons.append('off_topic')
return reasons
def filter_group(reasons):
"""Assign one group, with spam taking precedence over off-topic."""
if any(reason in ('invite_link', 'group_pitch', 'watchlist_spam') for reason in reasons):
return 'spam'
return 'off_topic' if 'off_topic' in reasons else 'kept'Endpoints
GET /twitter
Example output
From sample-output.md in the source folder. It was re-rendered offline with account names anonymized from the raw file of a live run on 2026-10-28.
| Ticker | Returned | Spam | Off-topic | Kept | Latest span (h) | Top post likes | Tilt |
| --- | --- | --- | --- | --- | --- | --- | --- |
| NVDA | Latest: 20; Top: 20 | 7 (17.5%) | 0 (0.0%) | 33 | 0.7 | 1184 | more bullish words |
| TSLA | Latest: 20; Top: 20 | 1 (2.5%) | 10 (25.0%) | 29 | 5.6 | 347 | more bullish words |
| SOFI | Latest: 20; Top: 20 | 0 (0.0%) | 0 (0.0%) | 40 | 5.5 | 1732 | more bullish words |Counts come from the latest 20 public X posts returned per ticker and sort, not all mentions. The tilt column is a rough word count.
Run it yourself
Get the Python examples and open the ticker pulse folder. Use Python 3.10 or newer; there are no packages to install. Create an API key in the console and set DESEARCH_API_KEY, or pass a private key file with --key-file PATH.
git clone https://github.com/Desearch-ai/desearch-py-examples
cd desearch-py-examples/stock-twitter-ticker-pulseThese commands are copied from the source README. The dry run prints the planned calls without a key or API calls.
python3 ticker_pulse.py NVDA TSLA AMD
python3 ticker_pulse.py '$NVDA' --watchlist watchlist.txt --count 30 --out output
python3 ticker_pulse.py NVDA --dry-run
python3 ticker_pulse.py NVDA --top-only --key-file /path/to/private-keyUse --watchlist FILE for a longer list, --max-cashtags to tune the watchlist spam rule and --anonymize to replace account names in the Markdown and CSV files.
What it costs
On 2026-10-28, every X search call with count=20 cost $0.003, read from the X-Desearch-Cost-Usd header. One ticker (Latest and Top) cost $0.006. A 3-ticker run made 6 calls, cost $0.018 and took about 55 seconds. Use --latest-only or --top-only to halve the calls. These are dated measurements, not current price quotes. Check pricing before a larger run.
Ideas to extend it
- Run the board every morning and keep each day's CSV to compare spam and off-topic shares over time.
- Add a column that links the most-liked post for each ticker in a team digest.
- Tune
--max-cashtagsfor watchlists where list posts are useful. - Combine the board with a news search for the same tickers.
