Investor Object Synchronization in Settrade Open API & SDK

เซสชั่นใน Settrade Open API & SDK เป็นแบบ single session ผมทดลองเขียนโค้ดแบบ synchronized object รับมือกับปัญหาและข้อจำกัดตรงนี้ได้ละครับ 😊

PROBLEM CONTEXT:

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

เพราะ ณ เวลาหนึ่ง 1 account จะมีแค่ 1 session เท่านั้นแตกต่างจาก MetaTrader (MT4/5) ที่เราล็อกอินบนหลายเครื่องด้วย account เดียวกันพร้อมกันได้ ข้อดีคือ เราจะสามารถรันบอทหลายตัวรันบนหลายเครื่องพร้อมกันได้ แถมยังเทรดมือควบคู่ไปด้วยได้

แต่แพลตฟอร์ม streaming pro ทำยังงั้นไม่ได้ ทำให้ปกติหลายคนต้องแก้ด้วยการไปเปิดหลายบัญชี ในหลายโบรกฯ หรือหลายบัญชีในโบรกฯ เดียวกัน ซึ่งโบรกฯ ปกติก็ไม่อนุญาตให้เปิดมากกว่า 1 บัญชีด้วย

ทำให้เมื่อทำบอท บอทจะ take trading action พร้อมกันไม่ได้ เช่น บอท 2 ตัวส่งออร์เดอร์พร้อมกันไม่ได้เนื่องจากทีมพัฒนา Settrade Open API & SDK พัฒนาอ็อบเจ็คต์หลักตัวหนึ่งชื่อ Investor ซึ่งทำงานเป็น session wrapper อีกที มีการทำงานแบบ singleton object ซึ่งไม่รองรับการรันแบบ concurrent ซึ่งหมายถึงมันทำ synchronization ในการเรียกฟังก์ชั่นเกี่ยวกับ trading action พร้อมกันไม่ได้ ทำให้มันทำงานได้แบบ sequential คือ เรียกได้ทีละ 1 ฟังก์ชั่น

เช่นมีบอท 2 ตัวจะเรียกฟังก์ชั่น place_order() พร้อมกันไม่ได้ ต้องเรียกได้ทีละ 1 โดยบอทตัวนึงเรียกใช้ก่อน บอทอีกตัวค่อยเรียกได้

CONCERNS & IMPACT:

Performance: ถ้ารันบอทหลายตัวจะรันนานมาก หลายวินาที เพราะมันต้องรอกัน และยังเสี่ยงต่อการเจอ slippage เยอะๆ ได้1. Availability: เพราะอ็อบเจ็คต์ Investor มัน available ในแบบ sequential access เรียกชั้นได้แค่ทีละคนนะจ๊ะ ทำให้บอทหลายตัวจะทำอะไรต่อก็ไม่ได้ ต้องรอเข้าใช้บริการจนกว่าจะจบ process เสียก่อน ซึ่งจะตรงจะ affect ไปถึงส่วน tick execution ได้ เช่นการ close order เมื่อ SL หรือ TP โดน trigger อาจ close order ทันทีไม่ได้ เพราะติดคิวอยู่

Usability: ยุ่งยาก ‘เรือหาย’ เจงๆ ทีมพัฒนา Settrade Open API & SDK เขาก็ทราบ constraint ตรงนี้ดีอยู่แล้ว น่าจะเขียนโค้ด wrapper ให้มันรองรับการเข้าใช้พร้อมๆ กันได้มาให้เลย กลับกลายเป็นภาระของผู้ใช้ที่ต้องมาเขียนโค้ดยุ่งยากจัดการเอง เพราะโดยปกติคนใช้บอทมากกว่าตัวเดียวอยู่แล้ว

Security: ถ้าผมเป็น hacker ผมจะเจาะเข้าไป acquire อ็อบเจ็คต์ Investor ของบอทคนอื่น แม่มซะเลย 5555 เพราะผู้ใช้ทั่วไปคงเก็บค่า confidential เช่น app id, app secret, app code ฯ กันแบบ plain text ธรรมดาๆ แน่เลย

Interoperability: คอขวดมหาศาลในการ take trading action ทำให้การทำงานระหว่างบอทกับระบบ Settrade Open API ฝั่ง server side จะคอขวดและจุกจิกหยุมหยิม สนุกสนานน้ำตาไหลพรากๆแต่ทุกข้อจำกัด เราต้องหาทางทะลวงออกไปให้ได้ 55555

SOLUTION:

1. ผมสร้างคลาสชื่อ Synchronizer ขึ้นมาโดยมีฟังก์ชั่นชื่อ call() ทำหน้าที่เป็น wrapper method ครอบการเรียกอ็อบเจ็คต์ Investor อีกที

2. ในฟังก์ชั่น call() มีใช้การจัดการ locking เพื่อ ให้เกิดการ lock อ็อบเจ็คต์ Investor เพื่อป้องกันไม่ให้บอทหลายตัวเรียกใช้พร้อมกัน ใครได้ใช้ก่อน บอทตัวอื่นก็รอแป๊บนึง พอบอทตัวแรกใช้เสร็จก็ release lock ให้บอทตัวอื่นๆ แย่งกันเข้าใช้ต่อได้ โดยการใช้ lock ( acquire & release) จะช่วยป้องกันว่าไม่มีการชนกัน และจะไม่เจอ dead lock แน่ๆ

3. บอทแต่ละตัวในจังหวะรัน execute trading action จะรันใน thread ของตัวเอง ทำให้ background เป็นการรัน execute trading action แบบ multithreading ทำให้ไม่ต้องคิดจะ debug จังหวะนี้ เพราะทำไม่ได้ หรือได้แต่ยุ่งหน่อย

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

==================================

ยกตัวอย่าง สมมติมี 2 trading action process

process 1: Open Long มีชั้นตอนคือ

1. cancel order ที่ค้าง เช่น pending, queuing ทิ้งให้หมดก่อน

2. close trade ที่มีก่อน

3. open trade ใหม่

process 2: Close Long มีขั้นตอนคือ

1. cancel order ที่ค้าง เช่น pending, queuing ทิ้งให้หมดก่อน

2. close order

สมมุติ มีบอท 2 ตัว ตัวแรกรัน process 1 ตัวที่สองรัน process 2 ทั้งสองตัวรันพร้อมกัน

1. สมมุติตัวแรกได้เข้าใช้อ็อบเจ็คต์ Investor ก่อน จึง cancel order

2. เมื่อทำเสร็จแล้วจะ release อ็อบเจ็คต์ Investor แล้วเตรียมจะ close trade

3. จังหวะนั้น process 2 อาจจะ acquire อ็อบเจ็คต์ Investor ต่อ เพื่อ cancel order ตัวเอง พอทำเสร็จก็ release อ็อบเจ็คต์

4. จังหวะนั้น process 1 อาจได้ acquire อ็อบเจ็คต์ Investor ใหม่ เพื่อเรียก close trade ต่อ……..

จากตัวอย่างข้างบน ทั้ง 2 process รันพร้อมกัน แต่เรียกใช้อ็อบเจ็คต์ Investor สลับกันไปมา โดยไม่ชนกัน ไม่แย่งกัน ไม่เกิด dead lock

==================================

แต่ๆๆๆๆๆๆๆ ปัญหานี้ก็ยังไม่จบนะ เพราะการทำงานของ Settrade Open API ฝั่ง server side ของเค้า ทำงานแบบ asynchronous หมายถึงการ handle trading action จะไม่สำเร็จในทันที

เช่น เราส่ง open order ไป เราจะได้รับ order no กลับมา แต่ order อาจยังไม่ match หรือยัง match ไม่หมดก็ได้นะทาง Settrade Open API & SDK มีฟังก์ชั่นแบบ asynchronous โดยใช้ websocket ให้เรารับข้อมูลส่งกลับจากฝั่ง server side ได้

เช่น สมมุติเป็นช่วงตลาด panic มากๆๆๆๆ บอทเรารอไป 20 วิ ทางฝั่ง server side จึงส่งผ่าน websocket กลับมาบอกว่า match หมดแล้วโว้ยยยยดังนั้น step ถัดไปผมก็จะเขียนโค้ดรับมือ scenario นี้อีกที 5555 มึนตึ้บจริงๆMAY THE FORCE BE WITH YOU 😊

Leave a Reply

Discover more from

Subscribe now to keep reading and get access to the full archive.

Continue reading