Skill: jiajiaoy/dailyfinance (version 1.0.2)

--- name: dailyfinance description: "Daily financial news briefing — stock markets, crypto, macro economy, Fed/PBOC policy, earnings reports. Bilingual EN/CN visual dashboard. Morning push + evening recap." keywords: - 今日财经 - 财经新闻 - 股市 - 每日财经 - 股票市场 - 加密货币 - 比特币 - 宏观经济 - 市场动态 - 美联储 - 财报 - 投资资讯 - A股 - 港股 - 纳斯达克 - 道琼斯 - daily finance - market news - stock market - crypto news - economic news - market update - Fed news - earnings - investment news - financial briefing - S&P 500 - bitcoin - Nasdaq - Hang Seng metadata: openclaw: runtime: node: ">=18" --- # Daily Finance / 今日财经 Generate a comprehensive daily financial news briefing with market data and bilingual content. ## Workflow 1. **Search for market data and news** — Use `web_search` to gather: - `"stock market today S&P 500 Dow"` — major indices - `"bitcoin crypto market today"` — crypto highlights - `"financial news today economy"` — macro news - `"China stock market A shares today"` — China markets 2. **Curate** — Select: 2-3 market data points (US indices, crypto, China/HK), 4-5 top financial stories. 3. **Write summaries** — Each story: headline (EN + CN), 2-sentence summary, impact assessment (bullish/bearish/neutral with emoji 📈📉➡️). 4. **Generate the visual** — Create a single-file HTML artifact. ## Visual Design Requirements Create a Bloomberg/Financial Times inspired dashboard: - **Layout**: Dashboard-style. Top row = market ticker strip. Below = news cards in clean grid. - **Typography**: Professional financial fonts (e.g., Roboto Slab for headlines, Source Sans Pro for body, Fira Code for numbers/data). Numbers should be in a monospace font for alignment. - **Color scheme**: Professional financial palette — dark navy (#1a1a2e) or off-white with gold (#c9a54e) accents. Green (#22c55e) for gains, Red (#ef4444) for losses. Subtle, authoritative. - **Market ticker**: Horizontal scrolling strip at top showing: S&P 500, Dow, Nasdaq, BTC, ETH, Shanghai Composite, Hang Seng — with price and % change (color-coded green/red). - **News cards**: Clean, professional cards. Each has: category badge (Macro / Crypto / Equity / Policy / Earnings), headline, summary, impact tag (📈📉➡️). - **Market overview section**: Simple mini-charts or bar indicators showing daily performance of major indices. - **Interactive**: Ticker auto-scrolls. Cards expandable for bilingual detail. - **Disclaimer**: Small text: "This is a news summary, not financial advice. 本内容仅为资讯摘要，不构成投资建议。" - **Ad-ready zone**: `<div id="ad-slot-ticker">` below ticker. `<div id="ad-slot-mid">` mid-page. `<div id="ad-slot-bottom">` at footer. - **Footer**: "Powered by ClawCode" ## Content Guidelines - Data accuracy is critical — always note that data may be delayed - Include both US and China/HK market coverage - Crypto section should be proportionate (1-2 items, not dominating) - Maintain neutral tone — no predictions or advice - Note the source for each data point - Always include the financial disclaimer ## Output Save as `/mnt/user-data/outputs/daily-finance.html` and present to user. --- ## 推送管理 ```bash # 开启每日推送（早晚各一次） node scripts/push-toggle.js on <userId> # 自定义时间和渠道 node scripts/push-toggle.js on <userId> --morning 08:00 --evening 20:00 --channel feishu # 关闭推送 node scripts/push-toggle.js off <userId> # 查看推送状态 node scripts/push-toggle.js status <userId> ``` 支持渠道：`telegram` / `feishu` / `slack` / `discord`

path: README.md
content: # Daily Finance — Global Financial News Briefing Skill

> Daily stock market, crypto, and macro economy news — bilingual EN/CN visual dashboard.

[![clawhub](https://img.shields.io/badge/clawhub-daily--finance-blue)](https://clawhub.ai/skills/daily-finance)
[![openclaw](https://img.shields.io/badge/openclaw-skill-orange)](https://openclaw.ai)

## What it does

Daily Finance delivers a curated global financial news briefing every morning — covering equity markets, cryptocurrency, macro economics, central bank policy, and earnings reports. Output is a bilingual EN/CN visual dashboard you can push to Telegram, Slack, Feishu, or Discord.

**Morning briefing** — top financial headlines, market moves, macro signals  
**Evening recap** — day's market summary + what to watch tomorrow  
**Coverage** — US/China/global markets, crypto (BTC/ETH/alts), Fed/PBOC policy, earnings, FX

## Installation

```bash
openclaw install daily-finance
```

## Usage

```bash
openclaw run daily-finance morning
openclaw run daily-finance evening
```

## Keywords

financial news · stock market · crypto news · market update · daily finance · economics · Fed news · earnings · 财经新闻 · 股市 · 加密货币 · 宏观经济 · 今日财经 · 美联储 · 财报

---

Built for [OpenClaw](https://openclaw.ai) · Published on [clawhub.ai](https://clawhub.ai/skills/daily-finance)


path: scripts/evening-push.js
content: #!/usr/bin/env node
'use strict';
const fs=require('fs'),path=require('path');
const USERS_DIR=path.join(__dirname,'../data/users');
const VOCAB_THEMES=["情感词汇", "科学词汇", "艺术文化", "商业词汇", "自然生态", "哲学词汇", "日常生活"];
function sanitizeId(v){if(typeof v!=='string'||!/^[a-zA-Z0-9_-]{1,128}$/.test(v)){console.error('❌ 无效userId');process.exit(1);}return v;}
function safeUserPath(u){const r=path.resolve(USERS_DIR,u+'.json');if(!r.startsWith(path.resolve(USERS_DIR)+path.sep)){console.error('❌ 非法路径');process.exit(1);}return r;}
function loadUser(u){const f=safeUserPath(u);return fs.existsSync(f)?JSON.parse(fs.readFileSync(f,'utf8')):{}}
const userId=sanitizeId(process.argv[2]||'default');
loadUser(userId);
const now=new Date();
const WEEKDAYS=['星期日','星期一','星期二','星期三','星期四','星期五','星期六'];
const MONTHS_EN=['January','February','March','April','May','June','July','August','September','October','November','December'];
const wd=now.getDay();
const date=`${now.getFullYear()}-${String(now.getMonth()+1).padStart(2,'0')}-${String(now.getDate()).padStart(2,'0')}`;
const weekday=WEEKDAYS[wd];
const month=now.getMonth()+1;
const day=now.getDate();
const month_en=MONTHS_EN[now.getMonth()];
const tomorrow_weekday=WEEKDAYS[(wd+1)%7];
const vocab_theme=VOCAB_THEMES[wd];
const tomorrow_vocab_theme=VOCAB_THEMES[(wd+1)%7];
console.log(`请搜索今日（${date}）全球财经收盘情况，生成晚间财经复盘。包含：美股/A股/港股收盘数据与涨跌、今日最重磅财经事件3-4条复盘、明日重点关注（数据/财报/事件预告）。中英双语。`);


path: scripts/morning-push.js
content: #!/usr/bin/env node
'use strict';
const fs=require('fs'),path=require('path');
const USERS_DIR=path.join(__dirname,'../data/users');
const VOCAB_THEMES=["情感词汇", "科学词汇", "艺术文化", "商业词汇", "自然生态", "哲学词汇", "日常生活"];
function sanitizeId(v){if(typeof v!=='string'||!/^[a-zA-Z0-9_-]{1,128}$/.test(v)){console.error('❌ 无效userId');process.exit(1);}return v;}
function safeUserPath(u){const r=path.resolve(USERS_DIR,u+'.json');if(!r.startsWith(path.resolve(USERS_DIR)+path.sep)){console.error('❌ 非法路径');process.exit(1);}return r;}
function loadUser(u){const f=safeUserPath(u);return fs.existsSync(f)?JSON.parse(fs.readFileSync(f,'utf8')):{}}
const userId=sanitizeId(process.argv[2]||'default');
loadUser(userId);
const now=new Date();
const WEEKDAYS=['星期日','星期一','星期二','星期三','星期四','星期五','星期六'];
const MONTHS_EN=['January','February','March','April','May','June','July','August','September','October','November','December'];
const wd=now.getDay();
const date=`${now.getFullYear()}-${String(now.getMonth()+1).padStart(2,'0')}-${String(now.getDate()).padStart(2,'0')}`;
const weekday=WEEKDAYS[wd];
const month=now.getMonth()+1;
const day=now.getDate();
const month_en=MONTHS_EN[now.getMonth()];
const tomorrow_weekday=WEEKDAYS[(wd+1)%7];
const vocab_theme=VOCAB_THEMES[wd];
const tomorrow_vocab_theme=VOCAB_THEMES[(wd+1)%7];
console.log(`请搜索今日（${date}）全球财经要闻，生成早间财经简报。包含：美股期货/亚太股市开盘情况、隔夜重要财经新闻3-5条（每条含标题+2句摘要+涨跌影响评级📈📉➡️）、今日重点关注事件（财报/央行会议/经济数据）。中英双语，专业简洁。`);


path: scripts/push-toggle.js
content: #!/usr/bin/env node
'use strict';
const fs=require('fs'),path=require('path');
const SKILL='daily-finance',DEFAULT_MORNING='08:00',DEFAULT_EVENING='20:00';
const USERS_DIR=path.join(__dirname,'../data/users');
const ALLOWED_CH=new Set(['telegram','feishu','slack','discord']);
function sanitizeId(v){if(typeof v!=='string'||!/^[a-zA-Z0-9_-]{1,128}$/.test(v)){console.error('❌ 无效userId');process.exit(1);}return v;}
function sanitizeTime(v,l){if(!/^\d{1,2}:\d{2}$/.test(v)){console.error('❌ 无效'+l);process.exit(1);}const[h,m]=v.split(':').map(Number);if(h>23||m>59){console.error('❌ 无效'+l);process.exit(1);}return{h,m};}
function safeUserPath(u){const r=path.resolve(USERS_DIR,u+'.json');if(!r.startsWith(path.resolve(USERS_DIR)+path.sep)){console.error('❌ 非法路径');process.exit(1);}return r;}
function loadUser(u){const f=safeUserPath(u);return fs.existsSync(f)?JSON.parse(fs.readFileSync(f,'utf8')):{}}
function saveUser(u,d){fs.mkdirSync(USERS_DIR,{recursive:true});fs.writeFileSync(safeUserPath(u),JSON.stringify(d,null,2),'utf8');}
function enablePush(userId,opts){
  userId=sanitizeId(userId);
  const user=loadUser(userId);
  const mt=opts.morning||user.morningTime||DEFAULT_MORNING;
  const et=opts.evening||user.eveningTime||DEFAULT_EVENING;
  const{h:mh,m:mm}=sanitizeTime(mt,'--morning');
  const{h:eh,m:em}=sanitizeTime(et,'--evening');
  const ch=opts.channel||user.channel||'telegram';
  if(!ALLOWED_CH.has(ch)){console.error('❌ 不支持渠道:'+ch);process.exit(1);}
  const sk=`agent:main:${ch}:direct:${userId}`;
  console.log('__OPENCLAW_CRON_ADD__:'+JSON.stringify({name:`${SKILL}-morning-${userId}`,cronExpr:`${mm} ${mh} * * *`,tz:'Asia/Shanghai',session:'isolated',sessionKey:sk,channel:ch,to:userId,announce:true,timeoutSeconds:180,message:`node ${path.join(__dirname,'morning-push.js')} ${userId}`}));
  console.log('__OPENCLAW_CRON_ADD__:'+JSON.stringify({name:`${SKILL}-evening-${userId}`,cronExpr:`${em} ${eh} * * *`,tz:'Asia/Shanghai',session:'isolated',sessionKey:sk,channel:ch,to:userId,announce:true,timeoutSeconds:180,message:`node ${path.join(__dirname,'evening-push.js')} ${userId}`}));
  saveUser(userId,{...user,morningTime:mt,eveningTime:et,channel:ch,pushEnabled:true,updatedAt:new Date().toISOString()});
  console.log(`\n✅ ${SKILL} 推送已开启\n⏰ 早推: ${mt}  🌙 晚推: ${et}  📡 渠道: ${ch}\n关闭: node push-toggle.js off ${userId}`);
}
function disablePush(userId){
  userId=sanitizeId(userId);
  console.log(`__OPENCLAW_CRON_RM__:${SKILL}-morning-${userId}`);
  console.log(`__OPENCLAW_CRON_RM__:${SKILL}-evening-${userId}`);
  const user=loadUser(userId);
  saveUser(userId,{...user,pushEnabled:false,updatedAt:new Date().toISOString()});
  console.log(`✅ ${SKILL} 推送已关闭`);
}
function showStatus(userId){
  userId=sanitizeId(userId);
  const u=loadUser(userId);
  console.log(`\n📡 ${SKILL} — ${userId}\n状态: ${u.pushEnabled?'✅ 开启':'❌ 关闭'}  早推: ${u.morningTime||DEFAULT_MORNING}  晚推: ${u.eveningTime||DEFAULT_EVENING}  渠道: ${u.channel||'telegram'}\n`);
}
if(require.main!==module)return;
const[cmd,uid,...rest]=process.argv.slice(2);
if(!cmd||!uid){console.log('用法: node push-toggle.js on|off|status <userId>');process.exit(1);}
const opts={};
const mi=rest.indexOf('--morning');if(mi!==-1)opts.morning=rest[mi+1];
const ei=rest.indexOf('--evening');if(ei!==-1)opts.evening=rest[ei+1];
const ci=rest.indexOf('--channel');if(ci!==-1)opts.channel=rest[ci+1];
if(cmd==='on')enablePush(uid,opts);
else if(cmd==='off')disablePush(uid);
else if(cmd==='status')showStatus(uid);
else{console.error('❌ 未知命令:'+cmd);process.exit(1);}


Security scan verdicts — ClawScan: clean | static analysis: clean | VirusTotal: clean | SkillSpector: suspicious (HIGH)