找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

180

积分

0

好友

21

主题
发表于 2025-10-10 22:33:22 | 查看: 14| 回复: 0
本帖最后由 linuxx 于 2025-10-10 22:40 编辑

OpenStock dashboard

OpenStock dashboard


上周五收盘后,我照例打开Wind查看持仓股票的技术面,突然想起这个月的订阅费又要扣了。作为量化研究员,我们对实时数据的依赖就像程序员离不开GitHub,但每年动辄几万的数据服务费,真的是必需品吗?

直到我在GitHub上发现了OpenStock——一个完全开源的股票追踪平台。它不仅提供实时行情、技术图表、公司基本面,还支持个性化自选股和AI新闻摘要。最关键的是:完全免费,代码开源,可以部署在自己的服务器上。

这让我想起Open Dev Society的那句宣言:"Technology should belong to everyone"。在金融数据被商业巨头垄断的今天,这样的项目显得格外珍贵。

今天就带大家深入体验这个项目,看看它能否成为我们日常研究的得力助手。

关注「alphaFind」公众号,获取更多量化交易开源项目解析


一、实战体验:从注册到盯盘的完整流程

1.1 首次登录:个性化投资画像

打开OpenStock的第一印象是简洁——没有花里胡哨的广告,没有弹窗推销,只有一个清爽的登录界面。

  • 关注行业:科技、医疗、金融、能源等

Market Overview

Market Overview

1.2 自选股管理:你的专属观察池

进入主界面后,第一件事就是构建自选股列表。点击顶部的搜索框(或按下Cmd/Ctrl + K快捷键),输入股票代码或公司名称:

  • 实时搜索:输入"AAPL"立即显示苹果公司
  • 模糊匹配:输入"Tesla"也能找到TSLA
  • 热门推荐:搜索框空白时显示当日热门股票

Search

Search

找到目标股票后,点击右侧的"⭐ Add to Watchlist"按钮即可加入自选。我测试了添加10只股票(AAPL、MSFT、TSLA、NVDA、GOOGL等),整个过程不到1分钟。

Add to Watchlist

Add to Watchlist

自选股列表会实时显示:

  • 当前价格
  • 涨跌幅(红涨绿跌,符合国际惯例)
  • 日内最高/最低价
  • 成交量

实测体验:由于使用的是Finnhub免费API,数据有15分钟延迟。对于日内高频交易者来说不够用,但对于做日频策略或基本面研究的人来说完全够了。如果需要实时数据,可以自己申请Finnhub付费版API,替换环境变量即可。

1.3 股票详情页:专业级的数据看板

点击任意一只股票,进入详情页。这里的信息密度堪比专业终端:

① TradingView图表集成

页面顶部是一个完整的TradingView嵌入式图表,支持:

  • 多种图表类型(K线、美国线、面积图)
  • 20+种技术指标(RSI、MACD、布林带、KDJ等)
  • 时间周期切换(1分钟到月线)
  • 绘图工具(趋势线、斐波那契回撤等)

Market Kline

Market Kline

我试着在AAPL的日线图上添加了MACD和布林带,响应速度很快,没有卡顿。这个功能对于技术分析爱好者来说是刚需——不用再开多个窗口切换了。

② 公司基本面信息

图表下方是公司的核心数据:

  • 估值指标:PE、PB、PS、市值
  • 财务数据:营收、净利润、ROE
  • 分红信息:股息率、派息比率
  • 公司简介:业务范围、CEO、员工数

Financials

Financials

这些数据来自Finnhub的Company Profile接口,更新频率为季度。我对比了几只股票的PE值,与Wind的数据误差在5%以内,可信度不错。

③ 市场新闻聚合

页面底部会显示与该股票相关的最新新闻,包括:

  • 新闻标题和来源
  • 发布时间
  • 情绪标签(正面/中性/负面)

Top Stories

Top Stories

点击新闻标题会跳转到原文链接。这个功能对于事件驱动策略的研究者很有用——可以快速追踪公司的重大事件(财报、并购、高管变动等)。

1.4 市场总览:全局视角的热力图

除了个股追踪,OpenStock还提供了市场总览页面,包含:

  • 市场热力图:直观显示各板块涨跌情况,颜色越深代表涨跌幅越大
  • 行业轮动:科技、金融、医疗等板块的资金流向
  • Top Movers:当日涨幅榜和跌幅榜

Stock Heatmap

Stock Heatmap

这个功能特别适合做行业轮动策略的朋友。我经常用热力图快速判断市场情绪——如果科技股全线飘红,说明风险偏好上升;如果公用事业板块领涨,可能是避险情绪升温。


二、动手部署:30分钟搭建你的专属平台

OpenStock最大的优势是完全可控——你可以部署在自己的服务器上,替换数据源,甚至二次开发添加自己的策略模块。下面我会详细讲解部署过程。

2.1 准备工作:注册必要的API密钥

在开始之前,需要准备以下账号(全部免费):

① MongoDB数据库(存储用户数据和自选股)

  • 访问 https://www.mongodb.com/cloud/atlas
  • 注册账号后创建免费集群(512MB存储)
  • 获取连接字符串,格式类似:mongodb+srv://user:pass@cluster.mongodb.net/

② Finnhub API(股票行情数据)

  • 访问 https://finnhub.io
  • 注册后在Dashboard获取API Key
  • 免费版限制:60次/分钟,数据延迟15分钟

③ Google Gemini API(AI新闻生成,可选)

④ Gmail账号(发送邮件通知)

  • 开启两步验证后生成应用专用密码
  • 路径:Google账号 → 安全性 → 应用专用密码

2.2 本地部署:5步启动项目

Step 1:克隆代码

git clone https://github.com/Open-Dev-Society/OpenStock.git
cd OpenStock

Step 2:安装依赖

npm install
# 或者使用pnpm(推荐,速度更快)
pnpm install

Step 3:配置环境变量

在项目根目录创建.env文件,填入以下内容:

# 数据库连接
MONGODB_URI=mongodb+srv://你的连接字符串

# 认证密钥(随机生成一个32位字符串)
BETTER_AUTH_SECRET=your_random_secret_key_here
BETTER_AUTH_URL=http://localhost:3000

# Finnhub API
FINNHUB_API_KEY=你的API密钥
FINNHUB_BASE_URL=https://finnhub.io/api/v1

# Gemini AI(可选)
GEMINI_API_KEY=你的Gemini密钥

# 邮件配置
NODEMAILER_EMAIL=你的Gmail地址
NODEMAILER_PASSWORD=应用专用密码

Step 4:测试数据库连接

npm run test:db

如果看到"✅ MongoDB连接成功",说明配置正确。

Step 5:启动开发服务器

npm run dev

打开浏览器访问 http://localhost:3000,你应该能看到登录页面了。

2.3 生产部署:一键发布到Vercel

如果想让朋友也能访问,可以部署到云端:

① Fork项目到你的GitHub

② 访问 https://vercel.com

  • 使用GitHub账号登录
  • 点击"Import Project"
  • 选择刚才Fork的仓库

③ 配置环境变量

  • 在Vercel的项目设置中,找到"Environment Variables"
  • .env文件中的所有变量复制过去
  • 注意:BETTER_AUTH_URL要改成Vercel分配的域名(如https://your-app.vercel.app

④ 部署

  • 点击"Deploy"按钮
  • 等待3-5分钟,部署完成

现在你有了一个公网可访问的股票追踪平台,可以分享给团队使用。

2.4 进阶配置:替换为实时数据源

如果你有付费的数据源(如Polygon.io、Alpha Vantage),可以修改数据获取逻辑:

① 找到数据获取函数

// lib/actions/finnhub.actions.ts
export async function getStockQuote(symbol: string) {
  // 原始代码使用Finnhub
  const response = await fetch(
    `${process.env.FINNHUB_BASE_URL}/quote?symbol=${symbol}&token=${process.env.FINNHUB_API_KEY}`
  );
  return response.json();
}

② 替换为你的数据源

export async function getStockQuote(symbol: string) {
  // 改用Polygon.io(实时数据)
  const response = await fetch(
    `https://api.polygon.io/v2/aggs/ticker/${symbol}/prev?apiKey=${process.env.POLYGON_API_KEY}`
  );
  const data = await response.json();

  // 转换为统一格式
  return {
    c: data.results[0].c,  // 收盘价
    h: data.results[0].h,  // 最高价
    l: data.results[0].l,  // 最低价
    o: data.results[0].o,  // 开盘价
    pc: data.results[0].c, // 前收价
  };
}

这样就能获取实时数据了,而且不需要改动前端代码。


三、从数据展示到量化研究:我的改造实践

作为量化,我不满足于只看行情。在使用OpenStock一周后,我基于它的架构做了一些扩展。

3.1 添加历史数据下载脚本

原项目没有批量下载历史数据的功能,我写了一个脚本:

// scripts/download-history.ts
import fs from 'fs';

async function downloadOHLCV(symbol: string, days: number) {
  const to = Math.floor(Date.now() / 1000);
  const from = to - days * 24 * 60 * 60;

  const response = await fetch(
    `https://finnhub.io/api/v1/stock/candle?symbol=${symbol}&resolution=D&from=${from}&to=${to}&token=${process.env.FINNHUB_API_KEY}`
  );
  const data = await response.json();

  // 转换为CSV格式
  const csv = data.t.map((timestamp: number, i: number) => 
    `${new Date(timestamp * 1000).toISOString()},${data.o[i]},${data.h[i]},${data.l[i]},${data.c[i]},${data.v[i]}`
  ).join('\n');

  fs.writeFileSync(`./data/${symbol}.csv`, `Date,Open,High,Low,Close,Volume\n${csv}`);
  console.log(`✅ ${symbol} 数据已保存`);
}

// 批量下载
const symbols = ['AAPL', 'MSFT', 'GOOGL', 'TSLA', 'NVDA'];
for (const symbol of symbols) {
  await downloadOHLCV(symbol, 365); // 下载一年数据
}

运行后会在data/目录生成CSV文件,可以直接导入到回测框架中。

3.2 集成技术指标计算

我添加了一个技术指标库,用于计算常见的量化因子:

// lib/indicators/technical.ts
export class Indicators {
  // RSI相对强弱指标
  static RSI(prices: number[], period = 14): number {
    const changes = prices.slice(1).map((p, i) => p - prices[i]);
    const gains = changes.filter(c => c > 0);
    const losses = changes.filter(c => c < 0).map(Math.abs);

    const avgGain = gains.reduce((a, b) => a + b, 0) / period;
    const avgLoss = losses.reduce((a, b) => a + b, 0) / period;

    const rs = avgGain / (avgLoss || 0.0001);
    return 100 - (100 / (1 + rs));
  }

  // 布林带
  static BollingerBands(prices: number[], period = 20, stdDev = 2) {
    const sma = prices.slice(-period).reduce((a, b) => a + b) / period;
    const variance = prices.slice(-period)
      .reduce((sum, p) => sum + Math.pow(p - sma, 2), 0) / period;
    const std = Math.sqrt(variance);

    return {
      upper: sma + stdDev * std,
      middle: sma,
      lower: sma - stdDev * std
    };
  }
}

现在可以在股票详情页显示这些指标的实时计算结果了。

3.3 价格预警系统

利用Inngest的定时任务功能,我实现了价格预警:

// lib/inngest/functions/price-alert.ts
export const checkPriceAlerts = inngest.createFunction(
  { id: "price-alert" },
  { cron: "*/5 * * * *" }, // 每5分钟检查
  async ({ step }) => {
    // 从数据库获取所有激活的预警
    const alerts = await step.run("fetch-alerts", () => 
      Alert.find({ status: 'ACTIVE' })
    );

    for (const alert of alerts) {
      const quote = await getStockQuote(alert.symbol);

      // 检查触发条件
      if (alert.type === 'PRICE_ABOVE' && quote.c > alert.targetPrice) {
        await sendAlertEmail(alert.userId, `${alert.symbol}已突破${alert.targetPrice}`);
        await Alert.updateOne({ _id: alert._id }, { status: 'TRIGGERED' });
      }
    }
  }
);

设置好预警后,股价达到目标就会收到邮件通知,再也不用盯盘了。


四、冷静思考:这个项目适合你吗?

在使用OpenStock两周后,我总结了它的适用场景和局限性:

✅ 适合这些人:

  • 个人投资者:需要免费的行情追踪工具
  • 量化研究员:需要可定制的数据基础设施
  • 学生/爱好者:学习全栈开发和金融数据处理
  • 小型团队:预算有限,不想买商业终端

⚠️ 不适合这些场景:

  • 日内高频交易:免费数据有延迟
  • 期货/期权交易:目前只支持股票
  • 生产级交易系统:缺少风控和监控模块
  • 完全不懂技术的用户:需要一定的部署能力

我的建议:
如果你只是想看看行情,直接用官方Demo( openstock-ods.vercel.app ) 就够了。如果你想深度定制、添加自己的策略,那么部署一套自己的实例是值得的。


写在最后

OpenStock让我想起多年前刚入行时的困境——想做量化研究,却被数据成本挡在门外。那时候我只能用Yahoo Finance的免费接口,数据质量参差不齐,经常出现缺失值。

现在开源社区给了我们更好的选择。OpenStock不是完美的,它没有Bloomberg的全面,也没有Wind的本土化,但它有一个最重要的特质:开放

你可以看到每一行代码的逻辑,可以替换任何一个模块,可以根据自己的需求改造。这种自由度,是任何商业软件都无法给予的。

更重要的是,它代表了一种理念:金融数据不应该被垄断,技术工具应该属于每一个人。

如果你认同这个理念,不妨给这个项目一个Star,或者贡献你的代码。也许有一天,我们能一起构建一个真正开放、免费、强大的金融数据平台。

那时候,我们就不用再为每年几万块的订阅费发愁了。


项目地址:


标签:#OpenStock #Github #开源项目 #量化交易 #金融科技 #股票分析 #Next.js

关注「alphaFind」,发现更多改变交易方式的开源工具。


您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|云栈社区(YunPan.Plus) ( 苏ICP备2022046150号-2 )

GMT+8, 2025-10-18 02:33 , Processed in 0.078141 second(s), 42 queries .

Powered by Discuz! X3.5

© 2025-2025 CloudStack.

快速回复 返回顶部 返回列表