Automated Grid Trading on Solana

Project นี้ เริ่มมาจากความต้องการที่จะมีระบบที่จะคอยส่งคำสั่ง เปิด order ให้อัตโนมัติ เมื่อ order ติดไม่ว่าจะเป็น Buy หรือ Sell ซึ่งก่อนหน้านี้ทำเอง คอยดูด้วยตาว่า order ไหนหายไปแล้วและก็มาเปิดกลับเองด้วยมือล้วนๆ ซึ่งเอาจริงๆ แล้วเนื่องจาก Port ก็ไม่ได้ใหญ่อะไรมาก order ก็ไม่ได้ติดรัวๆ ก็พอทำเองได้ แต่ถึงอย่างไรก็ตาม คนเรามันก็ต้องมีวันขี้เกียจใช่ไหม ซึ่งนั้นแหละ บางทีก็ปล่อยยาวเลย พลาดโอกาสในการทำกำไรกันไป

ความท้าทายของ Project นี้จะอยู่ที่ว่า เราจะเทรดบน DEX (Decentralize Exchange) ไม่ใช่ CEX (Centralize Exchange) อย่างพวก Binance, Bitkub, Kucoin, Coinbase เป็นต้น และ DEX ที่เราจะไปเทรดกัน ก็คือ Jupiter ซึ่งถือว่าเป็นเบอร์ 1 บน Solana เลยและมี API รองรับ รวมถึง document ก็มีเป็นอย่างดี

Jupiter: https://jup.ag/

ซึ่งการจะเทรดบน On-chain ได้นั้น เราก็จะต้องรู้จักในเรื่องของกระเป๋าและทำ Transaction บนนั้นเสียก่อน รายละเอียดในส่วนนี้จะละไว้ก่อนแล้วถึง ลองไปศึกษากันดูนะครับ 😁

โอเคมาดูกันก่อนว่าเราจะใช้อะไรบน Jupiter กับการทำ Automated Trading ของเราได้บ้าง โดยที่ Jupiter เขาก็จะมี Document ให้เรานะครับ สิ่งที่เราต้องการก็คือ การส่งคำสั่งให้ระบบไปเปิด order แบบ limit buy, limit sell ได้ และสามารถดูได้ว่า order ไหนเปิดอยู่บ้าง และ order ไหนติดไปแล้วใน history

ซึ่งจาก Requirement ทั้งหมดของเรา API ที่ตอบโจทย์นี้ และเราจะเอามาใช้ก็คือ Trigger API นะครับ มีครบเลย

https://dev.jup.ag/api-reference/trigger

ขั้นถัดไปเราก็ไปออกแบบกันว่าโครงสร้างหลักๆ ของเราจะเป็นอย่างไร ซึ่งในที่นี้จะใช้เป็น Docker Container ทำออกมาเป็นแบบ micro service แยกกันทำงานและส่งข้อมูลมาหากัน ภาพก็จะออกมาประมาณนี้

หัวใจหลักก็จะอยู่ในส่วนของ Trade Engine นี่แหละ เราจะให้มันไปคุยที่เราจะให้มันทำงานตาม Logic ที่วางไว้แล้วส่งคำสั่งไปให้ Signer Service ที่จะต้องใช้ Private Key ของกระเป๋าเรา(ตัว Private Key นี้สำคัญมาก การนำมาใช้และการเก็บจะต้องถูกเข้ารหัสไว้อย่างดี) sign transaction แล้วส่งไปที่ Jupiter DEX อีกที ส่วนของ Frontend ก็จะได้เป็นหน้า web ไว้ค่อยจัดการส่งคำสั่งและดู Dashboard ต่างๆ

ในด้านของ tech stack ที่ใช้ จากรูปก็จะเห็นได้คร่าวๆ แต่เรามาดูรายละเอียดกันว่าในแน่ละจุดใช้อะไรบ้าง เฉพาะหลักๆ ก่อนนะ

Frontend

TechnologyUsage
React 18UI Framework
ViteBuild tool & dev server
JavaScript (JSX)Frontend language
CSS3Styling (vanilla CSS)
React RouterRouting

Database & Caching

TechnologyUsage
PostgreSQLPrimary database
RedisCaching & message queue (BullMQ)

Blockchain

TechnologyUsage
Solana Web3.jsBlockchain interaction
🪐 Jupiter APIDEX aggregator & Limit Orders

Infrastructure & DevOps

TechnologyUsage
DockerContainerization
Docker ComposeMulti-container orchestration

หลักการทำงาน

ขออธิบายแบบเห็นภาพจากการทำงานบน Webapp เลยนะครับ

ขั้นแรกก่อนเลย เราจะต้องให้ระบบมี Private key ของกระเป๋าที่ต้องการเทรดก่อน โดยการที่จะต้องให้มีที่เก็บ Private key นี้ไว้เป็นอย่างดี แล้วแต่เทคนิคของแต่ละคนเลยนะว่าจะให้มันเก็บอย่างไร สำหรับ project นี้เราใช้ docker secret เป็นตัวช่วยจัดการ

หลังจากที่เรา Add เขามา เราก็จะต้องทำให้ระบบของเรา สามารถ อ่าน ค่าของกระเป๋านี้ได้บน Solana blockchain เพื่อที่จะได้รู้ว่ามี balance เท่าไหร่ และมี order เปิดอยู่เท่าไหร่ ซึ่งพวกนี้จะมีผลต่อ logic ในการคำนวณการเปิด zone (ขอเบลอไว้หน่อยแล้วกัน port เล็ก อาย อิอิ)

อ่อ อีกนิดนึง Token บน Solana ถ้าเราจะเอาไปเทรด เราต้องรู้จักมันด้วยนะว่า mint address มันคืออะไร มี Decimal อยู่เท่าไหร่ ในจุดนี้เราจะใส่แบบ hard code ลงไปเลยก็ได้ หรือจะให้ user มาเพิ่มเพื่อเทรดเหรียญอื่นๆ ตามใจเขาก็ได้

อันนี้ตัวอย่างของ WBTC ที่เป็น Wrapped Bitcoin ของ Wormhole บน Solana เราสามารถดูรายละเอียดได้ที่ Solscan ที่เป็น explorer ดูข้อมูล transaction บน Solana https://solscan.io/token/3NZ9JMVBmGAqocybic2c7LQCJScmgsAZ6vQqTDzcqmJh

กระเป๋าพร้อม, เหรียญพร้อม ต่อไปเริ่มสร้าง Grid กันได้แล้ว เราจะใช้หลักการให้ระบบมันคำนวณค่า min price, max price และ step price ที่เราต้องการให้มันสร้าง zone ขึ้นมา แล้วมันก็จะมาบอกเราว่าจะได้ทั้งหมดกี่ zone และใช้เงินเท่าไหร่ จาก amount token ที่เราใส่ไป

แถมเป็นเกร็ดให้อีกนิดนึง ในระบบของ Jupiter ที่เราต้องส่งคำสั่งไป จะมี token เป็น 2 ส่วน เรียกว่า Base กับ Quote token เพื่อให้เข้าใจง่ายขอยกตัวอย่างคู่ WBTC-USDC ที่เรา เห็นกันในรูปเลย ซึ่ง Base ก็จะคือ Token ตัวด้านหน้านั้นเอง และมันถูก Quote มาด้วยในหน่วยของ token ที่อยู่ด้านหลัง

WBTC = Base, USDC = Quote

เพื่อให้ง่ายกับการคำนวณ ผมไม่ได้ออกแบบให้เทรดด้วย Quote ค่าอื่นหรอก ให้เทรดด้วย Quote USDC อย่างเดียว ง่ายดี 555

โอเค มา step ถัดไป เมื่อกด Preview ระบบของเราก็คำนวณทั้งหมด ว่าได้กี่ zone ใช้เงินเท่าไหร่ ตรงนี้แหละ เมื่อเราโอเคแล้ว เราก็จะเป็นการกด เริ่มสร้าง grid ขึ้นมา . . . แต่ช้าก่อนในจุดนี้แหละ ที่เราเริ่มเข้ามายุ่งกับกระเป่าที่เราใส่ไปตอนแรกแล้ว คือเราจะสร้าง grid ได้อย่างไร ถ้าเงินเราไม่พอจริงไหม โดยที่จังหวะนี้เราจะเขียนโปรแกรมของเราให้ไปเช็คข้อมูลบน blockchain เพื่อมาเทียบเลย เงินไม่พอ ไม่ให้ไปต่อ 555

อ่ะ สมมติว่าเงินเราพอ เราไปต่อได้ (ไปเติมเงินเตรียมตัวมาเรียบร้อย) ระบบก็จะส่งข้อมูล grid นี้เข้า database แล้วก็ส่งสัญญาณให้ trade engine ไปเปิด order

แวะกันสักนิดนึง เราจะเห็นว่าจะมีทั้งการ preview grid และการส่งคำสั่งไปยัง trade engine ใช่ไหม แล้วอะไรเข้ามาช่วยตรงนี้ละ? คำตอบก็คือ เราใช้ Redis ที่ทำหน้าที่เป็น cache เข้ามาช่วยจัดการตรงนี้ครับ

ในช่วง preview ถ้า user สั่งเรียกดู แล้วไม่ถูกใจมันก็จะสร้างตัวใหม่ขึ้นมาให้ user ดูได้ และถ้า user ไม่ทำอะไรต่อ ตรงนี้มันจะอยู่ใน cache แล้ว 15 นาทีผ่านไปมันก็จะ expire และหายไปเอง ไม่ต้องไปยุ่งกับ database เลย

อีกส่วนหนึ่งก็จะเป็นจังหวะส่งคำสั่งไปยัง trade engine ครับ ในจุดนี้แหละ ต้องมีตัวกลางที่คอยจัดการคิวให้ระหว่าง service ซึ่ง Redis ก็มาช่วยครับ ภาพจะประมาณนี้

เอาล่ะ ทีนี้เราเปิด order ได้แล้ว แต่เราจะไป automate มันต่ออย่างไรใช่ไหม หลักการมันก็มีอยู่ง่ายๆ ถ้าเรา buy ได้แล้ว ต่อไปเราก็ต้องไปเปิด sell หรือถ้าเรา sell ได้แล้วต่อไปเราก็ต้องไปเปิด buy ง่ายๆ แค่นี้เอง อิอิ

ตรงส่วนนี้แหละ เราก็ต้องเพิ่มไปใน trade engine เพื่อให้มันรู้ว่ามันจะเปิด order ใหม่ตอนไหน หลักการคือให้คอยตรวจสอบ order อยู่ตลอดเวลา และถ้าพบว่ามี order ไหนหายไป ก็ให้ไปเช็คว่ามันหายไปเพราะโดน filled จริงๆ หรือป่าว ถ้าจริงก็เปิดกลับอีกฝั่งนึง แต่ถ้าเป็นอย่างอื่นก็เปิดซ่อมที่จุดเดิม

ในด้านของ Webapp ที่เราทำออกมาก็จะได้หน้าตาประมาณนี้ คอยตรวจสอบ order ทุกๆ 5 นาที ถ้ามี order filled ก็เปิดฝั่งตรงข้าม

แค่นี้เราก็ได้ automate grid trading มาใช้งานแบบสบายๆ แล้ว เย้!

หลังจากนี้ก็จะเป็นแค่ส่วนเพิ่มเติมที่จะทำให้ระบบนี้สมบูรณ์ยิ่งขึ้น อย่างเช่น การแจ้ง notification และดูสถานะผ่าน telegram, ระบบ login, ระบบ backup auto และส่งขึ้น google drive พวกนี้ขอยกเอาไว้ไปบทความหน้าแล้วกัน สำหรับบทความนี้ก็พอแค่นี้ก่อน และวันนี้ก็เป็นวันคริสมาสต์ พอดีก็ Merry Christmas กันนะครับทุกคน 🎄

Stay in the Stack

รับสรุปเทคนิคและอัปเดตใหม่ๆ จาก monstack ส่งตรงถึง Email คุณ

MonStack

Stack knowledge and built with ❤️