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

被端走的小菜
7 min readSep 27, 2021

前言

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

說明

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

實作

# app/models/stock.rbclass 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/

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

--

--

被端走的小菜

大家好,我是被端走的小菜。以個人部落格更新為主:https://riverye.com/