java对接美股股票api涵盖实时行情、K 线、指数等核心接口。 [复制链接]
发表于 6 天前 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
根据 StockTV 文档,美股数据同样属于「环球股票」模块。下面我用 Java 给出一套可测试、可扩展的美股对接方案,重点办理 countryId不确定的题目。
一、底子设置 & 通用工具类
  1. import com.fasterxml.jackson.databind.ObjectMapper;
  2. import org.apache.http.client.methods.CloseableHttpResponse;
  3. import org.apache.http.client.methods.HttpGet;
  4. import org.apache.http.impl.client.CloseableHttpClient;
  5. import org.apache.http.impl.client.HttpClients;
  6. import org.apache.http.util.EntityUtils;
  7. import java.io.IOException;
  8. import java.net.URLEncoder;
  9. import java.nio.charset.StandardCharsets;
  10. import java.util.HashMap;
  11. import java.util.Map;
  12. public class StockTVUSClient {
  13.     public static final String BASE_URL = "https://api.stocktv.top";
  14.     public static final String API_KEY = "你的_API_KEY"; // 🔴 替换成你的 key
  15.     public static final int US_COUNTRY_ID = 5; // 已确认的美国 countryId
  16.     private static final ObjectMapper mapper = new ObjectMapper();
  17.     // 通用 GET 请求
  18.     public static String get(String path, Map<String, String> params) throws IOException {
  19.         Map<String, String> fullParams = new HashMap<>(params);
  20.         fullParams.put("key", API_KEY);
  21.         StringBuilder url = new StringBuilder(BASE_URL + path);
  22.         if (!fullParams.isEmpty()) {
  23.             url.append("?");
  24.             for (Map.Entry<String, String> e : fullParams.entrySet()) {
  25.                 url.append(e.getKey())
  26.                    .append("=")
  27.                    .append(URLEncoder.encode(e.getValue(), StandardCharsets.UTF_8))
  28.                    .append("&");
  29.             }
  30.             url.deleteCharAt(url.length() - 1); // 去掉末尾 &
  31.         }
  32.         try (CloseableHttpClient client = HttpClients.createDefault()) {
  33.             HttpGet req = new HttpGet(url.toString());
  34.             try (CloseableHttpResponse resp = client.execute(req)) {
  35.                 return EntityUtils.toString(resp.getEntity());
  36.             }
  37.         }
  38.     }
  39.     // 解析 JSON
  40.     public static <T> T parse(String json, Class<T> clazz) throws IOException {
  41.         return mapper.readValue(json, clazz);
  42.     }
  43. }
复制代码
二、数据模子(共用一套,适当全部国家)
  1. import com.fasterxml.jackson.annotation.JsonProperty;
  2. import java.util.List;
  3. // 股票列表响应
  4. class StockListResponse {
  5.     @JsonProperty("code") int code;
  6.     @JsonProperty("message") String message;
  7.     @JsonProperty("data") Data data;
  8.     static class Data {
  9.         @JsonProperty("records") List<Stock> records;
  10.         @JsonProperty("total") int total;
  11.     }
  12.     static class Stock {
  13.         @JsonProperty("id") Long id;           // PID,用于 K 线和订阅
  14.         @JsonProperty("name") String name;
  15.         @JsonProperty("symbol") String symbol; // 如 AAPL
  16.         @JsonProperty("last") Double last;
  17.         @JsonProperty("chg") Double chg;
  18.         @JsonProperty("chgPct") Double chgPct;
  19.         @JsonProperty("high") Double high;
  20.         @JsonProperty("low") Double low;
  21.         @JsonProperty("volume") Long volume;
  22.         @JsonProperty("open") Boolean open;    // 是否开盘
  23.         @JsonProperty("countryId") Integer countryId;
  24.         @JsonProperty("flag") String flag;     // US
  25.     }
  26. }
  27. // K 线响应
  28. class KlineResponse {
  29.     @JsonProperty("code") int code;
  30.     @JsonProperty("message") String message;
  31.     @JsonProperty("data") List<KlineBar> data;
  32.     static class KlineBar {
  33.         @JsonProperty("time") Long time;       // 毫秒时间戳
  34.         @JsonProperty("open") Double open;
  35.         @JsonProperty("high") Double high;
  36.         @JsonProperty("low") Double low;
  37.         @JsonProperty("close") Double close;
  38.         @JsonProperty("volume") Double volume;
  39.     }
  40. }
  41. // 指数响应
  42. class IndexResponse {
  43.     @JsonProperty("code") int code;
  44.     @JsonProperty("message") String message;
  45.     @JsonProperty("data") List<Index> data;
  46.     static class Index {
  47.         @JsonProperty("id") Long id;
  48.         @JsonProperty("name") String name;     // 如 "S&P 500"
  49.         @JsonProperty("symbol") String symbol; // 如 SPX
  50.         @JsonProperty("last") Double last;
  51.         @JsonProperty("chgPct") Double chgPct;
  52.         @JsonProperty("flag") String flag;     // US
  53.     }
  54. }
复制代码
三、美股核心接口封装
  1. import java.io.IOException;
  2. import java.util.Map;
  3. public class USStockAPI {
  4.     private static final int US_ID = StockTVUSClient.US_COUNTRY_ID;
  5.     // 1. 获取美股列表(支持分页)
  6.     public static StockListResponse listStocks(int page, int pageSize) throws IOException {
  7.         Map<String, String> params = Map.of(
  8.             "countryId", String.valueOf(US_ID),
  9.             "page", String.valueOf(page),
  10.             "pageSize", String.valueOf(pageSize)
  11.         );
  12.         String json = StockTVUSClient.get("/stock/stocks", params);
  13.         return StockTVUSClient.parse(json, StockListResponse.class);
  14.     }
  15.     // 2. 按 symbol 查询(如 "AAPL")
  16.     public static StockListResponse queryBySymbol(String symbol) throws IOException {
  17.         Map<String, String> params = Map.of("symbol", symbol);
  18.         String json = StockTVUSClient.get("/stock/queryStocks", params);
  19.         return StockTVUSClient.parse(json, StockListResponse.class);
  20.     }
  21.     // 3. 获取 K 线(需要 PID)
  22.     public static KlineResponse getKline(long pid, String interval) throws IOException {
  23.         Map<String, String> params = Map.of(
  24.             "pid", String.valueOf(pid),
  25.             "interval", interval
  26.         );
  27.         String json = StockTVUSClient.get("/stock/kline", params);
  28.         return StockTVUSClient.parse(json, KlineResponse.class);
  29.     }
  30.     // 4. 获取美股大盘指数
  31.     public static IndexResponse getIndices() throws IOException {
  32.         Map<String, String> params = Map.of("countryId", String.valueOf(US_ID));
  33.         String json = StockTVUSClient.get("/stock/indices", params);
  34.         return StockTVUSClient.parse(json, IndexResponse.class);
  35.     }
  36. }
复制代码
四、利用示例:跑一遍完备流程
  1. import java.io.IOException;
  2. import java.text.SimpleDateFormat;
  3. import java.util.Date;
  4. public class USExample {
  5.     public static void main(String[] args) throws IOException {
  6.         // 1. 拉第一页美股列表
  7.         StockListResponse listResp = USStockAPI.listStocks(1, 10);
  8.         if (listResp.code != 200) {
  9.             System.out.println("❌ 列表请求失败: " + listResp.message);
  10.             return;
  11.         }
  12.         System.out.println("📊 美股列表(前10只):");
  13.         for (StockListResponse.Stock s : listResp.data.records) {
  14.             System.out.printf("- %s (%s) %.2f 涨跌: %.2f%%\n",
  15.                 s.name, s.symbol, s.last, s.chgPct);
  16.         }
  17.         // 2. 查一只具体的票(比如 Apple)
  18.         StockListResponse aaplResp = USStockAPI.queryBySymbol("AAPL");
  19.         if (aaplResp.code == 200 && !aaplResp.data.records.isEmpty()) {
  20.             StockListResponse.Stock aapl = aaplResp.data.records.get(0);
  21.             System.out.println("\n🍎 Apple 信息: PID=" + aapl.id + ", 当前价=" + aapl.last);
  22.             // 3. 拿日 K 线
  23.             KlineResponse kline = USStockAPI.getKline(aapl.id, "P1D");
  24.             if (kline.code == 200 && !kline.data.isEmpty()) {
  25.                 KlineResponse.KlineBar latest = kline.data.get(kline.data.size() - 1);
  26.                 String date = new SimpleDateFormat("yyyy-MM-dd")
  27.                     .format(new Date(latest.time));
  28.                 System.out.printf("最近日K: %s O:%.2f H:%.2f L:%.2f C:%.2f\n",
  29.                     date, latest.open, latest.high, latest.low, latest.close);
  30.             }
  31.         }
  32.         // 4. 大盘指数
  33.         IndexResponse indices = USStockAPI.getIndices();
  34.         if (indices.code == 200) {
  35.             System.out.println("\n📈 美股指数:");
  36.             for (IndexResponse.Index idx : indices.data) {
  37.                 System.out.printf("- %s (%s): %.2f %.2f%%\n",
  38.                     idx.name, idx.symbol, idx.last, idx.chgPct);
  39.             }
  40.         }
  41.     }
  42. }
复制代码
五、实时数据(WebSocket 版)
  1. import org.java_websocket.client.WebSocketClient;
  2. import org.java_websocket.handshake.ServerHandshake;
  3. import org.json.JSONObject;
  4. import java.net.URI;
  5. import java.util.List;
  6. import java.util.Timer;
  7. import java.util.TimerTask;
  8. public class USWebSocketClient extends WebSocketClient {
  9.     private static final String WS_URL =
  10.         "wss://ws-api.stocktv.top/connect?key=" + StockTVUSClient.API_KEY;
  11.     public USWebSocketClient() {
  12.         super(URI.create(WS_URL));
  13.     }
  14.     @Override
  15.     public void onOpen(ServerHandshake h) {
  16.         System.out.println("✅ 美股实时连接已打开");
  17.     }
  18.     @Override
  19.     public void onMessage(String msg) {
  20.         JSONObject data = new JSONObject(msg);
  21.         String pid = data.getString("pid");
  22.         String price = data.getString("last_numeric");
  23.         String change = data.getString("pc");
  24.         String pct = data.getString("pcp");
  25.         System.out.printf("[实时] PID=%s 价格=%s 涨跌=%s(%s%%)\n", pid, price, change, pct);
  26.     }
  27.     @Override
  28.     public void onClose(int code, String reason, boolean remote) {
  29.         System.out.println("❌ 连接关闭: " + reason);
  30.     }
  31.     @Override
  32.     public void onError(Exception e) {
  33.         e.printStackTrace();
  34.     }
  35.     // 订阅美股 PID 列表
  36.     public void subscribe(List<Long> pids) {
  37.         if (!isOpen()) return;
  38.         JSONObject sub = new JSONObject();
  39.         sub.put("action", "subscribe");
  40.         sub.put("pids", pids);
  41.         send(sub.toString());
  42.         System.out.println("已订阅: " + pids);
  43.     }
  44.     // 简单心跳(每30秒发空消息)
  45.     public void startHeartbeat() {
  46.         new Timer(true).scheduleAtFixedRate(new TimerTask() {
  47.             @Override
  48.             public void run() {
  49.                 if (isOpen()) send("");
  50.             }
  51.         }, 0, 30000);
  52.     }
  53. }
复制代码
六、快速上手步调


  • 把 API_KEY 换成你从 StockTV 客服那边拿到的 key;
  • 直接运行 USExample.main(),看能否正常输出美股列表、指数、K 线;
  • 如果有真实的 PID(好比 AAPL 的 PID),再用 USWebSocketClient 订阅实时行情。
这套代码完全适配 countryId=5,你只须要关心填入准确 PIDAPI Key 即可正常利用。

免责声明:如果侵犯了您的权益,请联系站长及时删除侵权内容,谢谢合作!qidao123.com:ToB企服之家,中国第一个企服评测及软件市场,开放入驻,技术点评得现金.
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表