feat(openinsider_top): add trade type tag in notifications and ensure absolute amount display
- Prefix titles and email lines with normalized trade tag (BUY/SALE/...)\n- Include amount as absolute value in lines; keep threshold logic unchanged
This commit is contained in:
@@ -161,14 +161,21 @@ class OpenInsiderTopCrawler(BaseCrawler):
|
|||||||
amount = self._parse_money(value_text)
|
amount = self._parse_money(value_text)
|
||||||
if amount is None or amount < self.min_amount:
|
if amount is None or amount < self.min_amount:
|
||||||
continue
|
continue
|
||||||
|
# Normalize trade type tag for notification clarity
|
||||||
|
tag = self._trade_tag(trans_type)
|
||||||
|
|
||||||
title = f"{ticker} {trans_type} - {insider} qty {qty} @ {price} value ${amount:,} on {trade_date}"
|
title = f"[{tag}] {ticker} - {insider} qty {qty} @ {price} value ${amount:,} on {trade_date}"
|
||||||
hash_src = f"{ticker}|{insider}|{trans_type}|{qty}|{price}|{trade_date}|{amount}|{url}"
|
hash_src = f"{ticker}|{insider}|{trans_type}|{qty}|{price}|{trade_date}|{amount}|{url}"
|
||||||
items.append({
|
items.append({
|
||||||
'title': title,
|
'title': title,
|
||||||
'link': url,
|
'link': url,
|
||||||
'scraped_at': datetime.now().isoformat(),
|
'scraped_at': datetime.now().isoformat(),
|
||||||
'hash': hashlib.md5(hash_src.encode('utf-8')).hexdigest()[:12],
|
'hash': hashlib.md5(hash_src.encode('utf-8')).hexdigest()[:12],
|
||||||
|
'trade_type': trans_type,
|
||||||
|
'trade_tag': tag,
|
||||||
|
'ticker': ticker,
|
||||||
|
'amount': amount,
|
||||||
|
'trade_date': trade_date,
|
||||||
})
|
})
|
||||||
|
|
||||||
return items
|
return items
|
||||||
@@ -234,9 +241,30 @@ class OpenInsiderTopCrawler(BaseCrawler):
|
|||||||
subject = f"OpenInsider 當日大額內部人交易(≥${self.min_amount:,}) - {len(items)} 筆"
|
subject = f"OpenInsider 當日大額內部人交易(≥${self.min_amount:,}) - {len(items)} 筆"
|
||||||
lines = []
|
lines = []
|
||||||
for it in items[:10]:
|
for it in items[:10]:
|
||||||
lines.append(f"• {it.get('title','')}")
|
tag = it.get('trade_tag') or 'TRADE'
|
||||||
|
ticker = it.get('ticker') or ''
|
||||||
|
amount = it.get('amount')
|
||||||
|
tdate = it.get('trade_date') or ''
|
||||||
|
if isinstance(amount, int):
|
||||||
|
line = f"• [{tag}] {ticker} ${amount:,} on {tdate}"
|
||||||
|
else:
|
||||||
|
line = f"• [{tag}] {it.get('title','')}"
|
||||||
|
lines.append(line)
|
||||||
body = (
|
body = (
|
||||||
f"發現 {len(items)} 筆符合金額門檻的內部人交易(OpenInsider):\n\n" + "\n".join(lines) + "\n\n"
|
f"發現 {len(items)} 筆符合金額門檻的內部人交易(OpenInsider):\n\n" + "\n".join(lines) + "\n\n"
|
||||||
f"抓取時間:{datetime.now().isoformat()}\n來源:\n- " + "\n- ".join(self.urls)
|
f"抓取時間:{datetime.now().isoformat()}\n來源:\n- " + "\n- ".join(self.urls)
|
||||||
)
|
)
|
||||||
return subject, body
|
return subject, body
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _trade_tag(trans_type: str) -> str:
|
||||||
|
t = (trans_type or '').lower()
|
||||||
|
if 'sale' in t or 'sell' in t:
|
||||||
|
return 'SALE'
|
||||||
|
if 'purchase' in t or 'buy' in t:
|
||||||
|
return 'BUY'
|
||||||
|
if 'option' in t:
|
||||||
|
return 'OPTION'
|
||||||
|
if 'gift' in t:
|
||||||
|
return 'GIFT'
|
||||||
|
return (trans_type or 'TRADE').upper()[:20]
|
||||||
|
Reference in New Issue
Block a user