Basic Python for Trading

บทความนี้ จะนำเสนอ Code ตัวอย่างที่เขียนด้วย Python Version 3.5 ในการทำงานกับข้อมูลหุ้นอย่างง่าย ตั้งแต่ การดึงข้อมูลออนไลน์ การพล็อตข้อมูล ไปจนถึงการ Backtest เทคนิค Moving average สำหรับผู้ที่ต้องการศึกษาวิจัยด้วยตนเอง โดยไม่พึ่งโปรแกรมสำเร็จรูป …

ทำไมเลือกใช้ Python?

  • Python เปิดโอกาสให้สามารถทำการทดลองได้ยืดหยุ่นกว่าโปรแกรมสำเร็จรูปมาก
  • Python  มี library ทาง Statistic, Finance, Machine ที่ถือได้ว่า ครบเครื่อง
  • Python มี Communities ที่ใหญ่ และ แข็งแรง สำหรับผู้ที่ต้องการศึกษาและวิจัยอย่างจริงจัง
  • Python มีโครงสร้างการทำงานที่เข้าใจง่าย สามารถเรียนรู้ได้ด้วยตนเองได้ง่าย

ตัวอย่างขั้นตอนการใช้งาน Python

1) Import library ที่จำเป็น

import quandl as ql
import talib as tl
from datetime import datetime
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

ก่อนอื่นเราต้อง import Library ที่จำเป็นต้องใช้ ในที่นี้ คือ

  • quandl คือ Library ที่เอาไว้โหลดดาต้าจากทั่วโลก อันนี้เขอแนะนำครับเพราะดีมากและฐานข้อมูลใหญ่มาก
  • datetime คือ Library สำหรับการจัดการทางด้านเวลา
  • numpy คือ Library ทีเอาไว้ทำงานกับตัวเลข
  • pandas คือ Library ที่เอาไว้จัดการกับข้อมูลที่สำคัญมากตัวหนึง
  • matplotlib คือ Library สำหรับการจัด

2) โหลดข้อมูลที่ต้องการจากเว็บไซต์ผู้ให้บริการ และ วิเคราะห์ข้อมูลเบื้องต้น

end = datetime.now()
start = datetime(end.year - 3,end.month,end.day)
STA = ql.get('GOOG/BKK_STA',start_date=start_date, end_date = end_date)

ตรงส่วนนี้เราจะทำการโหลดดาต้า .get คือคำสั่งในการเรียกโหลดดาต้าครับ ในที้นี้ผมลองหุ้น STA หรือ หุ้นศรีตรังของเรานั่นเองโดยเลือกเวลานับจากวันปัจจุบันย้อนไปเป็นเวลา 3 ปี

STA.info()

1

คำสั่งนี้คือดู information ของดาต้าที่เราโหลดมา โดยจะบอกข้อมูลคร่าวๆเช่น ดาต้าเป็นประเภทอะไร เริ่มจากเมื่อไหร่ มีจำนวนกี่แถว

STA.Close.plot(figsize=(15, 10))

2

3) ทดลองสร้างอินดิเคเตอร์ Simple moving average

STA['SMA20'] = STA['Close'].rolling(window=20).mean()
STA['SMA40'] = STA['Close'].rolling(window=40).mean()
STA.dropna(inplace=True)
STA.head()

.rolling_mean เป็นคำสั่งใช้หาค่าเฉลี่ยเคลื่อนที่ ในที่นี้เราจะใช้ 21 จากนั้นลองพล๊อตผลดูอีกที 20 และ 40 และ assign ค่าไปใส่ในดาต้า

.dropna คือการทิ้งคอลั่มที่เป็น NA ทิ้งไปทั้งหมด จากนั้นเราดูดาต้าด้วย  STA.head()

4

จะเห็นว่าดาต้าของเราจะไม่ได้เริ่ม ณ วันที่ 20 เดือน 1 ปี 2014 อีกแล้วเนื่องจากเราใช้คำสั่ง  dropna ไปแล้ว 40 row ที่นำมาคำนวน SMA ไปแล้ว และเราจะได้ SMA20 และ SMA40 ใส่ไว้ใน Column ต่อจาก Column ปกติของดาต้าแล้ว

ก่อนอื่นลองพล๊อตดาต้าดูก่อนครับ

STA[['Close', 'SMA20', 'SMA40']].plot(figsize=(15, 10))

5.png

4) สร้างกลยุธ (Strategy) Moving average crossover

จากนั้นเราจะมาลองสร้าง กลยุทธ์การเทรดแบบเบสิค Trend Following ด้วย Python ดูซักอันนะครับ

STA['position'] = np.where(STA['SMA20'] > STA['SMA40'], 1, -1)
f, axarr = plt.subplots(2, sharex=True)
axarr[0].plot(STA['Close'])
axarr[0].set_title('Sharing X axis')
axarr[1].plot(STA['position'])
plt.ylim(-1.1, 1.1)

6

เนื่องจากโพสนี้เป็นการสอนเบสิกธรรมดาเราจึงลองเอามันมาทำ Moving Average Crossover ดูด้วยคำสั่ง np.where(STA[‘SMA20’] > STA[‘SMA40’], 1, -1) คือมันจะตรวจดูว่า Column SMA20 ณ วันใดที่มีค่ามากกว่า SMA40 บ้าง ถ้าเป็นจริงให้เราส่งคำสั่งซื้อ 1 และถ้าไม่เป็นจริงก็ส่งคำสั่งขาย -1 ลงไปใน Column Position จากนั้นเราก็พล๊อตสถานะคำสั่งดู

5) ทดลอง Backtest และ เปรียบเทียบผลการทดลองกับ Benchmark (buy and hold)

ในส่วนนี้เราจะลองจำลองการซื้อขายแบบเบสิกที่สุดนะครับด้วยคำสั่ง

STA['benchmark(buyandhold)'] = np.log(STA['Close'] / STA['Close'].shift(1))
STA['strategy'] = STA['position'].shift(1) * STA['benchmark(buyandhold)']

จากนั้นเราจะสร้าง Column market ไว้เพื่อเก็บ return ของหุ้นศรีตรังเพื่อเอาไว้เปรียบเทียบเป็น Benchmark ของกลยุทธ์เรา ด้วย STA[‘Close’] / STA[‘Close’].shift(1)  คือการนำราคาปิดของวันปัจจุบัน STA[‘Close’] ไปหารด้วยราคาปิดของเมื่อวาน STA[‘Close’].shift(1) คือการเลื่อนวันเมื่อวานมาหารกับวันนี้ np.log คือการหา log return

เมื่อถึงขั้นการเก็บผลลัพธ์เราจึงสร้าง Column strategy มาเพื่อเก็บผลลัพธ์ของกลยุทธ์ของเราด้วยการนำ Column Position ที่เราคำนวณไว้ก่อนหน้านี้แล้ว แต่ถ้าเรานำมาสถาณะซื้อขายมาคูณเข้าไปเลยจะเป็นการ Look ahead bias เพราะความจริงเราไม่สามารถดูราคาเมื่อจบวันแล้วกลับไป ส่งตำสั่งซื้อขายเมื่อเริ่มวันได้ เราจึงต้องทำเหมือนด้านบนเพื่อจัดการกับปัญหานี้คือ STA[‘position’].shift(1) เพื่อเอาคำสั่งการ Crossover ของเมื่อวานเพื่อมาตัดสินใจในวันนี้ตามจริง

STA[['benchmark(buyandhold)', 'strategy']].cumsum().apply(np.exp).tail()

7

เราลองดูผลลัพธ์ครับด้วย คำสั่ง .cumsum().apply(np.exp).tail() คือการเก็บ cumulative ของผลลัพธ์ทั้ง ราคา Market หรือเราจะได้เงินแค่ไหนถ้าเรา buy&hold หุ้นตัวนี้ไว้ซึ้งเราคำนวณในตอนแรกเป็นรายวัน

STA[['benchmark(buyandhold)', 'strategy']].cumsum().apply(np.exp).plot(figsize=(15, 10))
plt.grid(True)

8

กราฟของผลลัพธ์ที่ได้เปรียบเทียบกันระหว่าง Buy and Hold และ Strategy Moving Average Crossover ของหุ้นศรีตรัง  จะเห็นได้ว่าโพสนี้มันดูง่ายๆเหลือเกิน ไม่มีอะไรแปลกใหม่เลย Strategy ก็เก่าไปหลายสิบปีแล้ว แต่ก็ถือซะว่าเป็นก้าวแรกของผู้สนใจ Quant ด้วย Python แล้วกันนะครับ โดยต่อไปเราจะมาดูวิธีการเขียนตัว measurement ที่มาวัดผล Strategy  ด้วยตัวเองกันในโพสหน้านะครับ

ก่อนจบบท ขอฝากผลลัพธ์ไว้ดูกันหน่อยแล้วกันครับ  …

9

 

 

 

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s