[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6XC7KXJYRY2ZFRQGCV3T596":3,"skill-same:01M6XC7KXJYRY2ZFRQGCV3T596":76},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":15,"categories":16,"keywords":27,"publishedAt":45,"linkOnly":46,"markdownContent":47,"markdownBody":48,"frontMatter":49,"refName":50,"commitSha":51,"skillDirectory":52,"forksCount":13,"repositoryHtmlUrl":53,"repositoryHomepageUrl":6,"ownerHtmlUrl":54,"ownerBlogUrl":6,"ownerDescription":6,"updatedAt":55,"install":56,"resources":69},"01M6XC7KXJYRY2ZFRQGCV3T596","finnhub-stock-api",null,"Integrate with Finnhub Stock API for real-time and historical stock market data. Covers quote fetching, company profiles, and WebSocket streaming.","UF-gzj\u002Fopenspace-claude-evolution","UF-gzj","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F272393507?v=4","01M6XBCZB755P01VVYGQWPYZY3","01M6XBCZFJA5AREA17WGETA3FW",0,"MIT","https:\u002F\u002Fgithub.com\u002FUF-gzj\u002Fopenspace-claude-evolution\u002Fblob\u002Fmain\u002Fshowcase\u002Fskills\u002Ffinnhub-stock-api\u002FSKILL.md",[17,22],{"categoryNo":18,"categoryName":19,"taxonomyType":20,"taxonomyTypeDesc":21},"01JBSEEDCAT000000000000010","后端与接口","SCENARIO","使用场景",{"categoryNo":23,"categoryName":24,"taxonomyType":25,"taxonomyTypeDesc":26},"01JBSEEDCAT000000000000030","开发工程师","PROFESSION","适用职业",[28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44],"finnhub stock api","api","finnhub","stock","quote","company","for","market data","profiles","with","streaming","time","Market","integrate","real-time","websocket","data","2026-11-10 10:12:30",false,"---\nname: finnhub-stock-api\ndescription: Integrate with Finnhub Stock API for real-time and historical stock market data. Covers quote fetching, company profiles, and WebSocket streaming.\n---\n\n# Finnhub Stock API Integration\n\nFinnhub provides free stock market data (REST + WebSocket). API key required (free tier: 60 calls\u002Fmin).\n\n- **Docs**: https:\u002F\u002Ffinnhub.io\u002Fdocs\u002Fapi\n- **Base URL**: `https:\u002F\u002Ffinnhub.io\u002Fapi\u002Fv1`\n- **Auth**: Query param `token=YOUR_API_KEY`\n- **Rate limit**: 60 requests\u002Fminute (free), 300\u002Fmin (premium)\n- **CORS**: Unknown (use server-side proxy)\n\n## Key Endpoints\n\n### 1. Stock Quote (Real-Time)\n\n```\nGET \u002Fquote?symbol=AAPL&token=API_KEY\n```\n\nResponse:\n```json\n{\n  \"c\": 178.72,     \u002F\u002F Current price\n  \"d\": 2.38,       \u002F\u002F Change (absolute)\n  \"dp\": 1.35,      \u002F\u002F Change percent\n  \"h\": 179.60,     \u002F\u002F High price of the day\n  \"l\": 175.10,     \u002F\u002F Low price of the day\n  \"o\": 176.15,     \u002F\u002F Open price\n  \"pc\": 176.34,    \u002F\u002F Previous close\n  \"t\": 1702569600  \u002F\u002F Timestamp\n}\n```\n\n### 2. Company Profile\n\n```\nGET \u002Fstock\u002Fprofile2?symbol=AAPL&token=API_KEY\n```\n\nResponse:\n```json\n{\n  \"country\": \"US\",\n  \"currency\": \"USD\",\n  \"exchange\": \"NASDAQ NMS - GLOBAL MARKET\",\n  \"name\": \"Apple Inc\",\n  \"ticker\": \"AAPL\",\n  \"ipo\": \"1980-12-12\",\n  \"marketCapitalization\": 2794000,\n  \"logo\": \"https:\u002F\u002Fstatic.finnhub.io\u002Flogo\u002F...\"\n}\n```\n\n### 3. Stock Candles (Historical)\n\n```\nGET \u002Fstock\u002Fcandle?symbol=AAPL&resolution=D&from=1609459200&to=1640995200&token=API_KEY\n```\n\n- `resolution`: 1, 5, 15, 30, 60, D, W, M\n- `from` \u002F `to`: UNIX timestamps\n\nResponse:\n```json\n{\n  \"c\": [130.21, 131.96, ...],  \u002F\u002F Close prices\n  \"h\": [131.74, 132.63, ...],  \u002F\u002F Highs\n  \"l\": [128.50, 130.23, ...],  \u002F\u002F Lows\n  \"o\": [130.92, 130.87, ...],  \u002F\u002F Opens\n  \"v\": [143301900, ...],       \u002F\u002F Volumes\n  \"t\": [1609459200, ...],      \u002F\u002F Timestamps\n  \"s\": \"ok\"                     \u002F\u002F Status\n}\n```\n\n### 4. Market News\n\n```\nGET \u002Fnews?category=general&token=API_KEY\n```\n\nCategories: `general`, `forex`, `crypto`, `merger`\n\n## Frontend Service Implementation\n\n```typescript\n\u002F\u002F src\u002Fservices\u002Fstock-market.ts\nimport { createCircuitBreaker } from '@\u002Futils\u002Fcircuit-breaker';\n\nexport interface StockQuote {\n  symbol: string;\n  name: string;\n  price: number | null;\n  change: number | null;\n  changePercent: number | null;\n  high: number | null;\n  low: number | null;\n  sparkline?: number[];\n}\n\nconst quoteBreaker = createCircuitBreaker\u003CStockQuote[]>({\n  name: 'StockQuotes',\n  cacheTtlMs: 30_000,\n});\n\nconst DEFAULT_SYMBOLS = ['AAPL', 'MSFT', 'GOOGL', 'AMZN', 'TSLA', 'NVDA', 'META'];\n\nexport async function fetchStockQuotes(symbols = DEFAULT_SYMBOLS): Promise\u003CStockQuote[]> {\n  return quoteBreaker.execute(async () => {\n    const resp = await fetch(`\u002Fapi\u002Fstocks?symbols=${symbols.join(',')}`);\n    if (!resp.ok) throw new Error(`HTTP ${resp.status}`);\n    const data = await resp.json();\n    return data.quotes.map((q: any) => ({\n      symbol: q.symbol,\n      name: q.name || q.symbol,\n      price: q.price ?? q.c ?? null,\n      change: q.change ?? q.d ?? null,\n      changePercent: q.changePercent ?? q.dp ?? null,\n      high: q.high ?? q.h ?? null,\n      low: q.low ?? q.l ?? null,\n    }));\n  }, []);\n}\n```\n\n## Alternative APIs (from public-apis)\n\nIf Finnhub rate limits are a concern, these alternatives are available:\n\n| API | Free Tier | Notes |\n|-----|-----------|-------|\n| **Alpha Vantage** | 25 req\u002Fday (free) | `https:\u002F\u002Fwww.alphavantage.co\u002F` |\n| **Twelve Data** | 800 req\u002Fday | `https:\u002F\u002Ftwelvedata.com\u002F` |\n| **Financial Modeling Prep** | 250 req\u002Fday | `https:\u002F\u002Ffinancialmodelingprep.com\u002F` |\n| **Yahoo Finance** (via RapidAPI) | Varies | `https:\u002F\u002Fwww.yahoofinanceapi.com\u002F` |\n| **Polygon** | 5 req\u002Fmin (free) | `https:\u002F\u002Fpolygon.io\u002F` |\n| **IEX Cloud** | 50k credits\u002Fmonth | `https:\u002F\u002Fiexcloud.io\u002F` |\n| **Marketstack** | 100 req\u002Fmonth | `https:\u002F\u002Fmarketstack.com\u002F` |\n\n## Server-Side Proxy\n\nThe frontend should **never** call Finnhub directly. Use the API proxy pattern (see `api-proxy-endpoint` skill) to:\n1. Hide the API key\n2. Batch multiple symbol requests\n3. Add edge caching (30s `Cache-Control`)\n4. Handle rate limit errors gracefully (return cached data)\n\n","# Finnhub Stock API Integration\n\nFinnhub provides free stock market data (REST + WebSocket). API key required (free tier: 60 calls\u002Fmin).\n\n- **Docs**: https:\u002F\u002Ffinnhub.io\u002Fdocs\u002Fapi\n- **Base URL**: `https:\u002F\u002Ffinnhub.io\u002Fapi\u002Fv1`\n- **Auth**: Query param `token=YOUR_API_KEY`\n- **Rate limit**: 60 requests\u002Fminute (free), 300\u002Fmin (premium)\n- **CORS**: Unknown (use server-side proxy)\n\n## Key Endpoints\n\n### 1. Stock Quote (Real-Time)\n\n```\nGET \u002Fquote?symbol=AAPL&token=API_KEY\n```\n\nResponse:\n```json\n{\n  \"c\": 178.72,     \u002F\u002F Current price\n  \"d\": 2.38,       \u002F\u002F Change (absolute)\n  \"dp\": 1.35,      \u002F\u002F Change percent\n  \"h\": 179.60,     \u002F\u002F High price of the day\n  \"l\": 175.10,     \u002F\u002F Low price of the day\n  \"o\": 176.15,     \u002F\u002F Open price\n  \"pc\": 176.34,    \u002F\u002F Previous close\n  \"t\": 1702569600  \u002F\u002F Timestamp\n}\n```\n\n### 2. Company Profile\n\n```\nGET \u002Fstock\u002Fprofile2?symbol=AAPL&token=API_KEY\n```\n\nResponse:\n```json\n{\n  \"country\": \"US\",\n  \"currency\": \"USD\",\n  \"exchange\": \"NASDAQ NMS - GLOBAL MARKET\",\n  \"name\": \"Apple Inc\",\n  \"ticker\": \"AAPL\",\n  \"ipo\": \"1980-12-12\",\n  \"marketCapitalization\": 2794000,\n  \"logo\": \"https:\u002F\u002Fstatic.finnhub.io\u002Flogo\u002F...\"\n}\n```\n\n### 3. Stock Candles (Historical)\n\n```\nGET \u002Fstock\u002Fcandle?symbol=AAPL&resolution=D&from=1609459200&to=1640995200&token=API_KEY\n```\n\n- `resolution`: 1, 5, 15, 30, 60, D, W, M\n- `from` \u002F `to`: UNIX timestamps\n\nResponse:\n```json\n{\n  \"c\": [130.21, 131.96, ...],  \u002F\u002F Close prices\n  \"h\": [131.74, 132.63, ...],  \u002F\u002F Highs\n  \"l\": [128.50, 130.23, ...],  \u002F\u002F Lows\n  \"o\": [130.92, 130.87, ...],  \u002F\u002F Opens\n  \"v\": [143301900, ...],       \u002F\u002F Volumes\n  \"t\": [1609459200, ...],      \u002F\u002F Timestamps\n  \"s\": \"ok\"                     \u002F\u002F Status\n}\n```\n\n### 4. Market News\n\n```\nGET \u002Fnews?category=general&token=API_KEY\n```\n\nCategories: `general`, `forex`, `crypto`, `merger`\n\n## Frontend Service Implementation\n\n```typescript\n\u002F\u002F src\u002Fservices\u002Fstock-market.ts\nimport { createCircuitBreaker } from '@\u002Futils\u002Fcircuit-breaker';\n\nexport interface StockQuote {\n  symbol: string;\n  name: string;\n  price: number | null;\n  change: number | null;\n  changePercent: number | null;\n  high: number | null;\n  low: number | null;\n  sparkline?: number[];\n}\n\nconst quoteBreaker = createCircuitBreaker\u003CStockQuote[]>({\n  name: 'StockQuotes',\n  cacheTtlMs: 30_000,\n});\n\nconst DEFAULT_SYMBOLS = ['AAPL', 'MSFT', 'GOOGL', 'AMZN', 'TSLA', 'NVDA', 'META'];\n\nexport async function fetchStockQuotes(symbols = DEFAULT_SYMBOLS): Promise\u003CStockQuote[]> {\n  return quoteBreaker.execute(async () => {\n    const resp = await fetch(`\u002Fapi\u002Fstocks?symbols=${symbols.join(',')}`);\n    if (!resp.ok) throw new Error(`HTTP ${resp.status}`);\n    const data = await resp.json();\n    return data.quotes.map((q: any) => ({\n      symbol: q.symbol,\n      name: q.name || q.symbol,\n      price: q.price ?? q.c ?? null,\n      change: q.change ?? q.d ?? null,\n      changePercent: q.changePercent ?? q.dp ?? null,\n      high: q.high ?? q.h ?? null,\n      low: q.low ?? q.l ?? null,\n    }));\n  }, []);\n}\n```\n\n## Alternative APIs (from public-apis)\n\nIf Finnhub rate limits are a concern, these alternatives are available:\n\n| API | Free Tier | Notes |\n|-----|-----------|-------|\n| **Alpha Vantage** | 25 req\u002Fday (free) | `https:\u002F\u002Fwww.alphavantage.co\u002F` |\n| **Twelve Data** | 800 req\u002Fday | `https:\u002F\u002Ftwelvedata.com\u002F` |\n| **Financial Modeling Prep** | 250 req\u002Fday | `https:\u002F\u002Ffinancialmodelingprep.com\u002F` |\n| **Yahoo Finance** (via RapidAPI) | Varies | `https:\u002F\u002Fwww.yahoofinanceapi.com\u002F` |\n| **Polygon** | 5 req\u002Fmin (free) | `https:\u002F\u002Fpolygon.io\u002F` |\n| **IEX Cloud** | 50k credits\u002Fmonth | `https:\u002F\u002Fiexcloud.io\u002F` |\n| **Marketstack** | 100 req\u002Fmonth | `https:\u002F\u002Fmarketstack.com\u002F` |\n\n## Server-Side Proxy\n\nThe frontend should **never** call Finnhub directly. Use the API proxy pattern (see `api-proxy-endpoint` skill) to:\n1. Hide the API key\n2. Batch multiple symbol requests\n3. Add edge caching (30s `Cache-Control`)\n4. Handle rate limit errors gracefully (return cached data)\n\n",{"name":5,"description":7},"main","0650921d63895de3997bc81f1ff1d0ac67032072","showcase\u002Fskills\u002Ffinnhub-stock-api","https:\u002F\u002Fgithub.com\u002FUF-gzj\u002Fopenspace-claude-evolution","https:\u002F\u002Fgithub.com\u002FUF-gzj","2026-04-16 09:31:03",{"source":8,"skillName":5,"commands":57,"prompt":67,"zipAvailable":68},[58,61,64],{"tool":59,"command":60},"npx","npx skills add UF-gzj\u002Fopenspace-claude-evolution --skill finnhub-stock-api",{"tool":62,"command":63},"bunx","bunx skills add UF-gzj\u002Fopenspace-claude-evolution --skill finnhub-stock-api",{"tool":65,"command":66},"pnpm","pnpm dlx skills add UF-gzj\u002Fopenspace-claude-evolution --skill finnhub-stock-api","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002FUF-gzj\u002Fopenspace-claude-evolution\u002Fblob\u002Fmain\u002Fshowcase\u002Fskills\u002Ffinnhub-stock-api\u002FSKILL.md",true,[70],{"path":71,"resourceType":72,"resourceTypeDesc":73,"sizeBytes":74,"sourceHtmlUrl":75},".skill_id","OTHER","其他",32,"https:\u002F\u002Fgithub.com\u002FUF-gzj\u002Fopenspace-claude-evolution\u002Fblob\u002Fmain\u002Fshowcase\u002Fskills\u002Ffinnhub-stock-api\u002F.skill_id",[77,101,117,126,152,168],{"skillNo":78,"name":79,"nameZh":6,"description":80,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":81,"categories":82,"keywords":83,"publishedAt":45},"01M6XCCXD3NCM2YKR3WNGBASPC","write-special-chars-ts-check","Workaround for write_file failures caused by special characters (apostrophes, backticks, template literals) using a Python heredoc script, plus a reliable TypeScript type-checking step that filters output to only the newly-written files to avoid being misled by pre-existing errors.","https:\u002F\u002Fgithub.com\u002FUF-gzj\u002Fopenspace-claude-evolution\u002Fblob\u002Fmain\u002Fshowcase\u002Fskills\u002Fwrite-special-chars-ts-check\u002FSKILL.md",[],[84,85,86,87,88,89,90,91,34,92,93,94,95,96,97,98,99,100],"check","write","write special chars ts check","typescript","filters","characters","Existing","type-checking","errors","script","output","type","files","only","template","file","python",{"skillNo":102,"name":103,"nameZh":6,"description":104,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":105,"categories":106,"keywords":107,"publishedAt":45},"01M6XCCT7E3J922Q345PBGSHPN","write-special-chars-readback","Workaround for write_file failures caused by special characters (apostrophes, backticks, template literals) using a Python heredoc script, with mandatory post-write verification via read_file and cleanup of \u002Ftmp helper scripts.","https:\u002F\u002Fgithub.com\u002FUF-gzj\u002Fopenspace-claude-evolution\u002Fblob\u002Fmain\u002Fshowcase\u002Fskills\u002Fwrite-special-chars-readback\u002FSKILL.md",[],[108,109,85,99,110,100,111,112,113,114,115,98,116,37,89,34,93],"readback","write special chars readback","helper","post","via","scripts","cleanup","read","verification",{"skillNo":118,"name":119,"nameZh":6,"description":120,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":121,"categories":122,"keywords":123,"publishedAt":45},"01M6XCCMQX1R8B6FECWB3P63T7","write-special-chars-heredoc","Workaround for write_file failures caused by special characters (apostrophes, backticks, template literals) by using a Python heredoc script executed via shell.","https:\u002F\u002Fgithub.com\u002FUF-gzj\u002Fopenspace-claude-evolution\u002Fblob\u002Fmain\u002Fshowcase\u002Fskills\u002Fwrite-special-chars-heredoc\u002FSKILL.md",[],[124,85,89,125,93,112,98,99,100,34],"write special chars heredoc","shell",{"skillNo":127,"name":128,"nameZh":6,"description":129,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":130,"categories":131,"keywords":135,"publishedAt":45},"01M6XCCG41M994JJEX6VN52PEP","worldmonitor-reference","Curated architecture index of the WorldMonitor open-source dashboard. Reference for extracting patterns — vanilla TypeScript, Panel class hierarchy, service layer, CSS grid, API edge functions, refresh scheduler, and 60+ data source integrations.","https:\u002F\u002Fgithub.com\u002FUF-gzj\u002Fopenspace-claude-evolution\u002Fblob\u002Fmain\u002Fshowcase\u002Fskills\u002Fworldmonitor-reference\u002FSKILL.md",[132],{"categoryNo":133,"categoryName":134,"taxonomyType":25,"taxonomyTypeDesc":26},"01JBSEEDCAT000000000000033","数据分析师",[136,137,138,139,140,87,141,142,143,144,145,34,146,147,148,149,150,151,29,44],"reference","worldmonitor","worldmonitor reference","architecture","dashboard","css","scheduler","layer","hierarchy","source","extracting","panel","patterns","edge functions","integrations","open",{"skillNo":153,"name":154,"nameZh":6,"description":155,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":156,"categories":157,"keywords":158,"publishedAt":45},"01M6XCCCHWNKG2W4VH9E6A10HF","virtual-list","Implement efficient virtual scrolling for rendering large lists with DOM recycling, chunk-based rendering, and performance optimizations","https:\u002F\u002Fgithub.com\u002FUF-gzj\u002Fopenspace-claude-evolution\u002Fblob\u002Fmain\u002Fshowcase\u002Fskills\u002Fvirtual-list\u002FSKILL.md",[],[159,160,161,162,34,163,37,164,165,166,167],"virtual list","list","virtual","chunk","dom","rendering","recycling","implement","performance",{"skillNo":169,"name":170,"nameZh":6,"description":171,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":6,"repositoryNo":12,"starsCount":13,"licenseSpdxId":14,"licenseFileUrl":6,"sourceHtmlUrl":172,"categories":173,"keywords":174,"publishedAt":45},"01M6XCC7X8PKMR2DEW91XGHYSV","verify-directory-structure","Diagnose and resolve file access issues by first verifying the directory structure.","https:\u002F\u002Fgithub.com\u002FUF-gzj\u002Fopenspace-claude-evolution\u002Fblob\u002Fmain\u002Fshowcase\u002Fskills\u002Fverify-directory-structure\u002FSKILL.md",[],[175,176,177,178,179,180,99,181,182,183],"directory","verify directory structure","structure","verify","access","first","issues","diagnose","file access"]