大綱

  • 收集盤後資料
  • 建立資料庫
  • 計算均線
  • 回報均線的位置和看盤工具比較
  • 建立自動化
  • 建立通知機制

 

收集盤後資料

參考 https://ithelp.ithome.com.tw/m/articles/10218918

 

實際操作 :

 

python程式: twse_after_hours_get.py

./twse_after_hours_get.py 資料庫位置 日期

取得的資料會存成 csv 檔, 用日期當檔名, 放在資料庫位置資料夾裡

ex:

./twse_after_hours_get.py /mnt/c/Users/rich_huang/Documents/twse_AfterHours 20241204

./twse_after_hours_get.py /mnt/c/Users/rich_huang/Documents/twse_AfterHours 20241205

 

rich_huang@rich-dell-5415:/mnt/c/Users/rich_huang/Documents/MyPy$ ls -lst /mnt/c/Users/rich_huang/Documents/twse_AfterHours/20241204.csv 152 -rwxrwxrwx 1 rich_huang rich_huang 155395 Dec 4 21:43 /mnt/c/Users/rich_huang/Documents/twse_AfterHours/20241204.csv

 

建立資料庫

使用批次腳本方式取得更多營業日的資料, 腳本如下:

twse_mget.sh (run bash script in WSL “Windows Subsystem Linux”, DOS batch 很難寫, 也很難讀)

#!/usr/bin/bash

TargetDate=$1

NumOfDays=$2

echo “Taget date is : $TargetDate”

echo “Number of days before taget date : $NumOfDays”

echo “The dates are :”

for (( i = 1; i <= $NumOfDays; i++ ))

do

t_date=$(date -d ” $i day ago $TargetDate” +%Y%m%d)

echo $t_date

./twse_after_hours_get.py /mnt/c/Users/rich_huang/Documents/twse_AfterHours $t_date

done

 

命令:

time ./twse_mget.sh 20241205 365 # 從指定日期往過去查找365天, 有資料就抓下來

 

 

rich_huang@rich-dell-5415:/mnt/c/Users/rich_huang/Documents/MyPy$ find /mnt/c/Users/rich_huang/Documents/twse_AfterHours -type f | wc -l

241

費時3分16秒, 抓了241個檔案 (一般一週只有五個營業日)

 

 

rich_huang@rich-dell-5415:/mnt/c/Users/rich_huang/Documents/MyPy$ find /mnt/c/Users/rich_huang/Documents/twse_AfterHours -type f | wc -l

483

rich_huang@rich-dell-5415:/mnt/c/Users/rich_huang/Documents/MyPy$ du -sh /mnt/c/Users/rich_huang/Documents/twse_AfterHours

70M        /mnt/c/Users/rich_huang/Documents/twse_AfterHours

目前資料庫裡已經有抓取了兩年的資料, 483個 csv 檔案, 約70MB , 筆電應該承受得起 (養得起)

 

計算均線

參考 : 移動平均線MA線是什麼?5分鐘入門,新手必學!

 

接下來可做大數據分析了

moveing_average.py start_date num_of_days stock_code fraction

 

程式操作說明 :

start_date : 均線計算的起始日

num_of_days : 起始日往前的天數 (過去的日子, 所以人家說看著技術線操作股票是”看著照後鏡開車”)

stock_code : 股票代號

fraction : !! 這我自訂的名詞, 均線糾結在視覺上非常主觀, 每個人的感覺不一定一樣 !!

 

把三條均線 (sma05, sma20, sma60) 加總除以三 當作參考值

sma_mean=(sma05+sma20+sma60)/3

[ 均線 跟 meam 的距離 (差的絕對值) / mean ] 我稱為fraction (分數 : 分子/分母), 分數越小表示三條均線越靠近

 

moveing_average.py :

#!/usr/bin/python

import datetime

import fractions

import json

import sys

import os

import re

 

import loguru

import requests

import csv

 

from pathlib import Path

 

def moving_average(priceC,average_period):

SMA = []

totalOperateDays = len(priceC)

for i in range(totalOperateDays-average_period) :

priceSum = 0.0

for j in range(average_period) :

priceSum += priceC[i+j]

priceSum = priceSum/average_period

SMA.append(priceSum)

return SMA

 

def in_fraction(a,b,c,fraction):

mean=(a+b+c)/3.0

#print(“mean,fraction:”,mean,fraction)

if (abs(a-mean)/mean <= fraction) and (abs(b-mean)/mean <= fraction) and (abs(c-mean)/mean <= fraction) :

return True

else :

return False

 

 

def main():

dataBasePath = sys.argv[1]

start_date = sys.argv[2]

num_of_days = sys.argv[3]

stock_code = sys.argv[4]

fraction = float(sys.argv[5])

 

ref_date = datetime.datetime.strptime(start_date,’%Y%m%d’)

#print(ref_date)

#print(ref_date.strftime(“%Y%m%d”))

 

operateDate = [] #營業日

priceC = [] #收盤價

SMA05 = [] #週均線

SMA20 = [] #月均線

SMA60 = [] #季均線

for i in range(int(num_of_days)):

target_date = ref_date – datetime.timedelta(days=i)

#concatenate filename with csv extention

fileName = target_date.strftime(“%Y%m%d”) + ‘.’ + ‘csv’

#concatenate full path of filename

target_file = os.path.join(dataBasePath,fileName)

#print(“target file : “, target_file)

if not Path(target_file).is_file() :

#print(” file not exist\n”)

continue

else :

#print(” file exist\n”)

operateDate.append(target_date.strftime(“%Y%m%d”))

with open(target_file, ‘r’, newline=”) as csvfile:

reader = csv.reader(csvfile)

for row in reader:

# comapre with stock code

if (row[0] == stock_code) :

priceC.append(float(row[8].replace(‘,’, ”).strip()))

break

else :

continue

 

#觀察期內的營業日總數

SMA05 = moving_average(priceC,5)

SMA20 = moving_average(priceC,20)

SMA60 = moving_average(priceC,60)

 

# 尋找均線糾結

totalOperateDays = len(priceC)

match_period=60

#fraction=0.005

inFraction=False

#print(“totalOperateDays,match_period:”,totalOperateDays,match_period)

latestInFractionDate=None

for i in range(totalOperateDays-match_period) :

if in_fraction(SMA05[i],SMA20[i],SMA60[i],fraction) :

inFraction = True

if latestInFractionDate == None :

latestInFractionDate = operateDate[i]

print(“in fraction, operate_date : “, fraction, operateDate[i])

 

”’

print(“The latest date of SMA60”, operateDate[len(SMA60)-1])

print(“SMA05 “, SMA05)

print(“\n”)

print(“SMA20 “, SMA20)

print(“\n”)

print(“SMA60 “, SMA60)

print(“\n”)

”’

if inFraction :

print(“latest fraction date : “, latestInFractionDate)

#os._exit(0)

#else :

#os._exit(1)

 

if __name__ == ‘__main__’:

main()

 

那麼, fraction要多小才算均線糾結?

我選四個數字來觀察比較看看

.02 (2%), 0.01 (1%), 0.0075 (0.75%), 0.005 (0.5%)

回報均線的位置和看盤工具比較

以聯詠(3034)為範例

rich_huang@rich-dell-5415:/mnt/c/Users/rich_huang/Documents/MyPy$ time ./moving_average.py /mnt/c/Users/rich_huang/Documents/twse_AfterHours 20241205 360 3034 0.005

2024-12-05 00:00:00

20241205

totalOperateDays match_period 238 60

in fraction, operate_date 0.005 20240701

in fraction, operate_date 0.005 20240628

in fraction, operate_date 0.005 20240627

in fraction, operate_date 0.005 20240614

in fraction, operate_date 0.005 20240613

in fraction, operate_date 0.005 20240612

in fraction, operate_date 0.005 20240611

in fraction, operate_date 0.005 20240607

in fraction, operate_date 0.005 20240606

in fraction, operate_date 0.005 20240605

in fraction, operate_date 0.005 20240604

in fraction, operate_date 0.005 20240603

 

real        0m0.703s

user        0m0.484s

sys        0m0.219s

 

對照 三竹的 “技術分析” 圖

 

rich_huang@rich-dell-5415:/mnt/c/Users/rich_huang/Documents/MyPy$ time ./moving_average.py /mnt/c/Users/rich_huang/Documents/twse_AfterHours 20241205 360 3034 0.0075

2024-12-05 00:00:00

20241205

totalOperateDays match_period 238 60

in fraction, operate_date 0.0075 20241028

in fraction, operate_date 0.0075 20241025

in fraction, operate_date 0.0075 20241024

in fraction, operate_date 0.0075 20240710

in fraction, operate_date 0.0075 20240709

in fraction, operate_date 0.0075 20240703

in fraction, operate_date 0.0075 20240702

in fraction, operate_date 0.0075 20240701

in fraction, operate_date 0.0075 20240628

in fraction, operate_date 0.0075 20240627

in fraction, operate_date 0.0075 20240626

in fraction, operate_date 0.0075 20240617

in fraction, operate_date 0.0075 20240614

in fraction, operate_date 0.0075 20240613

in fraction, operate_date 0.0075 20240612

in fraction, operate_date 0.0075 20240611

in fraction, operate_date 0.0075 20240607

in fraction, operate_date 0.0075 20240606

in fraction, operate_date 0.0075 20240605

in fraction, operate_date 0.0075 20240604

in fraction, operate_date 0.0075 20240603

in fraction, operate_date 0.0075 20240531

in fraction, operate_date 0.0075 20240521

 

real        0m0.581s

user        0m0.438s

sys        0m0.141s

 

個人覺得 fraction : %0.75 跟 “技術分析”圖的感覺最接近

 

rich_huang@rich-dell-5415:/mnt/c/Users/rich_huang/Documents/MyPy$ time ./moving_average.py /mnt/c/Users/rich_huang/Documents/twse_AfterHours 20241205 360 3034 0.01

2024-12-05 00:00:00

20241205

totalOperateDays match_period 238 60

in fraction, operate_date 0.01 20241028

in fraction, operate_date 0.01 20241025

in fraction, operate_date 0.01 20241024

in fraction, operate_date 0.01 20241023

in fraction, operate_date 0.01 20241022

in fraction, operate_date 0.01 20241021

in fraction, operate_date 0.01 20241018

in fraction, operate_date 0.01 20240710

in fraction, operate_date 0.01 20240709

in fraction, operate_date 0.01 20240708

in fraction, operate_date 0.01 20240705

in fraction, operate_date 0.01 20240704

in fraction, operate_date 0.01 20240703

in fraction, operate_date 0.01 20240702

in fraction, operate_date 0.01 20240701

in fraction, operate_date 0.01 20240628

in fraction, operate_date 0.01 20240627

in fraction, operate_date 0.01 20240626

in fraction, operate_date 0.01 20240618

in fraction, operate_date 0.01 20240617

in fraction, operate_date 0.01 20240614

in fraction, operate_date 0.01 20240613

in fraction, operate_date 0.01 20240612

in fraction, operate_date 0.01 20240611

in fraction, operate_date 0.01 20240607

in fraction, operate_date 0.01 20240606

in fraction, operate_date 0.01 20240605

in fraction, operate_date 0.01 20240604

in fraction, operate_date 0.01 20240603

in fraction, operate_date 0.01 20240531

in fraction, operate_date 0.01 20240530

in fraction, operate_date 0.01 20240522

in fraction, operate_date 0.01 20240521

in fraction, operate_date 0.01 20240520

 

real        0m0.608s

user        0m0.391s

sys        0m0.219s

(略 …..)

fraction 0.02 就不印出來了

 

使用 Jenkins 進行每日盤後資料收集, 均線糾結計算

安裝Jenkins之前, 需要安裝 java JDK

Installation of the JDK on Microsoft Windows Platforms

Installing Jenkins

 

目前我的Jenkins 主要有兩個專案

  • twse_after_hours
  • moving_average_detection

 

 

Job : twse_after_hours (抓台股盤後資料)

每天下午三點半執行一次

 

 

Job : moving_average_detection (均線糾結計算和偵測)

每天下午四點執行一次

 

使用 Line Notify 通知 “均線糾結”

參考 : 藉由命令列模式使用LINE Notify發送訊息到LINE

如果當天有 “均線糾結” 的話透過Line Notify 通知

 

Line Notify 通知畫面如下:

 

 

我的台股盤後資料收集和均線糾結研究

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *