การเพิ่มขึ้นของการซื้อขายอัตโนมัติ: เครื่องจักรที่ซื้อขาย S&P 500

เผยแพร่แล้ว: 2022-03-11

ทุกวันนี้ มากกว่า 60 เปอร์เซ็นต์ของกิจกรรมการซื้อขายด้วยสินทรัพย์ที่แตกต่างกัน (เช่น หุ้น ดัชนีฟิวเจอร์ส สินค้าโภคภัณฑ์) ไม่ได้ทำโดยผู้ค้า "ที่เป็นมนุษย์" อีกต่อไป แต่อาศัยการซื้อขายอัตโนมัติแทน มีโปรแกรมเฉพาะทางที่ใช้อัลกอริธึมเฉพาะที่ซื้อและขายสินทรัพย์ในตลาดต่างๆ โดยอัตโนมัติ เพื่อให้ได้รับผลตอบแทนที่ดีในระยะยาว

ในบทความนี้ ผมจะแสดงให้คุณเห็นถึงวิธีการทำนายด้วยความแม่นยำที่ดี ว่าควรวางการเทรดครั้งต่อไปอย่างไรเพื่อให้ได้กำไรในทางบวก สำหรับตัวอย่างนี้ ในฐานะสินทรัพย์อ้างอิงในการซื้อขาย ฉันเลือกดัชนี S&P 500 ซึ่งเป็นค่าเฉลี่ยถ่วงน้ำหนักของบริษัทในสหรัฐฯ 500 แห่งที่มีมูลค่าตัวพิมพ์ใหญ่กว่า กลยุทธ์ที่ง่ายมากในการดำเนินการคือซื้อดัชนี S&P 500 เมื่อ Wall Street Exchange เริ่มซื้อขายเวลา 9:30 น. และขายในช่วงปิดตลาดเวลา 16:00 น. ตามเวลาตะวันออก หากราคาปิดของดัชนีสูงกว่าราคาเปิด ก็มีกำไรเป็นบวก ในขณะที่กำไรติดลบจะเกิดขึ้นได้หากราคาปิดต่ำกว่าราคาเปิด คำถามคือ เราจะรู้ได้อย่างไรว่าช่วงการซื้อขายจะจบลงด้วยราคาปิดที่สูงกว่าราคาเปิด? แมชชีนเลิร์นนิงเป็นเครื่องมือที่มีประสิทธิภาพในการทำงานที่ซับซ้อนเช่นนี้ และอาจเป็นเครื่องมือที่มีประโยชน์ในการสนับสนุนเราในการตัดสินใจซื้อขาย

การเรียนรู้ของเครื่องเป็นขอบเขตใหม่ของแอปพลิเคชันในชีวิตจริงที่มีประโยชน์มากมาย การซื้อขายทางการเงินเป็นหนึ่งในนั้น และมักใช้กันมากในภาคส่วนนี้ แนวคิดที่สำคัญเกี่ยวกับการเรียนรู้ของเครื่องคือเราไม่จำเป็นต้องเขียนโค้ดสำหรับกฎที่เป็นไปได้ทุกประเภท เช่น การจดจำรูปแบบ เนื่องจากทุกโมเดลที่เกี่ยวข้องกับ Machine Learning จะเรียนรู้จากข้อมูลนั้นเอง จากนั้นจึงนำไปใช้เพื่อคาดการณ์ข้อมูลใหม่ที่มองไม่เห็นได้ในภายหลัง

ข้อจำกัดความรับผิดชอบ : บทความนี้มีจุดประสงค์เพื่อแสดงวิธีฝึกวิธีการเรียนรู้ของเครื่อง และในตัวอย่างโค้ดที่ให้มานั้นไม่ได้อธิบายทุกฟังก์ชัน บทความนี้ไม่ได้ตั้งใจให้คัดลอกและวางโค้ดทั้งหมดและเรียกใช้การทดสอบที่จัดเตรียมไว้แบบเดียวกัน เนื่องจากรายละเอียดบางอย่างขาดหายไปซึ่งอยู่นอกขอบเขตของบทความ นอกจากนี้ จำเป็นต้องมีความรู้พื้นฐานเกี่ยวกับ Python จุดประสงค์หลักของบทความนี้คือการแสดงตัวอย่างว่าแมชชีนเลิร์นนิงอาจมีประสิทธิภาพในการทำนายการซื้อและขายในภาคการเงินได้อย่างไร อย่างไรก็ตาม การค้าขายด้วยเงินจริงหมายถึงการมีทักษะอื่นๆ มากมาย เช่น การจัดการเงินและการบริหารความเสี่ยง บทความนี้เป็นเพียงส่วนเล็กๆ ของ "ภาพรวม"

การสร้างโปรแกรมการซื้อขายอัตโนมัติข้อมูลทางการเงินครั้งแรกของคุณ

คุณต้องการสร้างโปรแกรมแรกของคุณเพื่อวิเคราะห์ข้อมูลทางการเงินและทำนายการซื้อขายที่ถูกต้องใช่หรือไม่ ให้ฉันแสดงให้คุณเห็นว่า ฉันจะใช้ Python สำหรับโค้ด Machine Learning และเราจะใช้ข้อมูลย้อนหลังจากบริการ Yahoo Finance ดังที่ได้กล่าวไว้ก่อนหน้านี้ ข้อมูลในอดีตมีความจำเป็นในการฝึกโมเดลก่อนทำการคาดคะเนของเรา

ในการเริ่มต้น เราต้องติดตั้ง:

  • Python และโดยเฉพาะอย่างยิ่ง ฉันแนะนำให้ใช้โน้ตบุ๊ก IPython
  • แพ็คเกจ Yahoo Finance Python (ชื่อที่แน่นอนคือ yahoo-finance ) ผ่านคำสั่งเทอร์มินัล: pip install yahoo-finance
  • แพ็คเกจ Machine Learning เวอร์ชันทดลองฟรีที่ชื่อว่า GraphLab อย่าลังเลที่จะตรวจสอบเอกสารที่เป็นประโยชน์ของห้องสมุดนั้น

โปรดทราบว่ามีเพียงส่วนหนึ่งของ GraphLab เท่านั้นที่เป็นโอเพ่นซอร์ส นั่นคือ SFrame ดังนั้นหากต้องการใช้ไลบรารีทั้งหมด เราจำเป็นต้องมีใบอนุญาต มีใบอนุญาตฟรี 30 วันและใบอนุญาตที่ไม่ใช่เชิงพาณิชย์สำหรับนักเรียนหรือผู้ที่เข้าร่วมการแข่งขัน Kaggle จากมุมมองของฉัน GraphLab Create เป็นไลบรารีที่ใช้งานง่ายและใช้งานง่ายมาก เพื่อวิเคราะห์ข้อมูลและฝึกโมเดล Machine Learning

การขุดใน Python Code

มาขุดด้วยโค้ด Python เพื่อดูวิธีดาวน์โหลดข้อมูลทางการเงินจากอินเทอร์เน็ต ฉันแนะนำให้ใช้โน้ตบุ๊ก IPython เพื่อทดสอบโค้ดต่อไปนี้ เนื่องจาก IPython มีข้อดีหลายประการเมื่อเทียบกับ IDE แบบเดิม โดยเฉพาะอย่างยิ่งเมื่อเราต้องการรวมซอร์สโค้ด โค้ดการดำเนินการ ข้อมูลตาราง และแผนภูมิเข้าด้วยกันในเอกสารเดียวกัน สำหรับคำอธิบายสั้นๆ เกี่ยวกับการใช้โน้ตบุ๊ก IPython โปรดดูที่บทความ Introduction to IPython Notebook

เรามาสร้างโน้ตบุ๊ก IPython ใหม่และเขียนโค้ดเพื่อดาวน์โหลดราคาย้อนหลังของดัชนี S&P 500 หมายเหตุ หากคุณต้องการใช้เครื่องมืออื่นๆ คุณสามารถเริ่มต้นด้วยโครงการ Python ใหม่ใน IDE ที่คุณต้องการ

 import graphlab as gl from __future__ import division from datetime import datetime from yahoo_finance import Share # download historical prices of S&P 500 index today = datetime.strftime(datetime.today(), "%Y-%m-%d") stock = Share('^GSPC') # ^GSPC is the Yahoo finance symbol to refer S&P 500 index # we gather historical quotes from 2001-01-01 up to today hist_quotes = stock.get_historical('2001-01-01', today) # here is how a row looks like hist_quotes[0] {'Adj_Close': '2091.580078', 'Close': '2091.580078', 'Date': '2016-04-22', 'High': '2094.320068', 'Low': '2081.199951', 'Open': '2091.48999', 'Symbol': '%5eGSPC', 'Volume': '3790580000'}

ที่นี่ hist_quotes คือรายการพจนานุกรม และแต่ละอ็อบเจ็กต์พจนานุกรมเป็นวันซื้อขายด้วยค่า Open , High , Low , Close , Adj_close , Volume , Symbol และ Date ในแต่ละวันซื้อขาย ราคามักจะเปลี่ยนแปลงโดยเริ่มจากราคา Open เป็นราคา Close และแตะค่าสูงสุดและต่ำสุด High และ Low เราจำเป็นต้องอ่านข้อมูลและสร้างรายการของข้อมูลที่เกี่ยวข้องมากที่สุดแต่ละรายการ นอกจากนี้ ข้อมูลจะต้องเรียงลำดับตามค่าล่าสุดในตอนแรก ดังนั้นเราต้องย้อนกลับ:

 l_date = [] l_open = [] l_high = [] l_low = [] l_close = [] l_volume = [] # reverse the list hist_quotes.reverse() for quotes in hist_quotes: l_date.append(quotes['Date']) l_open.append(float(quotes['Open'])) l_high.append(float(quotes['High'])) l_low.append(float(quotes['Low'])) l_close.append(float(quotes['Close'])) l_volume.append(int(quotes['Volume']))

เราสามารถแพ็คใบเสนอราคาที่ดาวน์โหลดทั้งหมดลงในออบเจ็กต์ SFrame ซึ่งเป็นกรอบข้อมูลที่อิงตามคอลัมน์ที่ปรับขนาดได้สูงและถูกบีบอัด ข้อดีอย่างหนึ่งคือมันสามารถมีขนาดใหญ่กว่าจำนวน RAM ได้เนื่องจากเป็นดิสก์สำรอง คุณสามารถตรวจสอบเอกสารประกอบเพื่อเรียนรู้เพิ่มเติมเกี่ยวกับ SFrame

มาเก็บข้อมูลแล้วตรวจสอบข้อมูลย้อนหลังกัน:

 qq = gl.SFrame({'datetime' : l_date, 'open' : l_open, 'high' : l_high, 'low' : l_low, 'close' : l_close, 'volume' : l_volume}) # datetime is a string, so convert into datetime object qq['datetime'] = qq['datetime'].apply(lambda x:datetime.strptime(x, '%Y-%m-%d')) # just to check if data is sorted in ascending mode qq.head(3)
ปิด วันเวลา สูง ต่ำ เปิด ปริมาณ
1283.27 2001-01-02 00:00:00 1320.28 1276.05 1320.28 1129400000
1347.56 2001-01-03 00:00:00 1347.76 1274.62 1283.27 188070000
1333.34 2001-01-04 00:00:00 1350.24 1329.14 1347.56 2131000000

ตอนนี้เราสามารถบันทึกข้อมูลลงดิสก์ด้วยวิธี SFrame save ได้ดังนี้:

 qq.save(“SP500_daily.bin”) # once data is saved, we can use the following instruction to retrieve it qq = gl.SFrame(“SP500_daily.bin/”)

มาดูกันว่า S&P 500 หน้าตาเป็นอย่างไร

หากต้องการดูว่าข้อมูล S&P 500 ที่โหลดจะมีลักษณะอย่างไร เราสามารถใช้รหัสต่อไปนี้:

 import matplotlib.pyplot as plt %matplotlib inline # only for those who are using IPython notebook plt.plot(qq['close'])

ผลลัพธ์ของรหัสเป็นกราฟต่อไปนี้:

กราฟ S&P 500 ซึ่งโดยทั่วไปจะเติบโตเมื่อเวลาผ่านไป ตามที่แสดงโดยโค้ด Python ด้านบน

ฝึกโมเดลแมชชีนเลิร์นนิงบางส่วน

การเพิ่มผลลัพธ์

ตามที่ได้กล่าวไปแล้วในตอนต้นของบทความนี้ เป้าหมายของแต่ละรุ่นคือการคาดการณ์ว่าราคาปิดจะสูงกว่าราคาเปิดหรือไม่ ดังนั้น ในกรณีนั้น เราสามารถบรรลุผลตอบแทนที่เป็นบวกเมื่อซื้อสินทรัพย์อ้างอิง ดังนั้น เราจำเป็นต้องเพิ่มคอลัมน์ outcome ในข้อมูลของเรา ซึ่งจะเป็น target หรือตัวแปรที่ predicted ทุกแถวของคอลัมน์ใหม่นี้จะเป็น:

  • +1 สำหรับ วันขึ้น โดยมีราคา Closing สูงกว่าราคา Opening
  • -1 สำหรับ Down day โดยราคา Closing ต่ำกว่าราคา Opening
 # add the outcome variable, 1 if the trading session was positive (close>open), 0 otherwise qq['outcome'] = qq.apply(lambda x: 1 if x['close'] > x['open'] else -1) # we also need to add three new columns 'ho' 'lo' and 'gain' # they will be useful to backtest the model, later qq['ho'] = qq['high'] - qq['open'] # distance between Highest and Opening price qq['lo'] = qq['low'] - qq['open'] # distance between Lowest and Opening price qq['gain'] = qq['close'] - qq['open']

เนื่องจากเราต้องประเมินบางวันก่อนการซื้อขายวันสุดท้าย เราจึงต้อง ล่าช้า ข้อมูลอย่างน้อยหนึ่งวัน สำหรับการดำเนินการแล็กแบบนั้น เราจำเป็นต้องมีอ็อบเจ็กต์อื่นจากแพ็คเกจ GraphLab ชื่อ TimeSeries TimeSeries มีการ shift เมธอดที่ทำให้ข้อมูลล่าช้าตามจำนวนแถวที่กำหนด

 ts = gl.TimeSeries(qq, index='datetime') # add the outcome variable, 1 if the bar was positive (close>open), 0 otherwise ts['outcome'] = ts.apply(lambda x: 1 if x['close'] > x['open'] else -1) # GENERATE SOME LAGGED TIMESERIES ts_1 = ts.shift(1) # by 1 day ts_2 = ts.shift(2) # by 2 days # ...etc.... # it's an arbitrary decision how many days of lag are needed to create a good forecaster, so # everyone can experiment by his own decision

การเพิ่มตัวทำนาย

ตัวทำนาย คือชุดของตัวแปรคุณลักษณะที่ต้องเลือกเพื่อฝึกแบบจำลองและคาดการณ์ ผลลัพธ์ ของเรา ดังนั้น การเลือกปัจจัยการคาดการณ์จึงมีความสำคัญ หากไม่ใช่องค์ประกอบที่สำคัญที่สุดของนักพยากรณ์

เพื่อยกตัวอย่างบางส่วน ปัจจัยที่ต้องพิจารณาอาจเป็นถ้าการปิดของวันนี้สูงกว่าการปิดของเมื่อวาน และอาจขยายออกไปด้วยการปิดสองวันก่อนหน้า ฯลฯ ตัวเลือกที่คล้ายกันสามารถแปลได้ด้วยรหัสต่อไปนี้:

 ts['feat1'] = ts['close'] > ts_1['close'] ts['feat2'] = ts['close'] > ts_2['close']

ดังที่แสดงไว้ด้านบน ฉันได้เพิ่มคอลัมน์คุณสมบัติใหม่สองคอลัมน์ feat1 และ feat2 ในชุดข้อมูลของเรา ( ts ) ที่มี 1 หากการเปรียบเทียบเป็นจริงและ 0 หากไม่ใช่

บทความนี้มีจุดมุ่งหมายเพื่อให้ตัวอย่างการเรียนรู้ของเครื่องที่ใช้กับภาคการเงิน ฉันชอบที่จะมุ่งเน้นที่วิธีการใช้แบบจำลองการเรียนรู้ของเครื่องกับข้อมูลทางการเงิน และเราจะไม่ลงรายละเอียดเกี่ยวกับวิธีการเลือกปัจจัยที่เหมาะสมในการฝึกแบบจำลอง เป็นการอธิบายที่ละเอียดถี่ถ้วนเกินไปว่าทำไมจึงใช้ปัจจัยบางอย่างในส่วนที่เกี่ยวกับปัจจัยอื่นๆ เนื่องจากความซับซ้อนที่เพิ่มขึ้นอย่างมาก งานวิจัยของฉันคือการศึกษาสมมติฐานหลายประการในการเลือกปัจจัยเพื่อสร้างตัวทำนายที่ดี ดังนั้นสำหรับการเริ่มต้น เราขอแนะนำให้คุณทดลองกับปัจจัยต่างๆ มากมาย เพื่อดูว่าปัจจัยเหล่านี้อาจเพิ่มความแม่นยำของแบบจำลองหรือไม่

 # add_features is a helper function, which is out of the scope of this article, # and it returns a tuple with: # ts: a timeseries object with, in addition to the already included columns, also lagged columns # as well as some features added to train the model, as shown above with feat1 and feat2 examples # l_features: a list with all features used to train Classifier models # l_lr_features: a list all features used to train Linear Regression models ts, l_features, l_lr_features = add_features(ts) # add the gain column, for trading operations with LONG only positions. # The gain is the difference between Closing price - Opening price ts['gain'] = ts['close'] - ts['open'] ratio = 0.8 # 80% of training set and 20% of testing set training = ts.to_sframe()[0:round(len(ts)*ratio)] testing = ts.to_sframe()[round(len(ts)*ratio):]

การฝึกอบรมแบบจำลองแผนผังการตัดสินใจ

GraphLab Create มีอินเทอร์เฟซที่สะอาดมากเพื่อใช้โมเดลการเรียนรู้ของเครื่อง แต่ละรุ่นมีวิธีการ create ที่ใช้เพื่อให้พอดีกับแบบจำลองด้วยชุดข้อมูลการฝึก พารามิเตอร์ทั่วไปคือ:

  • training - เป็นชุดการฝึกที่มีคอลัมน์คุณลักษณะและคอลัมน์เป้าหมาย
  • target - เป็นชื่อของคอลัมน์ที่มีตัวแปรเป้าหมาย
  • validation_set - เป็นชุดข้อมูลสำหรับตรวจสอบประสิทธิภาพการวางนัยทั่วไปของโมเดล ในกรณีของเรา เราไม่มี validation_set
  • features - เป็นรายการคอลัมน์ชื่อคุณสมบัติที่ใช้สำหรับการฝึกโมเดล
  • verbose - if true ให้พิมพ์ข้อมูลความคืบหน้าระหว่างการฝึก

ในขณะที่พารามิเตอร์อื่น ๆ เป็นเรื่องปกติของตัวแบบเช่น:

  • max_depth คือความลึกสูงสุดของต้นไม้

ด้วยรหัสต่อไปนี้ เราสร้างโครงสร้างการตัดสินใจของเรา:

 max_tree_depth = 6 decision_tree = gl.decision_tree_classifier.create(training, validation_set=None, target='outcome', features=l_features, max_depth=max_tree_depth, verbose=False)

การวัดประสิทธิภาพของรุ่นที่ติดตั้ง

ความแม่นยำ เป็นตัวชี้วัดที่สำคัญในการประเมินความดีของผู้พยากรณ์ คือจำนวนการคาดการณ์ที่ถูกต้องหารด้วยจำนวนจุดข้อมูลทั้งหมด เนื่องจากโมเดลนี้ติดตั้งข้อมูลการฝึก ความแม่นยำที่ประเมินด้วยชุดการฝึกจึงดีกว่าชุดที่ได้รับจากชุดทดสอบ

ความแม่นยำ เป็นส่วนของการคาดการณ์เชิงบวกที่เป็นบวก เราต้องการความแม่นยำในการเป็นตัวเลขที่ใกล้กับ 1 เพื่อให้ได้อัตราการชนะที่ "สมบูรณ์แบบ" decision_tree ของเราในฐานะตัวแยกประเภทอื่นจากแพ็คเกจ GraphLab Create มีวิธีการในการ evaluate เพื่อรับตัวชี้วัดที่สำคัญมากมายของรุ่นที่ติดตั้ง

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

รหัสต่อไปนี้จะแสดง ความแม่นยำ ของรุ่นที่ติดตั้งทั้งกับชุดฝึกและชุดทดสอบ:

 decision_tree.evaluate(training)['accuracy'], decision_tree.evaluate(testing)['accuracy'] (0.6077348066298343, 0.577373211963589)

ดังที่แสดงไว้ข้างต้น ความแม่นยำของแบบจำลองพร้อมชุดทดสอบอยู่ที่ประมาณ 57 เปอร์เซ็นต์ ซึ่งดีกว่าการโยนเหรียญ (50 เปอร์เซ็นต์)

การทำนายข้อมูล

GraphLab Create มีอินเทอร์เฟซเดียวกันในการทำนายข้อมูลจากรุ่นที่ติดตั้งต่างกัน เราจะใช้วิธี predict ซึ่งต้องใช้ชุดทดสอบเพื่อทำนายตัวแปรเป้าหมาย ในกรณีของเรา outcome ตอนนี้ เราสามารถทำนายข้อมูลจากชุดการทดสอบได้:

 predictions = decision_tree.predict(testing) # and we add the predictions column in testing set testing['predictions'] = predictions # let's see the first 10 predictions, compared to real values (outcome column) testing[['datetime', 'outcome', 'predictions']].head(10)
วันเวลา ผล คำทำนาย
2013-04-05 00:00:00 -1 -1
2013-04-08 00:00:00 1 1
2013-04-09 00:00:00 1 1
2013-04-10 00:00:00 1 -1
2013-04-11 00:00:00 1 -1
2013-04-12 00:00:00 -1 -1
2013-04-15 00:00:00 -1 1
2013-04-16 00:00:00 1 1
2013-04-17 00:00:00 -1 -1
2013-04-18 00:00:00 -1 1

ผลบวกลวง คือกรณีที่ตัวแบบคาดการณ์ผลบวกในขณะที่ผลจริงจากชุดการทดสอบเป็นค่าลบ ในทางกลับกัน ค่าลบเท็จ คือกรณีที่ตัวแบบคาดการณ์ผลลัพธ์เชิงลบ โดยที่ผลลัพธ์จริงจากชุดการทดสอบนั้นเป็นบวก

กลยุทธ์การซื้อขายของเรารอผลที่คาดการณ์ในเชิงบวกเพื่อซื้อ S&P 500 ที่ราคา Opening และขายที่ราคา Closing ดังนั้นความหวังของเราคือการมีอัตรา False positive ต่ำสุดเพื่อหลีกเลี่ยงการขาดทุน กล่าวอีกนัยหนึ่ง เราคาดว่าแบบจำลองของเราจะมีอัตรา ความแม่นยำสูงสุด

ดังที่เราเห็น มีค่าเชิงลบเท็จสองค่า (ที่ 2013-04-10 และ 2013-04-11) และผลบวกเท็จสองค่า (ที่ 2013-04-15 และ 2013-04-18) ภายในค่าที่คาดการณ์ไว้สิบค่าแรกของ ชุดทดสอบ.

ด้วยการคำนวณอย่างง่าย โดยพิจารณาจากการคาดการณ์ 10 ชุดเล็ก ๆ นี้:

  • ความแม่นยำ = 6/10 = 0.6 หรือ 60%
  • ความแม่นยำ =3/5 = 0.6 หรือ 60%
  • เรียกคืน = 3/5 = 0.6 หรือ 60%

โปรดทราบว่าโดยปกติตัวเลขด้านบนจะต่างกัน แต่ในกรณีนี้จะเหมือนกัน

การทดสอบย้อนกลับโมเดล

ตอนนี้เราจำลองว่าตัวแบบจะซื้อขายอย่างไรโดยใช้ค่าที่คาดการณ์ไว้ หากผลลัพธ์ที่คาดการณ์ไว้เท่ากับ +1 แสดงว่าเราคาดว่าจะมี วันขึ้น ด้วย Up day เราจะซื้อดัชนีเมื่อเริ่มต้นเซสชัน และขายดัชนีเมื่อสิ้นสุดเซสชันในวันเดียวกัน ในทางกลับกัน หากผลลัพธ์ที่คาดการณ์ไว้เท่ากับ -1 เราคาดว่าจะมี วันดาวน์ ดังนั้นเราจะไม่ทำการซื้อขายในวันนั้น

กำไรและขาดทุน ( pnl ) สำหรับการซื้อขายรายวันแบบสมบูรณ์ เรียกอีกอย่างว่า round turn ในตัวอย่างนี้กำหนดโดย:

  • pnl = Close - Open (สำหรับแต่ละวันซื้อขาย)

ด้วยรหัสที่แสดงด้านล่าง ฉันเรียกใช้ฟังก์ชันตัวช่วย plot_equity_chart เพื่อสร้างแผนภูมิที่มีเส้นโค้งของกำไรสะสม (เส้นโค้งส่วนทุน) โดยไม่ต้องเจาะลึกเกินไป มันก็แค่รับชุดของมูลค่ากำไรขาดทุน และคำนวณชุดของผลรวมสะสมที่จะวางแผน

 pnl = testing[testing['predictions'] == 1]['gain'] # the gain column contains (Close - Open) values # I have written a simple helper function to plot the result of all the trades applied to the # testing set and represent the total return expressed by the index basis points # (not expressed in dollars $) plot_equity_chart(pnl,'Decision tree model') 

โมเดลแผนผังการตัดสินใจ โดยทั่วไปจะขึ้นและไปทางขวา ตามที่แสดงโดยโค้ด Python ด้านบน

 Mean of PnL is 1.843504 Sharpe is 1.972835 Round turns 511

ที่นี่ Sharpe คืออัตราส่วน Sharpe ประจำปี ซึ่งเป็นตัวบ่งชี้ที่สำคัญเกี่ยวกับความดีของรูปแบบการซื้อขาย

อัตราส่วน Sharpe เท่ากับสแควร์รูทของ 252 จากนั้นคูณด้วยค่าเฉลี่ยของ pnl หารด้วยค่าเบี่ยงเบนมาตรฐานของ pnl

พิจารณาการซื้อขายที่แสดงในแต่ละวัน ในขณะที่ mean คือค่าเฉลี่ยของรายการกำไรขาดทุน และ sd คือค่าเบี่ยงเบนมาตรฐาน เพื่อความง่ายในสูตรที่แสดงด้านบน ฉันได้พิจารณาผลตอบแทนที่ปราศจากความเสี่ยงเท่ากับ 0

ข้อมูลพื้นฐานบางประการเกี่ยวกับการซื้อขาย

การซื้อขายดัชนีจำเป็นต้องซื้อสินทรัพย์ซึ่งได้มาจากดัชนีโดยตรง โบรกเกอร์หลายแห่งจำลองดัชนี S&P 500 ด้วยผลิตภัณฑ์อนุพันธ์ที่เรียกว่า CFD (สัญญาสำหรับส่วนต่าง) ซึ่งเป็นข้อตกลงระหว่างสองฝ่ายในการแลกเปลี่ยนส่วนต่างระหว่างราคาเปิดและราคาปิดของสัญญา

ตัวอย่าง : ซื้อ 1 CFD S&P 500 เมื่อ Open (มูลค่า 2000) ขายเมื่อ Close ของวัน (มูลค่าคือ 2020) ความแตกต่างจึงได้ 20 คะแนน หากแต่ละจุดมีมูลค่า 25 เหรียญ:

  • กำไรขั้น ต้นคือ 20 points x $25 = $500 พร้อมสัญญา CFD 1 สัญญา

สมมุติว่าโบรกเกอร์เก็บ Slippage ไว้ที่ 0.6 จุดสำหรับรายได้ของตัวเอง:

  • กำไรสุทธิ คือ (20 - 0.6) points x $25 = $485

สิ่งสำคัญอีกประการที่ควรพิจารณาคือการหลีกเลี่ยงการสูญเสียที่สำคัญภายในการค้าขาย อาจเกิดขึ้นเมื่อใดก็ตามที่ผลลัพธ์ที่คาดการณ์ไว้คือ +1 แต่ค่าผลลัพธ์ที่แท้จริงคือ -1 ดังนั้นจึงเป็น ผลบวกลวง ในกรณีนั้น เซสชั่นที่สิ้นสุดจะกลายเป็น วัน ที่ราคาปิดต่ำกว่าราคาเปิดและเราขาดทุน

ต้องวาง คำสั่งหยุดการขาดทุนเพื่อ ป้องกันการสูญเสียสูงสุดที่เราจะยอมรับได้ในการเทรด และคำสั่งดังกล่าวจะถูกเรียกใช้เมื่อใดก็ตามที่ราคาของสินทรัพย์ต่ำกว่ามูลค่าคงที่ที่เราได้กำหนดไว้ก่อนหน้านี้

หากเราดูอนุกรมเวลาที่ดาวน์โหลดจาก Yahoo Finance ในตอนต้นของบทความนี้ ทุกวันจะมี Low price ซึ่งเป็นราคาต่ำสุดในวันนั้น หากเรากำหนดระดับการหยุดที่ -3 จุดห่างจากราคา Opening และ Low - Open = -5 คำสั่งหยุดจะถูกทริกเกอร์ และตำแหน่งที่เปิดจะถูกปิดโดยสูญเสีย -3 จุดแทนที่จะเป็น -5 นี่เป็นวิธีง่ายๆในการลดความเสี่ยง รหัสต่อไปนี้แสดงถึงฟังก์ชันผู้ช่วยของฉันเพื่อจำลองการซื้อขายที่มีระดับการหยุด:

 # This is a helper function to trade 1 bar (for example 1 day) with a Buy order at opening session # and a Sell order at closing session. To protect against adverse movements of the price, a STOP order # will limit the loss to the stop level (stop parameter must be a negative number) # each bar must contains the following attributes: # Open, High, Low, Close prices as well as gain = Close - Open and lo = Low - Open def trade_with_stop(bar, slippage = 0, stop=None): """ Given a bar, with a gain obtained by the closing price - opening price it applies a stop limit order to limit a negative loss If stop is equal to None, then it returns bar['gain'] """ bar['gain'] = bar['gain'] - slippage if stop<>None: real_stop = stop - slippage if bar['lo']<=stop: return real_stop # stop == None return bar['gain']

ต้นทุนการซื้อขาย

ต้นทุนการทำธุรกรรมเป็นค่าใช้จ่ายที่เกิดขึ้นในการซื้อหรือขายหลักทรัพย์ ต้นทุนในการทำธุรกรรมรวมถึงค่าคอมมิชชั่นและสเปรดของโบรกเกอร์ (ส่วนต่างระหว่างราคาที่ตัวแทนจำหน่ายจ่ายสำหรับหลักทรัพย์และราคาที่ผู้ซื้อจ่าย) และจะต้องนำมาพิจารณาหากต้องการทดสอบกลยุทธ์ของเราย้อนหลัง เช่นเดียวกับสถานการณ์จริง Slippage ในการซื้อขายหุ้นมักเกิดขึ้นเมื่อมีการเปลี่ยนแปลงในสเปรด ในตัวอย่างนี้และสำหรับการจำลองแบบต่อเนื่องครั้งต่อไป ค่าใช้จ่ายในการซื้อขายจะคงที่เป็น:

  • ความคลาดเคลื่อน = 0.6 คะแนน
  • ค่าคอมมิชชั่น = 1$ สำหรับแต่ละการเทรด (หนึ่งรอบจะมีราคา 2$)

เพียงเขียนตัวเลข หากกำไรรวมของเราคือ 10 จุด 1 จุด = $25 ดังนั้น $250 รวมค่าใช้จ่ายในการซื้อขาย กำไรสุทธิของเราจะเป็น (10 - 0.6)*$25 - 2 = $233

รหัสต่อไปนี้แสดงการจำลองกลยุทธ์การซื้อขายครั้งก่อนโดยมีการหยุดการขาดทุน -3 จุด เส้นโค้งสีน้ำเงินคือเส้นโค้งของผลตอบแทนสะสม ค่าใช้จ่ายเพียงอย่างเดียวที่นำมาพิจารณาคือความคลาดเคลื่อน (0.6 คะแนน) และผลลัพธ์จะแสดงเป็นจุดพื้นฐาน (หน่วยฐานเดียวกันของค่า S&P 500 ที่ดาวน์โหลดจาก Yahoo Finance)

 SLIPPAGE = 0.6 STOP = -3 trades = testing[testing['predictions'] == 1][('datetime', 'gain', 'ho', 'lo', 'open', 'close')] trades['pnl'] = trades.apply(lambda x: trade_with_stop(x, slippage=SLIPPAGE, stop=STOP)) plot_equity_chart(trades['pnl'],'Decision tree model') print("Slippage is %s, STOP level at %s" % (SLIPPAGE, STOP)) 

โมเดลแผนผังการตัดสินใจ โดยทั่วไปจะขึ้นและไปทางขวา แต่มีหนามแหลมที่เด่นชัดน้อยกว่า ตามที่แสดงโดยโค้ด Python ด้านบน

 Mean of PnL is 2.162171 Sharpe is 3.502897 Round turns 511 Slippage is 0.6 STOP level at -3

รหัสต่อไปนี้ใช้เพื่อทำนายในลักษณะที่ต่างออกไปเล็กน้อย โปรดใส่ใจกับวิธีการ predict ซึ่งเรียกด้วยพารามิเตอร์เพิ่มเติม output_type = “probability” พารามิเตอร์นี้ใช้เพื่อส่งคืนความน่าจะเป็นของค่าที่คาดการณ์ไว้แทนการทำนายคลาส ( +1 สำหรับผลลัพธ์ที่คาดการณ์ในเชิงบวก -1 สำหรับผลลัพธ์ที่คาดการณ์เชิงลบ) ความน่าจะเป็นที่มากกว่าหรือเท่ากับ 0.5 จะสัมพันธ์กับค่าที่คาดการณ์ไว้ +1 และค่าความน่าจะเป็นที่น้อยกว่า 0.5 จะสัมพันธ์กับค่าที่คาดการณ์ไว้ที่ -1 ยิ่งความน่าจะเป็นสูงเท่าไร โอกาสที่เราต้องทำนาย วันอัพ ที่แท้จริงก็จะยิ่งมากขึ้นเท่านั้น

 predictions_prob = decision_tree.predict(testing, output_type = 'probability') # predictions_prob will contain probabilities instead of the predicted class (-1 or +1)

ตอนนี้ เราทดสอบย้อนกลับโมเดลด้วยฟังก์ชันตัวช่วยที่เรียกว่า backtest_ml_model ซึ่งคำนวณชุดผลตอบแทนสะสม ซึ่งรวมถึง Slippage และค่าคอมมิชชัน และแปลงค่าของพวกมัน เพื่อความกระชับ โดยไม่ต้องอธิบายฟังก์ชัน backtest_ml_model อย่างละเอียด รายละเอียดที่สำคัญที่ควรเน้นคือแทนที่จะกรองวันเหล่านั้นด้วย outcome = 1 ตามที่เราได้ทำในตัวอย่างก่อนหน้านี้ ตอนนี้เรากรอง predictions_prob เหล่านั้นเท่ากับหรือมากกว่า threshold = 0.5 ดังต่อไปนี้:

 trades = testing[predictions_prob>=0.5][('datetime', 'gain', 'ho', 'lo', 'open', 'close')]

โปรดจำไว้ว่า กำไรสุทธิ ของแต่ละวันซื้อขายคือ: Net gain = (Gross gain - SLIPPAGE) * MULT - 2 * COMMISSION ค่าคอมมิชชัน

ตัวชี้วัดสำคัญอีกตัวหนึ่งที่ใช้ในการประเมินความดีของกลยุทธ์การซื้อขายคือ Drawdown สูงสุด โดยทั่วไปจะวัดการลดลงครั้งเดียวที่ใหญ่ที่สุดจากจุดสูงสุดไปยังจุดต่ำสุดในมูลค่าของพอร์ตการลงทุน ในกรณีของเรา มันเป็นการลดลงที่สำคัญที่สุดจากจุดสูงสุดไปยังจุดต่ำสุดของเส้นอิควิตี้ (เรามีสินทรัพย์เพียงรายการเดียวในพอร์ตโฟลิโอของเรา นั่นคือ S&P 500) ดังนั้นเมื่อพิจารณา SArray ของกำไรและขาดทุน pnl เราคำนวณการเบิกจ่ายเป็น:

 drawdown = pnl - pnl.cumulative_max() max_drawdown = min(drawdown)

ภายในฟังก์ชันตัวช่วย backtest_summary คำนวณ:

  • เบิกสูงสุด (เป็นดอลลาร์) ดังที่แสดงด้านบน
  • แม่นยำ ด้วยวิธี Graphlab.evaluation
  • แม่นยำ ด้วยวิธี Graphlab.evaluation
  • เรียกคืนด้วยวิธี Graphlab.evaluation

เมื่อนำทุกอย่างมารวมกันแล้ว ตัวอย่างต่อไปนี้แสดงเส้นส่วนทุนที่แสดงผลตอบแทนสะสมของกลยุทธ์แบบจำลอง โดยมีค่าทั้งหมดแสดงเป็นดอลลาร์

 model = decision_tree predictions_prob = model.predict(testing, output_type="probability") THRESHOLD = 0.5 bt_1_1 = backtest_ml_model(testing, predictions_prob, target='outcome', threshold=THRESHOLD, STOP=-3, MULT=25, SLIPPAGE=0.6, COMMISSION=1, plot_title='DecisionTree') backtest_summary(bt_1_1) 

กราฟ DecisionTree โดยมีแกน Y กำกับว่า "ดอลลาร์" และสูงถึง 30,000 และแกน X ระบุ "# of roundturns" และขยายเป็น 600 ตามที่แสดงโดยโค้ด Python ด้านบน ข้อมูลที่เป็นกราฟนั้นเหมือนกับการเรนเดอร์ครั้งก่อน

 Mean of PnL is 54.054286 Sharpe is 3.502897 Round turns 511 Name: DecisionTree Accuracy: 0.577373211964 Precision: 0.587084148728 Recall: 0.724637681159 Max Drawdown: -1769.00025

เพื่อเพิ่มความแม่นยำของค่าที่คาดการณ์ แทนที่จะเป็นความน่าจะเป็นมาตรฐานที่ 0.5 (50 เปอร์เซ็นต์) เราเลือกค่าเกณฑ์ที่สูงกว่า เพื่อให้มั่นใจมากขึ้นว่าแบบจำลองคาดการณ์ วันขึ้น

 THRESHOLD = 0.55 # it's the minimum threshold to predict an Up day so hopefully a good day to trade bt_1_2 = backtest_ml_model(testing, predictions_prob, target='outcome', threshold=THRESHOLD, STOP=-3, MULT=25, SLIPPAGE=0.6, COMMISSION=1, plot_title='DecisionTree') backtest_summary(bt_1_2) 

กราฟ DecisionTree โดยแกน Y ระบุว่า "ดอลลาร์" และสูงถึง 30,000 และแกน X ระบุ "# of roundturns" และขยายเป็น 250 เท่านั้นในครั้งนี้ ตามที่แสดงโดยโค้ด Python ด้านบน ข้อมูลที่เป็นกราฟนั้นคล้ายกับการเรนเดอร์ครั้งก่อน แต่มีการปรับให้เรียบยิ่งขึ้น

 Mean of PnL is 118.244689 Sharpe is 6.523478 Round turns 234 Name: DecisionTree Accuracy: 0.560468140442 Precision: 0.662393162393 Recall: 0.374396135266 Max Drawdown: -1769.00025

ดังที่เราเห็นได้จากแผนภูมิด้านบน เส้นส่วนผู้ถือหุ้นนั้นดีกว่าเมื่อก่อนมาก (Sharpe คือ 6.5 แทนที่จะเป็น 3.5) แม้ว่าจะมีรอบน้อยลงก็ตาม

จากนี้ไป เราจะพิจารณารุ่นถัดไปทั้งหมดที่มีขีดจำกัดสูงกว่าค่ามาตรฐาน

การฝึกอบรมตัวจำแนกประเภทลอจิสติกส์

เราสามารถนำการวิจัยของเราไปใช้ในแบบจำลอง Logistic Classifier ตามที่เราทำก่อนหน้านี้กับโครงสร้างการตัดสินใจ GraphLab Create มีอินเทอร์เฟซเดียวกันกับออบเจกต์ Logistic Classifier และเราจะเรียกเมธอด create เพื่อสร้างโมเดลของเราด้วยรายการพารามิเตอร์เดียวกัน ยิ่งกว่านั้น เราชอบที่จะทำนายเวกเตอร์ความน่าจะเป็นแทนเวกเตอร์คลาสที่คาดการณ์ไว้ (ประกอบด้วย +1 สำหรับผลลัพธ์ที่เป็นบวก และ -1 สำหรับผลลัพธ์เชิงลบ) ดังนั้นเราจะมีขีดจำกัดมากกว่า 0.5 เพื่อให้ได้ความแม่นยำที่ดีขึ้นใน การพยากรณ์

 model = gl.logistic_classifier.create(training, target='outcome', features=l_features, validation_set=None, verbose=False) predictions_prob = model.predict(testing, 'probability') THRESHOLD = 0.6 bt_2_2 = backtest_ml_model(testing, predictions_prob, target='outcome', threshold=THRESHOLD, STOP=-3, plot_title=model.name()) backtest_summary(bt_2_2) 

กราฟ LogisticClassifier โดยมีแกน Y กำกับว่า "ดอลลาร์" และเพิ่มขึ้นเป็น 50,000 ในครั้งนี้ และแกน X ระบุ "# of roundturns" และขยายเป็น 450 ตามที่แสดงโดยโค้ด Python ด้านบน ข้อมูลที่เป็นกราฟนั้นคล้ายกับการเรนเดอร์ครั้งก่อนในแนวโน้มโดยรวม

 Mean of PnL is 112.704215 Sharpe is 6.447859 Round turns 426 Name: LogisticClassifier Accuracy: 0.638491547464 Precision: 0.659624413146 Recall: 0.678743961353 Max Drawdown: -1769.00025

ในกรณีนี้ มีสรุปที่คล้ายกับแผนผังการตัดสินใจมาก ท้ายที่สุด ทั้งสองโมเดลเป็นตัวแยกประเภท พวกเขาทำนายคลาสของผลลัพธ์ไบนารีเท่านั้น ( +1 , -1 )

การฝึกโมเดลการถดถอยเชิงเส้น

ความแตกต่างหลักของโมเดลนี้คือมันเกี่ยวข้องกับค่าต่อเนื่องแทนที่จะเป็นคลาสไบนารีดังที่กล่าวไว้ก่อนหน้านี้ เราไม่ต้องฝึกโมเดลด้วยตัวแปรเป้าหมายเท่ากับ +1 สำหรับ Up days และ -1 สำหรับ Down days เป้าหมายของเราต้องเป็นตัวแปรต่อเนื่อง เนื่องจากเราต้องการคาดการณ์กำไรที่เป็นบวก หรือกล่าวอีกนัยหนึ่งว่าราคา ปิด สูงกว่าราคา เปิด ตอนนี้เป้าหมายจะต้องเป็นคอลัมน์กำไรของชุดการฝึกของเรา นอกจากนี้ รายการคุณสมบัติจะต้องประกอบด้วยค่าต่อเนื่อง เช่น Open ก่อนหน้า , Close ฯลฯ

เพื่อความกระชับ ฉันจะไม่ลงรายละเอียดเกี่ยวกับวิธีการเลือกคุณสมบัติที่เหมาะสม เนื่องจากนี่อยู่นอกเหนือขอบเขตของบทความนี้ ซึ่งมีแนวโน้มที่จะแสดงให้เห็นว่าเราควรใช้โมเดล Machine Learning ต่างๆ กับชุดข้อมูลอย่างไร รายการพารามิเตอร์ที่ส่งผ่านไปยังวิธีการสร้างคือ:

  • training - เป็นชุดการฝึกที่มีคอลัมน์คุณลักษณะและคอลัมน์เป้าหมาย
  • target - เป็นชื่อของคอลัมน์ที่มีตัวแปรเป้าหมาย
  • validation_set - เป็นชุดข้อมูลสำหรับตรวจสอบประสิทธิภาพการวางนัยทั่วไปของโมเดล ในกรณีของเรา เราไม่มี validation_set
  • features - เป็นรายการชื่อคอลัมน์ของคุณลักษณะที่ใช้สำหรับการฝึกโมเดล สำหรับรุ่นนี้ เราจะใช้ชุดอื่นที่เกี่ยวข้องกับรุ่นลักษณนาม
  • verbose - ถ้า true มันจะพิมพ์ข้อมูลความคืบหน้าระหว่างการฝึก
  • max_iterations - เป็นจำนวนสูงสุดที่อนุญาตผ่านข้อมูล การส่งผ่านข้อมูลมากขึ้นอาจส่งผลให้โมเดลที่ได้รับการฝึกอบรมมีความแม่นยำมากขึ้น
 model = gl.linear_regression.create(training, target='gain', features = l_lr_features, validation_set=None, verbose=False, max_iterations=100) predictions = model.predict(testing) # a linear regression model, predict continuous values, so we need to make an estimation of their # probabilities of success and normalize all values in order to have a vector of probabilities predictions_max, predictions_min = max(predictions), min(predictions) predictions_prob = (predictions - predictions_min)/(predictions_max - predictions_min)

จนถึงตอนนี้ เรามีการคาดคะเนซึ่งเป็น SArray ของกำไรที่คาดการณ์ไว้ ในขณะที่ predictions_prob _prob คือ SArray โดยมีค่า predictions ที่ปรับให้เป็นมาตรฐาน เพื่อให้ได้ความแม่นยำที่ดีและมีจำนวนรอบที่แน่นอน เทียบได้กับรุ่นก่อนๆ ฉันได้เลือกค่าธรณีประตูที่ 0.4 สำหรับ predictions_prob ที่น้อยกว่า 0.4 ฟังก์ชันตัวช่วย backtest_linear_model จะไม่เปิดการซื้อขายเนื่องจากคาดว่าจะมี วันลง มิฉะนั้น การซื้อขายจะเปิดขึ้น

 THRESHOLD = 0.4 bt_3_2 = backtest_linear_model(testing, predictions_prob, target='gain', threshold=THRESHOLD, STOP = -3, plot_title=model.name()) backtest_summary(bt_3_2) 

กราฟการถดถอยเชิงเส้น โดยมีแกน Y กำกับว่า "ดอลลาร์" และขึ้นไปถึง 45,000 และแกน X ระบุ "# ของการปัดเศษ" และขยายเป็น 350 ตามที่แสดงโดยโค้ด Python ด้านบน ข้อมูลที่เป็นกราฟนั้นมีความคล้ายคลึงกันอีกครั้ง แต่ไม่เหมือนกันทุกประการกับการเรนเดอร์ครั้งก่อน

 Mean of PnL is 138.868280 Sharpe is 7.650187 Round turns 319 Name: LinearRegression Accuracy: 0.631989596879 Precision: 0.705329153605 Recall: 0.54347826087 Max Drawdown: -1769.00025

ฝึกต้นไม้เสริมพลัง

อย่างที่เราเคยฝึกโครงสร้างการตัดสินใจ ตอนนี้เรากำลังจะฝึกตัวแยกประเภทต้นไม้ที่เพิ่มประสิทธิภาพด้วยพารามิเตอร์เดียวกันกับที่ใช้สำหรับแบบจำลองตัวแยกประเภทอื่นๆ นอกจากนี้ เรากำหนดจำนวน max_iterations = 12 เพื่อเพิ่มจำนวนการวนซ้ำสูงสุดสำหรับการส่งเสริม การทำซ้ำแต่ละครั้งส่งผลให้เกิดการสร้างต้นไม้พิเศษขึ้น นอกจากนี้เรายังตั้งค่าเกณฑ์ที่สูงกว่า 0.5 เพื่อเพิ่มความแม่นยำ

 model = gl.boosted_trees_classifier.create(training, target='outcome', features=l_features, validation_set=None, max_iterations=12, verbose=False) predictions_prob = model.predict(testing, 'probability') THRESHOLD = 0.7 bt_4_2 = backtest_ml_model(testing, predictions_prob, target='outcome', threshold=THRESHOLD, STOP=-3, plot_title=model.name()) backtest_summary(bt_4_2) 

กราฟ BoostedTreesClassifier โดยมีแกน Y กำกับว่า "ดอลลาร์" และสูงถึง 25,000 และแกน X ระบุ "# of roundturns" และขยายเป็น 250 ตามที่แสดงโดยโค้ด Python ด้านบน ข้อมูลที่เป็นกราฟเองนั้นคล้ายกับการเรนเดอร์ครั้งก่อนอีกครั้ง โดยเพิ่มขึ้นที่คมชัดกว่าประมาณ 175 บนแกน X

 Mean of PnL is 112.002338 Sharpe is 6.341981 Round turns 214 Name: BoostedTreesClassifier Accuracy: 0.563068920676 Precision: 0.682242990654 Recall: 0.352657004831 Max Drawdown: -1769.00025

ฝึกป่าสุ่ม

นี่เป็นแบบจำลองที่ผ่านการฝึกอบรมครั้งสุดท้ายของเรา นั่นคือ Random Forest Classifier ซึ่งประกอบด้วยกลุ่มต้นไม้ตัดสินใจ จำนวนต้นไม้สูงสุดที่จะใช้ในแบบจำลองถูกกำหนดเป็น num_trees = 10 เพื่อหลีกเลี่ยงความซับซ้อนมากเกินไปและเหมาะสมเกินไป

 model = gl.random_forest_classifier.create(training, target='outcome', features=l_features, validation_set=None, verbose=False, num_trees = 10) predictions_prob = model.predict(testing, 'probability') THRESHOLD = 0.6 bt_5_2 = backtest_ml_model(testing, predictions_prob, target='outcome', threshold=THRESHOLD, STOP=-3, plot_title=model.name()) backtest_summary(bt_5_2) 

กราฟ RandomForestClassifier โดยมีแกน Y กำกับว่า "ดอลลาร์" และสูงถึง 40,000 และแกน X ระบุ "# of roundturns" และขยายเป็น 350 ตามที่แสดงโดยโค้ด Python ด้านบน ข้อมูลที่เป็นกราฟนั้นคล้ายกับการแสดงก่อนหน้านี้อีกครั้ง

 Mean of PnL is 114.786962 sharpe is 6.384243 Round turns 311 Name: RandomForestClassifier Accuracy: 0.598179453836 Precision: 0.668810289389 Recall: 0.502415458937 Max Drawdown: -1769.00025

Collecting All the Models Together

Now we can join all the strategies together and see the overall result. It's interesting to see the summary of all Machine Learning models, sorted by their precision.

ชื่อ ความแม่นยำ ความแม่นยำ round turns sharpe
LinearRegression 0.63 0.71 319 7.65
BoostedTreesClassifier 0.56 0.68 214 6.34
RandomForestClassifier 0.60 0.67 311 6.38
DecisionTree 0.56 0.66 234 6.52
LogisticClassifier 0.64 0.66 426 6.45

If we collect all the profit and loss for each one of the previous models in the array pnl , the following chart depicts the equity curve obtained by the sum of each profit and loss, day by day.

 Mean of PnL is 119.446463 Sharpe is 6.685744 Round turns 1504 First trading day 2013-04-09 Last trading day 2016-04-22 Total return 179647

Just to give some numbers, with about 3 years of trading, all models have a total gain of about 180,000 dollars. The maximum exposition is 5 CFD contracts in the market, but to reduce the risk they all are closed at the end of each day, so overnight positions are not allowed.

Statistics of the Aggregation of All Models Together

Since each model can open a trade, but we added 5 concurrent models together, during the same day there could be from 1 contract up to 5 CFD contracts. If all models agree to open trades during the same day, there is a high chance to have an Up day predicted. Moreover, we can group by the number of models that open a trade at the same time during the opening session of the day. Then we evaluate precision as a function of the number of concurrent models.

As we can see by the chart depicted above, the precision gets better as the number of models do agree to open a trade. The more models agree, the more precision we get. For instance, with 5 models triggered the same day, the chance to predict an Up day is greater than 85%.

บทสรุป

Even in the financial world, Machine Learning is welcomed as a powerful instrument to learn from data and give us great forecasting tools. Each model shows different values of accuracy and precision, but in general, all models can be aggregated to achieve a better result than each one of them taken singularly. GraphLab Create is a great library, easy to use, scalable and able to manage Big Data very quickly. It implements different scientific and forecasting models, and there is a free license for students and Kaggle competitions.

ที่เกี่ยวข้อง: บทนำสู่ทฤษฎีการเรียนรู้ของเครื่องและการประยุกต์: การสอนด้วยภาพพร้อมตัวอย่าง

Additional disclosure: This article has been prepared solely for information purposes, and is not an offer to buy or sell or a solicitation of an offer to buy or sell any security or instrument or to participate in any particular trading strategy. Examples presented on these sites are for educational purposes only. Past results are not necessarily indicative of future results.