stock-recognizer-gliner2-large

LoRA adapter (v18) for fastino/gliner2-large-v1 (486M parameters) that finds stock tickers and company names in informal financial text such as Reddit and X posts.

Smaller bases are faster; the table below compares accuracy and speed across the sibling stock-recognizer-* repos.

Code, data pipeline and benchmark: StephanAkkerman/stock-recognizer-model. It is the NER backbone of the stock-recognizer engine, which resolves the extracted entities to actual tickers.

Intended uses

Retail investors write about stocks in slang, with cashtags ($GME), bare symbols (AMC), lowercase symbols (nvda) and company names (Goldman Sachs) mixed together. Regexes and general-purpose NER models handle this poorly. This model tags those mentions, which you can use to:

  • track which stocks a community is discussing over time,
  • link posts, comments or news replies to tickers,
  • feed a sentiment or trend pipeline with the right symbols,
  • pre-label more data for further training.

It is built for English, informal, post-length text. It only extracts mentions; it does not resolve ambiguous symbols (AA can be Alcoa or American Airlines) and it is not financial advice.

Entities

label what it captures
ticker A stock market ticker symbol, usually 1-5 letters, often preceded by a dollar sign (e.g., $AAPL, TSLA). MUST NOT be option expiry months (JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC), Reddit slang acronyms (DYOR, NFA, DD, YOLO, FOMO, TLDR, IMO, AMA, NGL, AH), or financial regulatory bodies (SEC, FINRA, DTC, CSRC, RSA).
company The name of a corporation, hedge fund, or business entity. MUST NOT be an uppercase ticker symbol, an index, or generic finance terms.

Labeling follows one policy: a span that is a valid ticker symbol is a ticker ($AMC, AMC, gme), a name that resolves to a company is a company (AMC Theatres, Nvidia). Government agencies, financial metrics and media outlets are not labeled.

Examples

Actual output of this model (threshold 0.75); empty labels are omitted.

Input:  $GME is mooning but Apple Inc. might crash tomorrow
Output: {"ticker": ["$GME"], "company": ["Apple Inc."]}
Input:  Bought more nvda and AMC calls, Goldman Sachs says Meta is a buy
Output: {"ticker": ["nvda", "AMC"], "company": ["Meta"]}
Input:  YOLO'd my savings into $tsla, DD says PT 400. NFA
Output: {"ticker": ["$tsla"]}
Input:  The SEC is investigating, but CNBC says Microsoft earnings were fine.
Output: {"company": ["Microsoft"]}
Input:  Just a normal post about my day, nothing to see here.
Output: {}

Results (held-out test set 4715f5eb653032f6, 74 documents)

Scoring is set-based: an entity counts as found if the model finds it at least once in a document, however often it is repeated. This mirrors the engine, which returns a deduplicated set of tickers per text. Case, whitespace and a leading $ are ignored when comparing.

label precision recall F1
ticker 83.9% 86.2% 85.1%
company 75.4% 95.5% 84.3%
overall 78.5% 91.7% 84.6%

Inference: 36.84 ms/doc (chunked, cuda).

Choosing a model

All sizes are trained on the same data and scored on the same test set.

model base params overall F1 ms/doc
GLiNER2.5 Small 74M 87.1% 7.36
GLiNER2.5 Base 194M 84.6% 15.49
GLiNER2 Base 208M 84.1% 16.04
GLiNER2 Large (this repo) 486M 84.6% 36.84

Usage

Needs pip install "gliner2>=2" peft huggingface_hub.

import json

from gliner2 import AutoExtractor
from huggingface_hub import snapshot_download
from peft import PeftConfig, PeftModel

adapter_dir = snapshot_download("StephanAkkerman/stock-recognizer-gliner2-large", revision="v18")
cfg = json.load(open(f"{adapter_dir}/recognizer_config.json"))
model = AutoExtractor.from_pretrained(cfg["base_model"])

# The adapter holds LoRA weights only; clearing task_type stops PEFT from
# expecting a classifier head. Merging gives a plain extractor.
peft_config = PeftConfig.from_pretrained(adapter_dir)
peft_config.task_type = None
model = PeftModel.from_pretrained(model, adapter_dir, config=peft_config)
model = model.merge_and_unload()

result = model.extract_entities(
    "$GME is mooning but Apple Inc. might crash tomorrow",
    cfg["entity_descriptions"],
    threshold=cfg["threshold"],
)
print(result)

Recommended threshold: 0.75. Lower it to find more entities (higher recall), raise it for fewer, more certain ones.

The engine loads this adapter for you through recognize_ai().

Training data

StephanAkkerman/wallstreetbets-ner: posts from r/wallstreetbets and related communities, pre-labeled and reviewed by hand in Label Studio. Train/validation split is 90/10 by post, with 150-word chunks overlapping by 40 words; chunks without entities are kept as negative examples.

This adapter saw 5925 training chunks and 238 validation chunks.

parameter value
LoRA rank / alpha / dropout 32 / 64 / 0.1
Target modules key_proj, dense, query_proj, value_proj
Epochs up to 10 (early stopping)
Batch size 4 (effective 8)
Encoder / task LR 2e-05 / 0.0005
Max sequence length 256

Limitations

  • Trained on Reddit; performance on news, research or formal text may differ.
  • Occasional boundary errors on multi-word company names.
  • Low-frequency or newly listed tickers may be missed, and unseen company names may be mislabeled.
  • Extracts mentions only; ambiguous symbols are not resolved.

Citation

@misc{akkerman_stock_recognizer,
  author = {Stephan Akkerman},
  title  = {stock-recognizer-model},
  year   = {2026},
  url    = {https://github.com/StephanAkkerman/stock-recognizer-model}
}
Downloads last month
18
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support

Model tree for StephanAkkerman/stock-recognizer-gliner2-large

Adapter
(19)
this model

Dataset used to train StephanAkkerman/stock-recognizer-gliner2-large