ดึงราคาหุ้นใน SET

by m3rLinEz 13. December 2009 18:14

ไปอ่านเอกสารพวก Chart Patterns มา ซึ่งมันคือ Pattern ของกราฟราคาหุ้นที่คนเขียนเอกสารพวกนี้เค้าสังเกตมาว่า เป็นสัญญาณอะไรบางอย่างที่ทำให้หุ้นจะเปลี่ยนราคา (ขึ้น หรือ ลง) ไปอย่างรวดเร็วทำให้สามารถใช้ trade ทำกำไร (หรือขาดทุนยับ) ได้ ส่วนใหญ่คนเขียนเอกสารเค้าก็จะออกตัวไว้ก่อนเลยว่า มันไม่ถูก 100% นะ แต่ก็ไม่เคยมีใครบอกว่ามันถูกกี่ % ดังนั้นก่อนอื่นต้องหาวิธีดึงราคามาเอาไว้ทำการทดลองก่อน

จริงๆแล้ว API ที่ บ.เหมาะกับงานนี้มากเลย แต่ถ้าเอา Data ตรงนั้นมาใช้กลัวว่าอาจจะได้เตะฝุ่นก่อนทำงานครบปี :[ เหอะๆ

class DayData:
    date = None
    open = None
    close = None
    max = None
    min = None
    volume = None
    value = None
    set_index = None

    def __init__(self):
        pass

    @staticmethod
    def to_datetime(str):
        from datetime import datetime
        ds = [int(x) for x in str.split('/')]
        ds[2] = ds[2] + 2000
        return datetime(ds[2], ds[1], ds[0])
                
    @staticmethod
    def to_decimal(str):
        from decimal import Decimal
        return Decimal(str.replace(',',''))

class SETFetch:
    @staticmethod
    def fetch(symbol):
        import urllib2
        from decimal import Decimal
        from BeautifulSoup import BeautifulSoup
        
        set_url_format = "http://www.settrade.com/C04_02_stock_historical_p1.jsp?txtSymbol=%s&from=%d";
        cur_pos = 1
        all_data = []

        while True:
            page = urllib2.urlopen(set_url_format % (symbol, cur_pos))
            soup = BeautifulSoup(page)
            read_data = soup.findAll('tr','tdbg_gray20') + soup.findAll('tr','tdbg_white20')
            if len(read_data) == 0:
                # no more data to read
                break
            cur_pos = cur_pos + len(read_data)
            all_data = all_data + read_data

        daily = []
        for day in all_data:
            flds = day.findAll('td')
            current = DayData()
            current.date =  DayData.to_datetime(flds[0].text)
            current.open = DayData.to_decimal(flds[1].text)
            current.max = DayData.to_decimal(flds[2].text)
            current.min = DayData.to_decimal(flds[3].text)
            current.close = DayData.to_decimal(flds[5].text)
            current.volume = DayData.to_decimal(flds[8].text) * 1000
            current.value = DayData.to_decimal(flds[9].text)
            current.set_index = DayData.to_decimal(flds[10].text)
            daily.append(current)    
        daily.sort(key=lambda x: x.date, reverse=True)
        return daily

if __name__ == '__main__':
    daily = SETFetch.fetch('PTT')
    for day in daily:
        print day.date
    #pdb.set_trace()
ตัวอย่างการใช้งาน
Python 2.6.3 (r263rc1:75186, Oct  2 2009, 20:40:30) [MSC v.1500 32 bit (Intel)]
on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> from setfetch import SETFetch
>>> data = SETFetch.fetch('CPF')
>>> dir(data[0])
['__doc__', '__init__', '__module__', 'close', 'date', 'max', 'min', 'open', 's
t_index', 'to_datetime', 'to_decimal', 'value', 'volume']
>>> for sample in data[0:10]:
...     print sample.date, sample.close
...
2009-12-11 00:00:00 10.90
2009-12-09 00:00:00 10.70
2009-12-08 00:00:00 10.80
2009-12-04 00:00:00 11.00
2009-12-03 00:00:00 10.70
2009-12-02 00:00:00 10.60
2009-12-01 00:00:00 10.90
2009-11-30 00:00:00 10.70
2009-11-27 00:00:00 10.20
2009-11-26 00:00:00 10.40
>>>

เท่าที่รู้ SET จะไม่ยอมให้ใครมาเผยแพร่ Historical Prices พวกนี้ ยกเว้นคนที่จ่ายตังค์ให้ SET และถ้าจะเผยแพร่ก็ต้องเผยแพร่แบบเก็บเงินเท่านั้นด้วย! (แจกฟรีไม่ได้) แต่ทุกวันนี้ก็จะเห็นมีการแอบแจกกันบ่อยๆ :} เป็นเหตุผลว่าทำไมถึงดูราคาหุ้นไทยในเว็บดีๆอย่าง Google Finance ไม่ได้ (แต่ทำไม Bloomberg ดูได้ไม่รู้ ขี้โกงๆ)

ช่วงนี้นอกจากจะเขียนโค้ดช้าลงแล้ว เวลาว่างยาวๆติดๆกันก็ไม่ค่อยจะมี ความสนใจก็เยอะเหลือเกิน >_< เลยต้องพยายามทำให้เสร็จไปเป็นชิ้นเล็กๆ ครั้งหน้าค่อยมาต่อกันเรื่อง Bar Pattern ที่ไปดูมา ว่าพอมาทดสอบกับข้อมูล 6 เดือนที่ดึงมาแล้วมันจะเวิร์คแค่ไหน

Tags: , , , Category: General

Comments (6) -

hybridknight
hybridknight
12/13/2009 6:41:40 PM #

เมพขริงๆๆๆ

อรุช
อรุช
2/6/2010 1:40:26 AM #

ไม่อัพบล๊อกเลยเรอะ - -

blueflame
blueflame
2/21/2010 12:41:42 AM #

พี่แก๊นมีราคาปิดสิ้นปี 51, 50, และ 49 ของ AP และ SPALI ไหมคะ? แอมกำลังทำรายงานวิเคราะห์ผลประกอบการย้อนหลังของ 2 บริษัทนี้อยู่ ติดตรงหาราคาปิดของหุ้น ณ สิ้นปีไม่ได้ซักที ขอบคุณค่ะ  Smile

กร
กร
5/6/2010 5:58:44 PM #

กูว่าโค้ด static method ของ python ไม่สวยเลยอะ ต้องมานั่งเขียน @ นำหน้า

Forex
Forex
6/6/2010 3:47:00 AM #

เห็นแล้ว มึนครับ มันพอจะมี feed xml ให้ดึงที่ไหนบ้างไหม๊ครับ

iPAS
iPAS
10/17/2010 2:22:00 AM #

ขอบคุณมากครับ
ขออนุญาตแก้ไขเพื่อให้เหมาะสมกับ html ที่ได้จาก settrade.com นะครับ

class DayData:
date        = None
open        = None
close       = None
max         = None
min         = None
volume      = None
value       = None
set_index   = None

def __init__(self):
pass

@staticmethod
def to_datetime(text):
from datetime import datetime
import re
text = str(text)
text = re.sub('<td[^>]+>', '', text, re.I)
text = re.sub('</td>', '', text, re.I)              
ds = [ int(x) for x in text.split('/') ]
ds[2] = ds[2] + 2000
return datetime(ds[2], ds[1], ds[0])

@staticmethod
def to_decimal(text):
from decimal import Decimal
import re
text = str(text)
text = re.sub('<td[^>]+>', '', text, re.I)
text = re.sub('</td>', '', text, re.I)
return Decimal(text.replace(',',''))

class SETFetch:

@staticmethod
def fetch(symbol):
import urllib2
from BeautifulSoup import BeautifulSoup
import re

set_url_format  = 'www.settrade.com/C04_02_stock_historical_p1.jsp'
cur_pos         = 1
all_data        = []

# Loop read many page
while True:                        
request   = urllib2.Request(set_url_format % (symbol, cur_pos))
#request.add_header('If-Modified-Since', 'Sun, 02 Mar 2008 04:00:08 GMT')  
request.add_header('User-agent', 'Mozilla/5.0')
response  = urllib2.urlopen(request)
page      = response.read()

# Clean dirt html
text = page
while True:
oldtext = text
text = re.sub('<form[^>]+>', '', text, re.I)
text = re.sub('</form>', '', text, re.I)      
text = re.sub('<input[^>]+>', '', text, re.I)      
text = re.sub('<img[^>]+>', '', text, re.I)
text = re.sub('</a>', '', text, re.I)
if text == oldtext:
break
page = text

# HTML
soup      = BeautifulSoup(page)
read_data = soup.findAll('tr', 'tdbg_gray20') + soup.findAll('tr', 'tdbg_white20')

if len(read_data) == 0: # no more data to read
break

cur_pos  = cur_pos + len(read_data)
all_data = all_data + read_data
break # --debug--

# Converse to decimal data      
daily = []
for day in all_data:
flds    = day.findAll('td')          
current = DayData()
current.date        = DayData.to_datetime(flds[0])          
current.open        = DayData.to_decimal(flds[1])
current.max         = DayData.to_decimal(flds[2])
current.min         = DayData.to_decimal(flds[3])
current.close       = DayData.to_decimal(flds[5])
current.volume      = DayData.to_decimal(flds[8]) * 1000
current.value       = DayData.to_decimal(flds[9])
current.set_index   = DayData.to_decimal(flds[10])
daily.append(current)    

daily.sort(key=lambda x: x.date, reverse=True)
return daily

if __name__ == '__main__':
print 'test'
daily = SETFetch.fetch('ptt')
for day in daily:
print day.date, day.close, day.value

Add comment




biuquote
  • Comment
  • Preview
Loading






Most comments

khimkhim khimkhim
1 comments
weaw weaw
1 comments
domehuhu domehuhu
1 comments

RecentComments

Comment RSS