iT邦幫忙

2021 iThome 鐵人賽

DAY 26
0
自我挑戰組

Ruby on Rails 與它們相關的東西 II系列 第 26

Day26 - 用 Ruby on Rails 寫分析股票的技術指標

前言

在做選股之前,可透過技術指標來分析,像是可以用 KD、均線、量價...等

說明

這邊要申明下,這邊是以技術交流為主,不會有任何投資建議,當自己寫了一套選股策略後,除了要做回測外,要知道沒有 100% 勝率且永遠有效的方法,如果有,請私訊讓我知道 xDD

實作

# app/models/stock.rb

class Stock < ApplicationRecord
  def specify_date(date)
    daily_quotes.find_by(transaction_date: date.to_date)
  end

  def self.simple_moving_average(code, number)
    stock = self.find_by!(code: code)
    stock.simple_moving_average(number)
  rescue ActiveRecord::RecordNotFound => e
    puts "無此股票代號: #{code}"
  end

  def simple_moving_average(number)
    result = daily_quotes.order("transaction_date DESC").limit(number).select(:closing_price)
    if result.size == number
      (result.sum(&:closing_price) / number).round(2)
    else
      0
    end
  end

  # 找出指定日期,成交量前幾名的股票
  def self.top_ranks_trade_volume(number, date = nil)
    self.latest_transaction_date(date)
        .order("daily_quotes.trade_volume DESC")
        .limit(number)
        .select(:name, :code, "daily_quotes.trade_volume")
        .map { |stock| { "股票名稱" => stock.name, "股票代號" => stock.code, "成交量(張)" => stock.trade_volume / 1000 } }
  end

  # 找出指定日期,成交量破XXXX張的股票
  def self.volume_broke_lot(number, date = nil)
    self.latest_transaction_date(date)
        .where("daily_quotes.trade_volume > ?", number * 1000)
        .order("daily_quotes.trade_volume DESC")
        .select(:name, :code, "daily_quotes.trade_volume")
        .map { |stock| { "股票名稱" => stock.name, "股票代號" => stock.code, "成交量(張)" => stock.trade_volume / 1000 } }
  end

  # 找出指定日期,漲停的股票
  def self.find_limit_up_stocks(date = nil)
    latest_transaction_date = find_latest_transaction_dates(2, date)
    candidate_stocks = find_ups_and_downs(latest_transaction_date)
    candidate_stocks.select do |key, values|
      latest_info = nil
      yesterday_info = nil
      values.each do |value|
        if value.transaction_date == latest_transaction_date[0]
          latest_info = value
        else
          yesterday_info = value
        end
      end
      next if latest_info.ups_and_downs != "+" || latest_info.closing_price != latest_info.highest_price

      latest_info.closing_price >= yesterday_info.closing_price * 1.095
    end.keys
  end

  # 找出指定日期,跌停的股票
  def self.find_limit_down_stocks(date = nil)
    latest_transaction_date = find_latest_transaction_dates(2, date)
    candidate_stocks = find_ups_and_downs(latest_transaction_date)
    candidate_stocks.select do |key, values|
      latest_info = nil
      yesterday_info = nil
      values.each do |value|
        if value.transaction_date == latest_transaction_date[0]
          latest_info = value
        else
          yesterday_info = value
        end
      end
      next if latest_info.ups_and_downs != "-" || latest_info.closing_price != latest_info.lowest_price

      latest_info.closing_price <= yesterday_info.closing_price / 1.095
    end.keys
  end

  private

  # 找出最新 X 天的交易日期
  def self.find_latest_transaction_dates(number, date = nil)
    if date
      DailyQuote.where("transaction_date <= ?", date.to_date)
    else
      DailyQuote
    end.select(:transaction_date).order("transaction_date DESC").distinct.limit(number).pluck(:transaction_date)
  end

  def self.find_ups_and_downs(latest_transaction_date)
    self.joins(:daily_quotes)
        .where(daily_quotes: { transaction_date: latest_transaction_date[-1]..latest_transaction_date[0] })
        .order("daily_quotes.trade_volume DESC")
        .select(:code, :name,
                "daily_quotes.transaction_date", "daily_quotes.opening_price", "daily_quotes.closing_price",
                "daily_quotes.highest_price", "daily_quotes.lowest_price", "daily_quotes.ups_and_downs",
               )
        .group_by { |stock| { "股票名稱" => stock.name, "股票代號" => stock.code } }
  end
end

實際執行畫面

小結

每當寫完一個技術指標後,如何驗證自己寫的是否正確呢?

我的做法是去用其他平台,然後看結果是否與我一樣 XD

有更好的方法或發現有寫錯的地方,歡迎和我說喔

與「臺灣證券交易所」有關的系列文,這邊告一段落了,後面還有 4 篇鐵人賽文章要寫 (掩面哭,怎還沒結束 QAQ)


鐵人賽文章連結:https://ithelp.ithome.com.tw/articles/10273425
medium 文章連結:https://link.medium.com/G7zXw5NuTjb
本文同步發布於 小菜的 Blog https://riverye.com/

備註:之後文章修改更新,以個人部落格為主


上一篇
Day25 - 透過 Rake 自動下載處理臺灣證券交易所的資料
下一篇
Day27 - 如何讓 Google 搜尋到你的網站
系列文
Ruby on Rails 與它們相關的東西 II30

尚未有邦友留言

立即登入留言