> ## Documentation Index
> Fetch the complete documentation index at: https://developers.fhsc.com.vn/llms.txt
> Use this file to discover all available pages before exploring further.

# Sàng lọc cổ phiếu (screener)

> Sàng lọc cổ phiếu trên toàn thị trường: kết hợp filter phạm vi (`exchange`, `index`, `sector`), filter số dạng `<field>_gt` / `<field>_lt`, `sort`, `window` (hoặc `date`) và `fields`. Riêng `price_gt` / `price_lt` nhận thêm `ma50` / `ma200` để so giá với chính đường trung bình động của mã đó. `window` quét tới phiên đang chạy; `date` quét đúng một phiên quá khứ đã đóng, khi đó mọi số liệu lấy từ lịch sử lưu trữ nên các field không có giá trị quá khứ (`market_cap`, `shares_outstanding`, `pe`, `pb`, `eps`, `value`, `ma50`, `ma200`) trả về `null` và không dùng để `sort` / filter được. Kết quả phân trang, mặc định sắp xếp theo vốn hoá giảm dần (theo `volume` khi dùng `date`).




## OpenAPI

````yaml /openapi.yaml get /market/stocks
openapi: 3.1.0
info:
  title: Finhay Securities Open API
  version: 0.2.0-preview.3
  description: |
    Đặc tả chính thức của Finhay Securities Open API, dùng chung cho SDK
    codegen, Redoc docs, và (sau này) mock server / contract test.

    ## Authentication — 2 tier

    - **Tier 1 — chỉ cần API key**: các endpoint đọc dữ liệu thị trường
      (`GET /market/**`, `GET /trading/market/**`). Gửi kèm header
      `X-FH-APIKEY` là đủ.
    - **Tier 2 — HMAC signing**: các endpoint liên quan đến account /
      trading / user. Gửi kèm 4 header `X-FH-APIKEY` + `X-FH-TIMESTAMP` +
      `X-FH-NONCE` + `X-FH-SIGNATURE`; thêm `X-FH-BODYHASH` khi request có
      body. Chi tiết thuật toán xem extension `x-finhay-signing` ở root
      spec hoặc phần README.

    ## Bootstrap flow

    Gọi 2 endpoint tag **Khởi tạo** (`GET /users/v1/users/me` và
    `GET /users/v1/users/{userId}/sub-accounts`) **1 lần khi khởi tạo
    client** để lấy thông tin `user_id` và `subAccountId`. Mọi endpoint thuộc
    tag **Tổng tài sản / Tiểu khoản / Danh mục đầu tư / Sổ lệnh / Lãi-lỗ /
    Quyền cổ đông** đều cần 2 giá trị này để truyền vào path parameter.
  contact: {}
servers:
  - url: https://open-api.fhsc.com.vn
    description: Production
security:
  - FinhayApiKey: []
tags:
  - name: Khởi tạo
    description: >-
      Khởi tạo client — lấy `user_id` và `subAccountId`. Gọi 1 lần khi khởi tạo
      SDK rồi cache lại.
  - name: Bảng giá thị trường
    description: >-
      Giá realtime, lịch sử và sổ lệnh thống nhất cho stocks / indices / forex /
      crypto / hàng hoá / quỹ mở / trái phiếu / ETF.
  - name: Phân tích cơ bản
    description: >-
      Chỉ số tài chính cơ bản của doanh nghiệp — chỉ số tổng quan, phân tích
      theo kỳ và báo cáo tài chính chuẩn (income statement / balance sheet /
      cash flow).
  - name: Tin tức-sự kiện
    description: >-
      Sự kiện doanh nghiệp (cổ tức, quyền mua, ĐHCĐ, …), tin tức stock, tin tức
      tài chính toàn cầu (forex / commodities / economic-indicators /
      stock-market / cryptocurrency) và báo cáo khuyến nghị từ analyst.
  - name: Kinh tế vĩ mô
    description: >-
      Chỉ số kinh tế vĩ mô (CPI, PMI, PCE, GDP, …), lãi suất tiền gửi ngân hàng
      và lịch sự kiện kinh tế.
  - name: Tổng tài sản
    description: >-
      Tổng quan tài sản cấp user — cross-product (stock, fund, bond, hay0) kèm
      cash, debt, PnL.
  - name: Tiểu khoản
    description: Thông tin tiểu khoản — số dư, margin, dư nợ và ngân hàng liên kết.
  - name: Danh mục đầu tư
    description: Danh mục stock đang nắm giữ kèm giá realtime và PnL theo vị thế.
  - name: Sổ lệnh
    description: >-
      Quản lý lệnh — sổ lệnh trong ngày, danh sách đầy đủ hoặc chi tiết theo
      `orderId`.
  - name: Lãi-lỗ
    description: PnL và analytics cá nhân — lãi / lỗ trong ngày tổng hợp theo user.
  - name: Quyền cổ đông
    description: Quyền cổ đông (cổ tức, quyền mua, bỏ phiếu, …) của tiểu khoản.
  - name: Phiên giao dịch
    description: >-
      Hạ tầng trading — trạng thái phiên giao dịch và order type khả dụng của
      mỗi exchange.
  - name: Thực thi lệnh
    description: |
      ⚠️ Nhóm endpoint này đang ở giai đoạn **preview**.

      Đặt / sửa / huỷ lệnh trên sàn — write operation nhạy cảm, yêu cầu
      Tier 2 HMAC đầy đủ + `X-FH-BODYHASH` + `X-FH-2FA-TOKEN` (daily 2FA
      session).
paths:
  /market/stocks:
    get:
      tags:
        - Bảng giá thị trường
      summary: Sàng lọc cổ phiếu (screener)
      description: >
        Sàng lọc cổ phiếu trên toàn thị trường: kết hợp filter phạm vi
        (`exchange`, `index`, `sector`), filter số dạng `<field>_gt` /
        `<field>_lt`, `sort`, `window` (hoặc `date`) và `fields`. Riêng
        `price_gt` / `price_lt` nhận thêm `ma50` / `ma200` để so giá với chính
        đường trung bình động của mã đó. `window` quét tới phiên đang chạy;
        `date` quét đúng một phiên quá khứ đã đóng, khi đó mọi số liệu lấy từ
        lịch sử lưu trữ nên các field không có giá trị quá khứ (`market_cap`,
        `shares_outstanding`, `pe`, `pb`, `eps`, `value`, `ma50`, `ma200`) trả
        về `null` và không dùng để `sort` / filter được. Kết quả phân trang, mặc
        định sắp xếp theo vốn hoá giảm dần (theo `volume` khi dùng `date`).
      operationId: stocksScreen
      parameters:
        - name: exchange
          in: query
          required: false
          description: Lọc theo sàn niêm yết.
          schema:
            type: string
            enum:
              - HOSE
              - HNX
              - UPCOM
            example: HOSE
        - name: index
          in: query
          required: false
          description: Lọc theo rổ chỉ số.
          schema:
            type: string
            enum:
              - VN30
              - HNX30
            example: VN30
        - name: sector
          in: query
          required: false
          description: Lọc theo slug ngành cấp 1.
          schema:
            type: string
            enum:
              - technology
              - telecommunications
              - healthcare
              - financials
              - real-estate
              - consumer-discretionary
              - consumer-staples
              - industrials
              - basic-materials
              - energy
              - utilities
            example: financials
        - name: window
          in: query
          required: false
          description: >-
            Cửa sổ luỹ kế cho các field dòng tiền (foreign_*, proprietary_*,
            volume, value), kết thúc ở phiên hiện tại. Các field trạng thái (pe,
            market_cap…) không chịu ảnh hưởng. Mặc định `1D`. Không dùng chung
            với `date`.
          schema:
            type: string
            enum:
              - 1D
              - 1W
              - 1M
              - 3M
              - 6M
              - 1Y
              - YTD
            default: 1D
            example: YTD
        - name: date
          in: query
          required: false
          description: >-
            Quét đúng một phiên quá khứ đã đóng (`YYYY-MM-DD`, phải nhỏ hơn ngày
            hôm nay — phiên đang chạy dùng `window=1D`). Không dùng chung với
            `window`. Khi có `date`, các field chỉ tồn tại ở thời điểm hiện tại
            (`market_cap`, `shares_outstanding`, `pe`, `pb`, `eps`, `value`,
            `ma50`, `ma200`) trả về `null`, và `sort` / filter theo chúng bị từ
            chối 400.
          schema:
            type: string
            format: date
            example: '2026-08-05'
        - name: sort
          in: query
          required: false
          description: >-
            Field số để sắp xếp, thêm tiền tố `-` cho giảm dần. VD
            `-market_cap`, `foreign_net_value`. Mặc định `-market_cap`, riêng
            khi dùng `date` mặc định là `-volume`. Không sắp xếp được theo
            `ma50`/`ma200`; khi dùng `date` cũng không sắp xếp được theo các
            field không có giá trị quá khứ (`market_cap`, `shares_outstanding`,
            `pe`, `pb`, `eps`, `value`).
          schema:
            type: string
            example: '-foreign_net_value'
        - name: fields
          in: query
          required: false
          description: >-
            Danh sách field cần trả về, phân tách bằng dấu phẩy. Mặc định
            `symbol,exchange,name,price,change_percent`. Field dùng trong
            `sort`/filter luôn được thêm vào. Field hợp lệ: `symbol`, `name`,
            `exchange`, `sector`, `price`, `change_percent`, `market_cap`,
            `shares_outstanding`, `pe`, `pb`, `eps`, `volume`, `value`,
            `foreign_buy_value`, `foreign_sell_value`, `foreign_net_value`,
            `foreign_net_volume`, `foreign_room_available`,
            `foreign_room_available_pct`, `proprietary_buy_value`,
            `proprietary_sell_value`, `proprietary_net_value`,
            `proprietary_net_volume`, `ma50`, `ma200`. `ma50`/`ma200` chỉ hiển
            thị được qua `fields` — không dùng làm `sort` hay filter trực tiếp,
            chỉ làm vế phải của `price_gt`/`price_lt`.
          schema:
            type: string
            example: symbol,name,pe,market_cap
        - name: price_gt
          in: query
          required: false
          description: >-
            Chỉ lấy mã có giá hiện tại lớn hơn giá trị này. Nhận một số (vnd),
            hoặc `ma50` / `ma200` để lấy các mã đang giao dịch trên đường trung
            bình động của chính mã đó.
          schema:
            oneOf:
              - type: number
                example: 20000
              - type: string
                enum:
                  - ma50
                  - ma200
                example: ma50
        - name: price_lt
          in: query
          required: false
          description: >-
            Chỉ lấy mã có giá hiện tại nhỏ hơn giá trị này. Nhận một số (vnd),
            hoặc `ma50` / `ma200` để lấy các mã đang giao dịch dưới đường trung
            bình động của chính mã đó.
          schema:
            oneOf:
              - type: number
                example: 20000
              - type: string
                enum:
                  - ma50
                  - ma200
                example: ma50
        - name: change_percent_gt
          in: query
          required: false
          description: Chỉ lấy mã có thay đổi giá (%) lớn hơn giá trị này.
          schema:
            type: number
            example: 3
        - name: change_percent_lt
          in: query
          required: false
          description: Chỉ lấy mã có thay đổi giá (%) nhỏ hơn giá trị này.
          schema:
            type: number
            example: 3
        - name: market_cap_gt
          in: query
          required: false
          description: Chỉ lấy mã có vốn hoá (vnd) lớn hơn giá trị này.
          schema:
            type: number
            example: 1000000000000
        - name: market_cap_lt
          in: query
          required: false
          description: Chỉ lấy mã có vốn hoá (vnd) nhỏ hơn giá trị này.
          schema:
            type: number
            example: 1000000000000
        - name: shares_outstanding_gt
          in: query
          required: false
          description: Chỉ lấy mã có số cổ phiếu lưu hành lớn hơn giá trị này.
          schema:
            type: number
            example: 100000000
        - name: shares_outstanding_lt
          in: query
          required: false
          description: Chỉ lấy mã có số cổ phiếu lưu hành nhỏ hơn giá trị này.
          schema:
            type: number
            example: 100000000
        - name: pe_gt
          in: query
          required: false
          description: Chỉ lấy mã có p/e lớn hơn giá trị này.
          schema:
            type: number
            example: 15
        - name: pe_lt
          in: query
          required: false
          description: Chỉ lấy mã có p/e nhỏ hơn giá trị này.
          schema:
            type: number
            example: 15
        - name: pb_gt
          in: query
          required: false
          description: Chỉ lấy mã có p/b lớn hơn giá trị này.
          schema:
            type: number
            example: 2
        - name: pb_lt
          in: query
          required: false
          description: Chỉ lấy mã có p/b nhỏ hơn giá trị này.
          schema:
            type: number
            example: 2
        - name: eps_gt
          in: query
          required: false
          description: Chỉ lấy mã có eps (vnd) lớn hơn giá trị này.
          schema:
            type: number
            example: 3000
        - name: eps_lt
          in: query
          required: false
          description: Chỉ lấy mã có eps (vnd) nhỏ hơn giá trị này.
          schema:
            type: number
            example: 3000
        - name: volume_gt
          in: query
          required: false
          description: Chỉ lấy mã có khối lượng khớp lớn hơn giá trị này.
          schema:
            type: number
            example: 1000000
        - name: volume_lt
          in: query
          required: false
          description: Chỉ lấy mã có khối lượng khớp nhỏ hơn giá trị này.
          schema:
            type: number
            example: 1000000
        - name: value_gt
          in: query
          required: false
          description: Chỉ lấy mã có giá trị khớp (vnd) lớn hơn giá trị này.
          schema:
            type: number
            example: 50000000000
        - name: value_lt
          in: query
          required: false
          description: Chỉ lấy mã có giá trị khớp (vnd) nhỏ hơn giá trị này.
          schema:
            type: number
            example: 50000000000
        - name: foreign_net_value_gt
          in: query
          required: false
          description: Chỉ lấy mã có giá trị mua ròng khối ngoại (vnd) lớn hơn giá trị này.
          schema:
            type: number
            example: 0
        - name: foreign_net_value_lt
          in: query
          required: false
          description: Chỉ lấy mã có giá trị mua ròng khối ngoại (vnd) nhỏ hơn giá trị này.
          schema:
            type: number
            example: 0
        - name: foreign_net_volume_gt
          in: query
          required: false
          description: >-
            Chỉ lấy mã có khối lượng mua ròng khối ngoại trong `window` lớn hơn
            giá trị này.
          schema:
            type: number
            example: 0
        - name: foreign_net_volume_lt
          in: query
          required: false
          description: >-
            Chỉ lấy mã có khối lượng mua ròng khối ngoại trong `window` nhỏ hơn
            giá trị này.
          schema:
            type: number
            example: 0
        - name: foreign_buy_value_gt
          in: query
          required: false
          description: >-
            Chỉ lấy mã có giá trị khối ngoại MUA trong `window` (vnd) lớn hơn
            giá trị này. Đây là chiều mua, không phải mua ròng — mua ròng dùng
            `foreign_net_value_gt`.
          schema:
            type: number
            example: 10000000000
        - name: foreign_buy_value_lt
          in: query
          required: false
          description: >-
            Chỉ lấy mã có giá trị khối ngoại MUA trong `window` (vnd) nhỏ hơn
            giá trị này.
          schema:
            type: number
            example: 10000000000
        - name: foreign_sell_value_gt
          in: query
          required: false
          description: >-
            Chỉ lấy mã có giá trị khối ngoại BÁN trong `window` (vnd) lớn hơn
            giá trị này. Đây là chiều bán, không phải bán ròng — bán ròng dùng
            `foreign_net_value_lt`.
          schema:
            type: number
            example: 10000000000
        - name: foreign_sell_value_lt
          in: query
          required: false
          description: >-
            Chỉ lấy mã có giá trị khối ngoại BÁN trong `window` (vnd) nhỏ hơn
            giá trị này.
          schema:
            type: number
            example: 10000000000
        - name: foreign_room_available_gt
          in: query
          required: false
          description: >-
            Chỉ lấy mã có room ngoại còn lại (số cổ phiếu) lớn hơn giá trị này.
            Muốn so theo tỷ lệ thì dùng `foreign_room_available_pct_gt`.
          schema:
            type: number
            example: 1000000
        - name: foreign_room_available_lt
          in: query
          required: false
          description: Chỉ lấy mã có room ngoại còn lại (số cổ phiếu) nhỏ hơn giá trị này.
          schema:
            type: number
            example: 1000000
        - name: foreign_room_available_pct_gt
          in: query
          required: false
          description: >-
            Chỉ lấy mã có room ngoại còn lại (% so với trần sở hữu nước ngoài,
            0–100) lớn hơn giá trị này.
          schema:
            type: number
            example: 50
        - name: foreign_room_available_pct_lt
          in: query
          required: false
          description: >-
            Chỉ lấy mã có room ngoại còn lại (% so với trần sở hữu nước ngoài,
            0–100) nhỏ hơn giá trị này. VD `foreign_room_available_pct_lt=5` để
            tìm các mã gần kín room.
          schema:
            type: number
            example: 5
        - name: proprietary_net_value_gt
          in: query
          required: false
          description: >-
            Chỉ lấy mã có giá trị mua ròng của tự doanh trong `window` (vnd) lớn
            hơn giá trị này. VD `proprietary_net_value_gt=0` để lấy các mã tự
            doanh mua ròng.
          schema:
            type: number
            example: 0
        - name: proprietary_net_value_lt
          in: query
          required: false
          description: >-
            Chỉ lấy mã có giá trị mua ròng của tự doanh trong `window` (vnd) nhỏ
            hơn giá trị này. VD `proprietary_net_value_lt=0` để lấy các mã tự
            doanh bán ròng.
          schema:
            type: number
            example: 0
        - name: proprietary_net_volume_gt
          in: query
          required: false
          description: >-
            Chỉ lấy mã có khối lượng mua ròng của tự doanh trong `window` lớn
            hơn giá trị này.
          schema:
            type: number
            example: 0
        - name: proprietary_net_volume_lt
          in: query
          required: false
          description: >-
            Chỉ lấy mã có khối lượng mua ròng của tự doanh trong `window` nhỏ
            hơn giá trị này.
          schema:
            type: number
            example: 0
        - name: proprietary_buy_value_gt
          in: query
          required: false
          description: >-
            Chỉ lấy mã có giá trị tự doanh MUA trong `window` (vnd) lớn hơn giá
            trị này. Đây là chiều mua, không phải mua ròng — mua ròng dùng
            `proprietary_net_value_gt`.
          schema:
            type: number
            example: 5000000000
        - name: proprietary_buy_value_lt
          in: query
          required: false
          description: >-
            Chỉ lấy mã có giá trị tự doanh MUA trong `window` (vnd) nhỏ hơn giá
            trị này.
          schema:
            type: number
            example: 5000000000
        - name: proprietary_sell_value_gt
          in: query
          required: false
          description: >-
            Chỉ lấy mã có giá trị tự doanh BÁN trong `window` (vnd) lớn hơn giá
            trị này. Đây là chiều bán, không phải bán ròng — bán ròng dùng
            `proprietary_net_value_lt`.
          schema:
            type: number
            example: 5000000000
        - name: proprietary_sell_value_lt
          in: query
          required: false
          description: >-
            Chỉ lấy mã có giá trị tự doanh BÁN trong `window` (vnd) nhỏ hơn giá
            trị này.
          schema:
            type: number
            example: 5000000000
        - name: page
          in: query
          required: false
          description: Trang, bắt đầu từ 1. Mặc định 1.
          schema:
            type: integer
            minimum: 1
            example: 1
        - name: page_size
          in: query
          required: false
          description: Số mã mỗi trang (1–50). Mặc định 20.
          schema:
            type: integer
            minimum: 1
            maximum: 50
            example: 20
      responses:
        '200':
          description: >-
            `data.items` là danh sách mã, mỗi item chỉ chứa các field được chọn
            qua `fields`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/StockScreenerResponse'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '404':
          $ref: '#/components/responses/NotFound'
        '429':
          $ref: '#/components/responses/RateLimited'
        '500':
          $ref: '#/components/responses/InternalError'
      x-codeSamples:
        - lang: bash
          label: cURL
          source: |
            curl -H "X-FH-APIKEY: $FINHAY_API_KEY" \
              "https://open-api.fhsc.com.vn/market/stocks?exchange=HOSE&sort=-market_cap&page_size=20"
components:
  schemas:
    StockScreenerResponse:
      allOf:
        - $ref: '#/components/schemas/EnvelopeBase'
        - type: object
          required:
            - data
          properties:
            data:
              $ref: '#/components/schemas/StockScreenerResult'
    EnvelopeBase:
      type: object
      description: |
        Các field chung của envelope trong mọi response của Finhay API.

        - `error_code` là `"0"` (string) khi thành công, mã khác `"0"` khi lỗi.
        - `message` là thông điệp ngắn từ server.
      properties:
        error_code:
          type: string
          description: '`"0"` khi thành công, khác `"0"` khi lỗi.'
          example: '0'
        message:
          type: string
          description: Thông điệp trạng thái dễ đọc.
          example: success
    StockScreenerResult:
      type: object
      description: Kết quả sàng lọc cổ phiếu, đã phân trang.
      required:
        - items
      properties:
        window:
          type:
            - string
            - 'null'
          description: Cửa sổ luỹ kế đã áp dụng. `null` khi quét theo `date`.
          example: 1D
        date:
          type:
            - string
            - 'null'
          format: date
          description: Phiên quá khứ đã quét (`YYYY-MM-DD`). `null` khi quét theo `window`.
          example: '2026-08-05'
        updated_at:
          type: string
          description: Thời điểm dữ liệu (ISO 8601 kèm offset).
          example: '2026-05-27T14:30:15+07:00'
          format: date-time
        page:
          type: integer
          description: Trang hiện tại.
          example: 1
        page_size:
          type: integer
          description: Số mã mỗi trang.
          example: 20
        total:
          type: integer
          description: Tổng số mã khớp bộ lọc.
          example: 312
        items:
          type: array
          description: Danh sách mã.
          items:
            $ref: '#/components/schemas/StockScreenerItem'
    ErrorBody:
      type: object
      description: Body của response khi 4xx / 5xx.
      properties:
        error_code:
          type: string
          description: >-
            Mã lỗi khác `"0"` (ví dụ `AUTH_SIGNATURE_INVALID`,
            `RATE_LIMIT_EXCEEDED`, …).
          example: '400'
        message:
          type: string
          description: Thông điệp lỗi (tiếng Anh, từ server).
          example: Invalid parameter
      required:
        - error_code
        - message
    StockScreenerItem:
      type: object
      description: >-
        Một dòng kết quả screener. Chỉ chứa các field được chọn qua `fields`
        (mặc định `symbol`, `exchange`, `name`, `price`, `change_percent`), cộng
        thêm field dùng trong `sort`/filter.
      properties:
        symbol:
          type: string
          description: Mã cổ phiếu.
          example: VNM
        name:
          type: string
          description: Tên doanh nghiệp.
          example: CTCP Sữa Việt Nam
        exchange:
          type: string
          description: Sàn niêm yết.
          example: HOSE
        sector:
          $ref: '#/components/schemas/StockSector'
        price:
          type:
            - number
            - 'null'
          description: Giá hiện tại (VND).
          example: 68500
        change_percent:
          type:
            - number
            - 'null'
          description: Thay đổi giá so với tham chiếu (%).
          example: 0.44
        market_cap:
          type:
            - number
            - 'null'
          description: Vốn hoá (VND).
          example: 143000000000000
        shares_outstanding:
          type:
            - number
            - 'null'
          description: Số cổ phiếu lưu hành.
          example: 2089955445
        pe:
          type:
            - number
            - 'null'
          description: P/E.
          example: 15.2
        pb:
          type:
            - number
            - 'null'
          description: P/B.
          example: 2.8
        eps:
          type:
            - number
            - 'null'
          description: EPS (VND).
          example: 4500
        volume:
          type:
            - number
            - 'null'
          description: Khối lượng khớp trong `window`.
          example: 1284500
        value:
          type:
            - number
            - 'null'
          description: Giá trị khớp trong `window` (VND).
          example: 87000000000
        foreign_buy_value:
          type:
            - number
            - 'null'
          description: Giá trị khối ngoại mua trong `window` (VND).
          example: 12000000000
        foreign_sell_value:
          type:
            - number
            - 'null'
          description: Giá trị khối ngoại bán trong `window` (VND).
          example: 9000000000
        foreign_net_value:
          type:
            - number
            - 'null'
          description: Giá trị khối ngoại mua ròng trong `window` (VND).
          example: 3000000000
        foreign_net_volume:
          type:
            - number
            - 'null'
          description: Khối lượng khối ngoại mua ròng trong `window`.
          example: 43000
        foreign_room_available:
          type:
            - number
            - 'null'
          description: Room ngoại còn lại (số cổ phiếu).
          example: 120000000
        foreign_room_available_pct:
          type:
            - number
            - 'null'
          description: >-
            Room ngoại còn lại tính theo % trần sở hữu nước ngoài (0–100). Càng
            gần 0 là càng kín room.
          example: 5.7
        proprietary_buy_value:
          type:
            - number
            - 'null'
          description: Giá trị tự doanh mua trong `window` (VND).
          example: 4000000000
        proprietary_sell_value:
          type:
            - number
            - 'null'
          description: Giá trị tự doanh bán trong `window` (VND).
          example: 5000000000
        proprietary_net_value:
          type:
            - number
            - 'null'
          description: Giá trị tự doanh mua ròng trong `window` (VND).
          example: -1000000000
        proprietary_net_volume:
          type:
            - number
            - 'null'
          description: Khối lượng tự doanh mua ròng trong `window`.
          example: -14000
        ma50:
          type:
            - number
            - 'null'
          description: >-
            Trung bình động 50 phiên (VND), cùng thang với `price`. `null` khi
            mã chưa đủ lịch sử.
          example: 66200
        ma200:
          type:
            - number
            - 'null'
          description: >-
            Trung bình động 200 phiên (VND), cùng thang với `price`. `null` khi
            mã chưa đủ lịch sử.
          example: 61800
    StockSector:
      type:
        - object
        - 'null'
      description: Ngành của mã (cấp 1).
      properties:
        slug:
          type: string
          description: Slug ngành.
          example: consumer-staples
        name:
          type: string
          description: Tên ngành.
          example: Hàng tiêu dùng thiết yếu
  responses:
    BadRequest:
      description: Request không hợp lệ — thiếu hoặc sai tham số.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorBody'
          example:
            error_code: '400'
            message: Invalid parameter
    Unauthorized:
      description: Không xác thực — thiếu, sai hoặc không hợp lệ chữ ký / API key.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorBody'
          example:
            error_code: '401'
            message: Invalid signature
    NotFound:
      description: >-
        Tài nguyên không tồn tại — `error_code` mô tả cụ thể loại tài nguyên
        không tìm thấy.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorBody'
          example:
            error_code: '404'
            message: Not found
    RateLimited:
      description: >-
        Vượt giới hạn rate limit. Chờ đến thời điểm `X-RateLimit-Reset` rồi thử
        lại.
      headers:
        X-RateLimit-Reset:
          $ref: '#/components/headers/XRateLimitReset'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorBody'
          example:
            error_code: '429'
            message: Too many requests
    InternalError:
      description: Lỗi server nội bộ.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/ErrorBody'
          example:
            error_code: '500'
            message: Internal server error
  headers:
    XRateLimitReset:
      description: |
        Unix timestamp (giây) — thời điểm window rate limit reset. Client nhận
        `429 Too Many Requests` nên chờ đến thời điểm này rồi retry.
      schema:
        type: integer
        format: int64
        example: 1713441600
  securitySchemes:
    FinhayApiKey:
      type: apiKey
      in: header
      name: X-FH-APIKEY
      description: >
        API key dài hạn của client. Cấu hình 1 lần lúc khởi tạo; có thể wire
        thẳng

        vào static setter của SDK tự-gen. Đi kèm với `FINHAY_API_SECRET` —
        secret

        này chỉ dùng ở phía client để tính `X-FH-SIGNATURE`, **không** bao giờ

        gửi qua mạng.

````