ข้ามไปที่เนื้อหา

วิธีสร้างบอทเทรดด้วย Python

บทความและวิดีโอนี้นำเสนอคำแนะนำทีละขั้นตอนสำหรับการสร้างหุ่นยนต์เทรดด้วย Python

หมายเหตุ

cTrader เป็นแพลตฟอร์มการเทรดหลักเพียงรายเดียวที่มีการรองรับ Python แบบเนทีฟ ช่วยให้คุณสามารถเขียนโค้ดด้วย Python และสร้างบอท อินดิเคเตอร์ทางเทคนิค และเครื่องมือต่างๆ ได้โดยตรงใน cTrader Windows หรือ Mac ไม่จำเป็นต้องใช้อะแดปเตอร์หรือวิธีแก้ปัญหาที่ซับซ้อน

สร้างหุ่นยนต์เทรด

ในแท็บ cBots ของแอป Algo คลิกปุ่ม New เพื่อเริ่มสร้างบอทเทรดใหม่

ตั้งชื่อให้ cBot และเลือก Python เป็นภาษาโปรแกรมมิ่ง

หมายเหตุ

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

เลือก Using template เป็นวิธีการสร้าง เลือก Grid Sample จากนั้นคลิก Create

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

มาลองสร้าง cBot ของเราเพื่อตรวจสอบความถูกต้องของโค้ด

กด Ctrl+B หรือคลิก Build

กด Cmd+B หรือคลิกไอคอน Build

เพิ่มอินดิเคเตอร์

มาเพิ่มอินดิเคเตอร์เข้าไปในบอทเทรดของเราเพื่อปรับปรุงความแม่นยำ

Relative Strength Index (RSI) เป็นอินดิเคเตอร์ยอดนิยมที่ส่งสัญญาณสภาวะซื้อมากเกินไปหรือขายมากเกินไปในตลาด อินดิเคเตอร์นี้สามารถช่วยให้ cBot ของเราหลีกเลี่ยงการเปิดโพสิชันใหม่เมื่อตลาดถูกดึงไปในทิศทางใดทิศทางหนึ่ง

ผสาน RSI เข้ากับตรรกะของหุ่นยนต์ เริ่มต้นอินดิเคเตอร์ด้วยช่วงเวลาเริ่มต้น 14 และตั้งค่าระดับซื้อมากเกินไปและขายมากเกินไปเป็น 70 และ 30 ตามลำดับ ใช้ราคาปิดของสัญลักษณ์เพื่อสร้าง RSI

1
2
3
4
self.rsi_period = getattr(api, "RsiPeriod", 14)
self.rsi_overbought = getattr(api, "RsiOverbought", 70)
self.rsi_oversold = getattr(api, "RsiOversold", 30)
self.rsi = api.Indicators.RelativeStrengthIndex(api.Bars.ClosePrices, self.rsi_period)

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

1
2
3
4
5
6
if len(self.get_grid_positions()) == 0:
    # self.open_position()
    if self.passes_rsi_filter():
        self.open_position()
    else:
        api.Print("RSI filter blocked initial entry (RSI={:.2f})".format(self.get_rsi_value()))

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

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
if distance >= api.StepPips:
    # self.open_position()
    if self.passes_rsi_filter():
        self.open_position()
    else:
        api.Print("RSI filter: no new entry (RSI={:.2f}, range {}-{})"
                    .format(self.get_rsi_value(), self.rsi_oversold, self.rsi_overbought))

def get_rsi_value(self):
    # Use the last CLOSED bar for stability
    return self.rsi.Result.Last(1)

def passes_rsi_filter(self):
    r = self.get_rsi_value()
    return (r > self.rsi_oversold) and (r < self.rsi_overbought)

ปรับตรรกะการคำนวณสำหรับระยะทางเป็น pip ระหว่างราคาตลาดปัจจุบันและราคาเข้าของโพสิชัน

1
2
3
4
5
6
7
def get_distance_in_pips(self, position):
    # return (position.EntryPrice - api.Symbol.Ask if position.TradeType == TradeType.Buy else api.Symbol.Bid - position.EntryPrice) / api.Symbol.PipSize
    if position.TradeType == TradeType.Buy:
        diff = position.EntryPrice - api.Symbol.Ask
    else:
        diff = api.Symbol.Bid - position.EntryPrice
    return diff / api.Symbol.PipSize

คุณสามารถคัดลอกโค้ด Python ฉบับเต็มพร้อมอินดิเคเตอร์ RSI ที่รวมอยู่ด้านล่างนี้:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
import clr

clr.AddReference("cAlgo.API")

# Import cAlgo API types
from cAlgo.API import *

# Import trading wrapper functions
from robot_wrapper import *

class SupercBot():
    def on_start(self):
        self.volumeInUnits = api.Symbol.QuantityToVolumeInUnits(api.VolumeInLots)
        self.enoughMoney = True

        self.rsi_period = getattr(api, "RsiPeriod", 14)
        self.rsi_overbought = getattr(api, "RsiOverbought", 70)
        self.rsi_oversold = getattr(api, "RsiOversold", 30)
        self.rsi = api.Indicators.RelativeStrengthIndex(api.Bars.ClosePrices, self.rsi_period)

        if len(self.get_grid_positions()) == 0:
            if self.passes_rsi_filter():
                self.open_position()
            else:
                api.Print("RSI filter blocked initial entry (RSI={:.2f})".format(self.get_rsi_value()))

    def on_tick(self):
        grid_positions = self.get_grid_positions()
        net_profit_sum = sum([p.NetProfit for p in grid_positions])
        if net_profit_sum >= api.TargetProfit:
            api.Print("Target profit is reached. Closing all grid positions")
            self.close_grid_positions()
            api.Print("All grid positions are closed. Stopping cBot")
            api.Stop()

        if len(grid_positions) > 0 and self.enoughMoney == True:
            position_with_highest_pips = sorted(grid_positions, key=lambda pos: pos.Pips, reverse=True)[0]
            distance = self.get_distance_in_pips(position_with_highest_pips)          
            if distance >= api.StepPips:
                if self.passes_rsi_filter():
                    self.open_position()
                else:
                    api.Print("RSI filter: no new entry (RSI={:.2f}, range {}-{})"
                              .format(self.get_rsi_value(), self.rsi_oversold, self.rsi_overbought))

    def get_rsi_value(self):
        # Use the last CLOSED bar for stability
        return self.rsi.Result.Last(1)

    def passes_rsi_filter(self):
        r = self.get_rsi_value()
        return (r > self.rsi_oversold) and (r < self.rsi_overbought)

    def get_grid_positions(self):
        return [pos for pos in api.Positions if pos.SymbolName == api.SymbolName and pos.TradeType == api.TradeType]

    def open_position(self):
        result = api.ExecuteMarketOrder(api.TradeType, api.SymbolName, self.volumeInUnits, "Grid")
        if result.Error == ErrorCode.NoMoney:
            self.enoughMoney = False
            api.Print("Not enough money to open additional positions")

    def close_grid_positions(self):
        for position in self.get_grid_positions():
            position.Close()

        if len(self.get_grid_positions()) > 0:
            self.close_grid_positions()

    def get_distance_in_pips(self, position):
        if position.TradeType == TradeType.Buy:
            diff = position.EntryPrice - api.Symbol.Ask
        else:
            diff = api.Symbol.Bid - position.EntryPrice
        return diff / api.Symbol.PipSize

เริ่มต้นอินสแตนซ์

กลับมาที่ cBot ของเราและสร้างมันขึ้นมา ตอนนี้ คลิกไอคอน เริ่ม cBot สำหรับอินสแตนซ์ใดๆ และหุ่นยนต์เทรดจะเริ่มทำงาน

หรือคุณสามารถคลิก เพิ่มอินสแตนซ์ ระบุพารามิเตอร์อินสแตนซ์ที่คุณต้องการ เพิ่มอินสแตนซ์ใหม่และเริ่มต้น

โดยการ เพิ่ม และ ปรับแต่ง อินสแตนซ์ใหม่ คุณสามารถรัน cBot พร้อมกันบนสัญลักษณ์ ช่วงเวลา หรือพารามิเตอร์ที่แตกต่างกันได้

รันบอทที่อื่น

เมื่อเปิดใช้งาน ซิงโครไนซ์บนคลาวด์ cBot จะปรากฏโดยอัตโนมัติในแอปพลิเคชัน cTrader ทั้งหมดที่ cTID ของคุณใช้งานอยู่ เราสามารถเริ่มต้นหุ่นยนต์เทรดเดียวกันในคลาวด์ในแอป cTrader ใดก็ได้ รวมถึง cTrader Mobile และ Web

ใน cTrader Algo ให้เริ่มต้น cBot

บทความนี้ได้แสดงวิธีการสร้างหุ่นยนต์เทรด Python และเริ่มต้นใช้งาน ช่วยให้คุณสามารถทำให้กลยุทธ์ของคุณเป็นอัตโนมัติและรัน Algo บนอุปกรณ์ใดก็ได้

Image title