dYdX 전략 설계의 예

저자:리디아, 창작: 2022-11-07 10:59:29, 업데이트: 2023-09-15 21:03:43

img

많은 사용자들의 요구에 대응하여 FMZ 플랫폼은 최근 분산화 된 거래소인 dYdX에 액세스했습니다. 전략이있는 사람은 디지털 통화 dYdX를 획득하는 과정을 즐길 수 있습니다. 저는 오랫동안 스토카스틱 거래 전략을 쓰고 싶었습니다. 수익을 올리는지 상관없이. 다음으로 우리는 함께 스토카스틱 거래 전략을 설계합니다. 전략이 잘 수행하는지 여부에 관계없이 전략 디자인을 배우십시오.

스토카스틱 거래 전략 설계

브레인스토밍을 해보자! 무작위 지표와 가격으로 무작위적으로 주문을 하는 전략을 설계할 계획이다. 주문을 하는 것은 길거나 짧게 가는 것, 확률에 베팅하는 것뿐이다. 그러면 무작위 숫자를 1~100으로 사용하여 길거나 짧게 가는지를 결정할 것이다.

장기화 조건: 무작위 숫자 1~50 가공 조건: 무작위 숫자 51~100

따라서 길고 짧게 가는 양쪽 모두 50개의 숫자입니다. 다음으로, 포지션을 닫는 방법에 대해 생각해 보겠습니다. 베팅이기 때문에 이기고 잃는 기준이 있어야 합니다. 우리는 거래에서 고정된 스톱 이익과 손실에 대한 기준을 설정합니다. 이기는 경우 스톱 이익, 잃는 경우 스톱 손실을 설정합니다. 스톱 이익과 손실의 양에 관해서는 실제로 이익과 손실 비율에 영향을 미칩니다. 오 예! 이 승률에도 영향을 미칩니다! (이 전략 설계가 효과적입니까? 긍정적 인 수학적 기대로 보장 될 수 있습니까? 먼저하십시오! (후에, 그것은 단지 학습, 연구을위한 것입니다!)

트레이딩은 무료가 아닙니다. 우리의 스톡라스틱 트레이딩 승률을 50% 이하로 끌어내기 위해 충분한 미끄러짐, 수수료 등이 있습니다. 포지션을 증가시키기 위해 멀티플리커를 설계하면 어떨까요? 베팅이기 때문에 무작위 거래의 연속에서 8 ~ 10 번 동안 잃을 확률은 낮아야합니다. 따라서 첫 번째 거래는 가능한 한 작은 양의 주문을 배치하도록 설계되었습니다. 그러면 내가 잃으면 주문의 양을 증가시키고 무작위로 주문을 계속합니다.

좋습니다. 전략은 간단하게 설계되었습니다.

소스 코드가 설계된:

var openPrice = 0 
var ratio = 1
var totalEq = null 
var nowEq = null 

function cancelAll() {
    while (1) {
        var orders = _C(exchange.GetOrders)
        if (orders.length == 0) {
            break
        }
        for (var i = 0 ; i < orders.length ; i++) {
            exchange.CancelOrder(orders[i].Id, orders[i])
            Sleep(500)
        }
        Sleep(500)
    }
}

function main() {
    if (isReset) {
        _G(null)
        LogReset(1)
        LogProfitReset()
        LogVacuum()
        Log("reset all data", "#FF0000")
    }

    exchange.SetContractType(ct)

    var initPos = _C(exchange.GetPosition)
    if (initPos.length != 0) {
        throw "Strategy starts with a position!"
    }
    
    exchange.SetPrecision(pricePrecision, amountPrecision)
    Log("set the pricePrecision", pricePrecision, amountPrecision)
    
    if (!IsVirtual()) {
        var recoverTotalEq = _G("totalEq")
        if (!recoverTotalEq) {
            var currTotalEq = _C(exchange.GetAccount).Balance   // equity
            if (currTotalEq) {
                totalEq = currTotalEq
                _G("totalEq", currTotalEq)
            } else {
                throw "failed to obtain initial interest"
            }
        } else {
            totalEq = recoverTotalEq
        }
    } else {
        totalEq = _C(exchange.GetAccount).Balance
    }
    
    while (1) {
        if (openPrice == 0) {
            // Update account information and calculate profits
            var nowAcc = _C(exchange.GetAccount)
            nowEq = IsVirtual() ? nowAcc.Balance : nowAcc.Balance  // equity
            LogProfit(nowEq - totalEq, nowAcc)
            
            var direction = Math.floor((Math.random()*100)+1)   // 1~50 , 51~100
            var depth = _C(exchange.GetDepth)
            if (depth.Asks.length <= 2 || depth.Bids.length <= 2) {
                Sleep(1000)
                continue 
            }
            if (direction > 50) {
                // long
                openPrice = depth.Bids[1].Price
                exchange.SetDirection("buy")
                exchange.Buy(Math.abs(openPrice) + slidePrice, amount * ratio)
            } else {
                // short
                openPrice = -depth.Asks[1].Price
                exchange.SetDirection("sell")
                exchange.Sell(Math.abs(openPrice) - slidePrice, amount * ratio)
            }       
            Log("place", direction > 50 ? "buying order" : "selling order", ", price:", Math.abs(openPrice))
            continue
        }

        var orders = _C(exchange.GetOrders)
        if (orders.length == 0) {
            var pos = _C(exchange.GetPosition)
            if (pos.length == 0) {
                openPrice = 0
                continue
            }
            
            // Test for closing the position
            while (1) {
                var depth = _C(exchange.GetDepth)
                if (depth.Asks.length <= 2 || depth.Bids.length <= 2) {
                    Sleep(1000)
                    continue 
                }
                var stopLossPrice = openPrice > 0 ? Math.abs(openPrice) - stopLoss : Math.abs(openPrice) + stopLoss 
                var stopProfitPrice = openPrice > 0 ? Math.abs(openPrice) + stopProfit : Math.abs(openPrice) - stopProfit
                var winOrLoss = 0 // 1 win , -1 loss 
                
                // drawing the line
                $.PlotLine("bid", depth.Bids[0].Price)
                $.PlotLine("ask", depth.Asks[0].Price)
                
                // stop loss
                if (openPrice > 0 && depth.Bids[0].Price < stopLossPrice) {
                    exchange.SetDirection("closebuy")
                    exchange.Sell(depth.Bids[0].Price - slidePrice, pos[0].Amount)
                    winOrLoss = -1
                } else if (openPrice < 0 && depth.Asks[0].Price > stopLossPrice) {
                    exchange.SetDirection("closesell")
                    exchange.Buy(depth.Asks[0].Price + slidePrice, pos[0].Amount)
                    winOrLoss = -1
                }
                
                // stop profit
                if (openPrice > 0 && depth.Bids[0].Price > stopProfitPrice) {
                    exchange.SetDirection("closebuy")
                    exchange.Sell(depth.Bids[0].Price - slidePrice, pos[0].Amount)  
                    winOrLoss = 1
                } else if (openPrice < 0 && depth.Asks[0].Price < stopProfitPrice) {
                    exchange.SetDirection("closesell")
                    exchange.Buy(depth.Asks[0].Price + slidePrice, pos[0].Amount)
                    winOrLoss = 1
                }
                
                // Test the pending orders
                Sleep(2000)
                var orders = _C(exchange.GetOrders)                
                if (orders.length == 0) {
                    pos = _C(exchange.GetPosition)
                    if (pos.length == 0) {
                        if (winOrLoss == -1) {
                            ratio++
                        } else if (winOrLoss == 1) {
                            ratio = 1
                        }
                        break
                    }                    
                } else {
                    // cancel pending orders
                    cancelAll()
                    Sleep(2000)
                    pos = _C(exchange.GetPosition)
                    // update the position after cancellation, and check it again
                    if (pos.length == 0) {
                        if (winOrLoss == -1) {
                            ratio++
                        } else if (winOrLoss == 1) {
                            ratio = 1
                        }
                        break
                    }    
                }
                
                var tbl = {
                    "type" : "table", 
                    "title" : "info", 
                    "cols" : ["totalEq", "nowEq", "openPrice", "bid1Price", "ask1Price", "ratio", "pos.length"], 
                    "rows" : [], 
                }
                tbl.rows.push([totalEq, nowEq, Math.abs(openPrice), depth.Bids[0].Price, depth.Asks[0].Price, ratio, pos.length])
                tbl.rows.push(["pos", "type", "amount", "price", "--", "--", "--"])
                for (var j = 0 ; j < pos.length ; j++) {
                    tbl.rows.push([j, pos[j].Type, pos[j].Amount, pos[j].Price, "--", "--", "--"])
                }
                LogStatus(_D(), "\n", "`" + JSON.stringify(tbl) + "`")
            }
        } else {
            // cancel the pending orders
            // reset openPrice
            cancelAll()
            openPrice = 0
        }
        Sleep(1000)
    }
}

전략 매개 변수

img

그래요! 전략은 이름이 필요해요, 그라든가 크기를 추측하세요 (dYdX 버전)

백테스트

백테스팅은 참고용입니다. >_

img

img

img

img

백테스트가 끝났어 버그가 없어

이 전략은 학습 및 참조를 위해만 사용 됩니다. 실제 봇에서 사용하지 마십시오!


관련

더 많은