技術(shù)圖文:如何利用BigOne的API制作自動(dòng)化交易系統(tǒng)--網(wǎng)格交易法

背景

前面,通過(guò)圖文 如何利用 C# 爬取 ONE 的交易數(shù)據(jù)? 向大家介紹了<u>如何爬取在 BigOne 上線(xiàn)的數(shù)字資產(chǎn)的交易數(shù)據(jù)</u>。

其次,通過(guò)圖文 如何利用BigOne的API制作自動(dòng)化交易系統(tǒng) -- 身份驗(yàn)證 向大家介紹了<u>利用 BigOne API 函數(shù)之前的身份驗(yàn)證問(wèn)題</u>。

然后,通過(guò)圖文 如何利用BigOne的API制作自動(dòng)化交易系統(tǒng) -- 獲取賬戶(hù)資產(chǎn) 向大家介紹了<u>利用 BigOne API 函數(shù)獲取自己的賬戶(hù)資產(chǎn)數(shù)據(jù)</u>。

接著,通過(guò)圖文 如何利用BigOne的API制作自動(dòng)化交易系統(tǒng) -- 訂單系統(tǒng) 向大家介紹了 <u>利用 BigOne API 函數(shù)進(jìn)行掛單、撤單、查詢(xún)訂單狀態(tài)等交易操作</u>。

最后,通過(guò)圖文 如何進(jìn)行代碼的重構(gòu)?以封裝 BigOne API 為例 向大家介紹了 <u>利用 Layers 軟件體系結(jié)構(gòu)風(fēng)格重構(gòu)對(duì) BigOne API 的封裝過(guò)程</u>。

有了以上的基礎(chǔ),我們就可以制定交易策略,通過(guò)自動(dòng)化的方式進(jìn)行數(shù)字資產(chǎn)的交易了。從此告別手動(dòng)掛單、撤單、查看是否成交的煩惱!


技術(shù)分析

道氏理論指出,金融市場(chǎng)的價(jià)格變動(dòng)可以分為三種情況,分別是上漲、下跌和牛皮。而在上漲或下跌的過(guò)程中也會(huì)在較短周期上出現(xiàn)連續(xù)的波動(dòng),價(jià)格最終或者以無(wú)趨勢(shì)波動(dòng)呈現(xiàn)出來(lái),或者以短期的波動(dòng)和長(zhǎng)期的趨勢(shì)呈現(xiàn)出來(lái)的。在外匯市場(chǎng)上有一種被稱(chēng)為漁網(wǎng)交易法的交易理念,這種理念認(rèn)為,在一定的時(shí)間周期上,價(jià)格基本處于往復(fù)波動(dòng)的狀態(tài),投資者可以通過(guò)較高的頻率交易,利用限價(jià)單的交易方式來(lái)獲得價(jià)格波動(dòng)的收益。

什么是網(wǎng)格交易法呢?

網(wǎng)格交易法,就是跌買(mǎi)漲賣(mài)。具體做法是把資金分成 n 份,每次投入固定金額,先初始建倉(cāng),再設(shè)定一個(gè)百分比,比如 5%,股價(jià)跌 5% 就買(mǎi)入一份,漲 5% 就賣(mài)出一份,如此反復(fù)買(mǎi)賣(mài),不斷的低吸高拋,不斷產(chǎn)生盈利,從而積少成多。

網(wǎng)格交易法

本次圖文,就是帶著大家通過(guò) BigOne API 構(gòu)建一個(gè)針對(duì)數(shù)字資產(chǎn)的等金額網(wǎng)格交易策略,該策略的基本流程如下:

網(wǎng)格交易策略的流程圖
  • 創(chuàng)建網(wǎng)格對(duì)象:根據(jù)歷史成交數(shù)據(jù)確定向上、向下的網(wǎng)格密度(寬度)以及確定每個(gè)網(wǎng)格賣(mài)出、買(mǎi)入的價(jià)格和數(shù)量。
  • 撤銷(xiāo)全部訂單:撤銷(xiāo)當(dāng)前未完成的訂單。
  • 掛買(mǎi)入訂單:形成買(mǎi)入的網(wǎng)格。
  • 掛賣(mài)出訂單:形成賣(mài)出的網(wǎng)格。
  • 判斷訂單狀態(tài):監(jiān)測(cè)數(shù)字資產(chǎn)價(jià)格是否觸及網(wǎng)格,如果觸及并成交則重新創(chuàng)建網(wǎng)格對(duì)象,如此往復(fù)執(zhí)行。

代碼實(shí)現(xiàn)

Step1 定義網(wǎng)格交易用到的數(shù)據(jù)結(jié)構(gòu)

<u>表示訂單的結(jié)構(gòu) Order</u>

public class Order
{
    // 價(jià)格
    public double Price { get; set; }
    // 數(shù)量
    public double Amount { get; set; }
    
    public Order(double price, double amount)
    {
        Price = price;
        Amount = amount;
    }
}

<u>表示數(shù)字貨幣資產(chǎn)的接口 IDigitalCurrency</u>。

public interface IDigitalCurrency
{
    // 資產(chǎn)ID
    string AssetId { get; }
    
    // 獲取該資產(chǎn)的歷史記錄
    List<AssetData> GetHistoryData(string period, string time, string limit);

    // 獲取該資產(chǎn)的歷史記錄
    List<AssetData> GetHistoryData();
}

<u>利用 BTC 來(lái)實(shí)現(xiàn)數(shù)字資產(chǎn)接口舉例</u>。

代碼原理參見(jiàn):如何利用 C# 爬取 ONE 的交易數(shù)據(jù)?

public class Btc : IDigitalCurrency
{
    public string AssetId { get; } = "BTC";

    public List<AssetData> GetHistoryData(string period, string time, string limit)
    {
        string url =
            "https://b1.run/api/xn/v1/asset_pairs/550b34db-696e-4434-a126-196f827d9172/candles?"
            + "period=" + period
            + "&time=" + time
            + "&limit=" + limit;

        ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
        IHtmlDocument document = new JumonyParser().LoadDocument(url);
        List<IHtmlNode> nos = document.Nodes().ToList();
        string str = nos[0].ToString();
        StringReader sr = new StringReader(str);
        JsonTextReader jsonReader = new JsonTextReader(sr);
        JsonSerializer serializer = new JsonSerializer();
        JsonOne one = serializer.Deserialize<JsonOne>(jsonReader);
        return one.data;
    }

    public List<AssetData> GetHistoryData()
    {
        string period = "DAY1";
        DateTime dt = DateTime.Now;
        string time = dt.Year + "-" + dt.Month.ToString().PadLeft(2, '0')
                        + "-" + dt.Day.ToString().PadLeft(2, '0')
                        + "T00:00:00.000Z";
        string limit = "250";
        return GetHistoryData(period, time, limit);
    }
}

Step2 網(wǎng)格交易的抽象結(jié)構(gòu) GridMethod。

public abstract class GridMethod
{
    // 資產(chǎn)
    public IDigitalCurrency Asset { get; protected set; }
    // 市場(chǎng)交易對(duì)
    public string MarketId { get; protected set; }
    // 網(wǎng)格的基準(zhǔn)價(jià)格
    public double BasePrice { get; protected set; }
    // 按照基準(zhǔn)價(jià)格進(jìn)行購(gòu)買(mǎi)時(shí),所用的資金
    public double BaseMoney { get; protected set; }
    // 取數(shù)據(jù)的天數(shù),用于計(jì)算網(wǎng)格密度
    public int Days { get; protected set; }
    // 每日交易的頻數(shù),用于計(jì)算網(wǎng)格密度
    public int DailyTurnover { get; protected set; }
    // 向上網(wǎng)格的密度(寬度)
    public double GridAmplitudeUp { get; protected set; }
    // 向下網(wǎng)格的密度(寬度)
    public double GridAmplitudeDown { get; protected set; }
    // 向上,向下劃分網(wǎng)格的條數(shù)
    public int GridCount { get; protected set; }
    // 訂單列表
    public List<Order> OrderList { get; protected set; }
    // 計(jì)算網(wǎng)格密度(寬度)
    protected abstract void CalculateAmplitude();

    // 計(jì)算網(wǎng)格訂單
    protected abstract void CalculateGrid();

    // 撤銷(xiāo)所有訂單
    public abstract void CancelAllOrder();

    // 創(chuàng)建買(mǎi)入訂單
    public abstract List<OrderResponse> CreateBidOrders();

    // 創(chuàng)建賣(mài)出訂單
    public abstract List<OrderResponse> CreateAskOrders();

    // 網(wǎng)格的格式化輸出
    public override string ToString()
    {
        string infor = "AssetId:" + Asset.AssetId + Environment.NewLine
                        + "MarketId:" + MarketId + Environment.NewLine
                        + "BasePrice:" + BasePrice + Environment.NewLine
                        + "BaseMoney:" + BaseMoney + Environment.NewLine
                        + "Days:" + Days + Environment.NewLine
                        + "DailyTurnover:" + DailyTurnover + Environment.NewLine
                        + "GridAmplitudeUp:" + GridAmplitudeUp + Environment.NewLine
                        + "GridAmplitudeDown:" + GridAmplitudeDown + Environment.NewLine
                        + "GridCount:" + GridCount;
        return infor;
    }
}

Step3 等金額的網(wǎng)格策略 GridMethodEqualMoney。

該交易策略的每個(gè)網(wǎng)格所使用的網(wǎng)格寬度相同、金額相同,即是一種沉淀數(shù)字資產(chǎn)的交易策略。

public sealed class GridMethodEqualMoney : GridMethod
{
    private readonly IDigitalCurrencyUtility _digitalCurrencyUtility;

    public GridMethodEqualMoney(IDigitalCurrency asset, string marketId, int days, int dailyTurnover,
        double baseMoney, double basePrice, int gridCount, IDigitalCurrencyUtility digitalCurrencyUtility)
    {
        _digitalCurrencyUtility = digitalCurrencyUtility;
        Asset = asset;
        MarketId = marketId;
        BasePrice = basePrice;
        BaseMoney = baseMoney;
        Days = days;
        DailyTurnover = dailyTurnover;
        GridCount = gridCount;

        //計(jì)算向上、向下的網(wǎng)格寬度
        CalculateAmplitude();
        //計(jì)算訂單列表
        CalculateGrid();
    }

    protected override void CalculateAmplitude()
    {
        //根據(jù)以往的成交量數(shù)據(jù),計(jì)算指定周期的振幅。
        List<AssetData> lstTrade = Asset.GetHistoryData();
        List<double> lst = new List<double>();
        
        int count = Days < lstTrade.Count - 1 ? Days : lstTrade.Count - 1;
        for (int i = 0; i < count; i++)
        {
            double zf = (lstTrade[i].high - lstTrade[i].low)/lstTrade[i + 1].close;
            lst.Add(zf);
        }
        double result = lst.Count == 0 ? 0.02 : Math.Round(lst.Average()/(2.0*DailyTurnover), 4);
        result = Math.Max(0.02, result);
        GridAmplitudeUp = result;
        GridAmplitudeDown = result;
    }

    protected override void CalculateGrid()
    {

        OrderList = new List<Order>();
        double price = Math.Round(BasePrice, 6);
        double amount = Math.Round(BaseMoney/price, 3);
        Order order = new Order(price, amount);
        OrderList.Add(order);

        for (int i = 0; i < GridCount; i++)
        {
            price = Math.Round(price/(1.0 - GridAmplitudeUp), 6);
            amount = Math.Round(BaseMoney/price, 3);
            order = new Order(price, amount);
            OrderList.Add(order);
        }

        price = Math.Round(BasePrice, 6);
        for (int i = 0; i < GridCount; i++)
        {
            price = Math.Round(price*(1.0 - GridAmplitudeDown), 6);
            amount = Math.Round(BaseMoney/price, 3);
            order = new Order(price, amount);
            OrderList.Add(order);
        }
        OrderList = OrderList.OrderBy(a => a.Price).ToList();
    }

    public override void CancelAllOrder()
    {
        _digitalCurrencyUtility.CancelAllOrder(MarketId);
    }

    public override List<OrderResponse> CreateBidOrders()
    {
        List<Order> lst = OrderList.GetRange(0, GridCount);
        return _digitalCurrencyUtility.CreateBidOrders(lst, MarketId);
    }

    public override List<OrderResponse> CreateAskOrders()
    {
        List<Order> lst = OrderList.GetRange(GridCount + 1, GridCount);
        return _digitalCurrencyUtility.CreateAskOrders(lst, MarketId);
    }
}

總結(jié)

到此為止,網(wǎng)格交易策略的實(shí)現(xiàn)框架就基本介紹完了,下面是我利用該框架對(duì) BTC、EOS、BTM、PRS、ONE等 進(jìn)行網(wǎng)格交易的截圖。

<u>ONE-USDT 交易對(duì)</u>

ONE-USDT

<u>PRS-USDT 交易對(duì)</u>

PRS-USDT

<u>EOS-USDT 交易對(duì)</u>

EOS-USDT

<u>BTM-USDT 交易對(duì)</u>

BTM-USDT

該策略的回測(cè)和評(píng)估需要積累一定數(shù)據(jù)才能進(jìn)行,我們后面再來(lái)介紹。

網(wǎng)格交易看起來(lái)似乎簡(jiǎn)單,其實(shí)里面包含了很復(fù)雜的問(wèn)題,比如市場(chǎng)趨勢(shì)向上、向下、橫盤(pán)震蕩時(shí)我們?nèi)绾握{(diào)整向上、向下網(wǎng)格的寬度;如何確定每個(gè)網(wǎng)格買(mǎi)入、賣(mài)出的數(shù)字資產(chǎn)數(shù)量(金字塔、倒金字塔、同量……);資金固定的情況下如何進(jìn)行資金分配等等。這些都是需要考慮和寫(xiě)程序根據(jù)不同的場(chǎng)景進(jìn)行自適應(yīng)調(diào)整的。慢慢來(lái)??!今天就到這里吧!See You!


相關(guān)圖文

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀(guān)點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容