技术图文(如何进行代码的重构(以封装|技术图文:如何进行代码的重构?以封装 BigOne API 为例))

背景 自从把“量化交易”作为自己精进的技术方向之后,我做了一些准备工作。
比如:
1. 爬取交易所的公告,根据公告的信息来研判数字货币的短期走势
这里面有一个“流动性溢价”的概念,等后面我会结合一些例子跟大家聊聊这块的发现。

  • 如何利用 C# 爬取Gate.io交易所的公告
  • 如何利用 C# 爬取BigOne交易所的公告
2. 爬取平台币 One 的数据,根据数据来估计该数字货币的价值
  • 如何利用 C# 爬取 One 持有者返利数据
  • 如何利用 C# 爬取 ONE 的交易数据
  • One的投资价值分析
3. 封装 BigOne 交易所的 API,改进“网格交易法”做了一款自动化交易系统
  • 如何利用BigOne的API制作自动化交易系统 -- 身份验证
  • 如何利用BigOne的API制作自动化交易系统 -- 获取账户资产
  • 如何利用BigOne的API制作自动化交易系统 -- 订单系统
技术分析 写程序的码农们所追求的一定是自己写的代码是 可复用、可扩展、易维护、灵活性好 的。所以,这两天我用 Layers软件体系结构风格 对自己的交易系统进行了重构。
什么是 Layers软件体系结构风格 呢?
【技术图文(如何进行代码的重构(以封装|技术图文:如何进行代码的重构?以封装 BigOne API 为例))】层次系统组织成一个层次结构,每一层为上一层提供服务,并作为下一层的客户。
技术图文(如何进行代码的重构(以封装|技术图文:如何进行代码的重构?以封装 BigOne API 为例))
文章图片
Layers软件体系结构风格 这种风格的优点是:
  • 支持基于可增加抽象的层的设计。这样允许将一个复杂问题分解成一个增量步骤序列的实现。
  • 支持系统改进。和管道过滤器风格一样,因为每一层最多只与上下相邻两层交互,所以改变每一层的功能最多只影响两层。
  • 支持软件复用。和抽象数据类型风格一样,只要给相邻层提供相同的接口,允许每一层用不同的方法实现。这使得在标准的接口上构建不同的实现成为可能。
基于这种风格,我把 BigOne API 封装为三层:
  • 通讯层,该层的作用是:封装 Get 和 Set 请求,与 BigOne 服务器进行通讯,为中间层提供支撑。
  • 中间层,该层的作用是:调用通讯层,获取 BigOne 服务器返回的数据,该数据不进行处理。
  • 应用层,该层的作用是:为客户端提供对象群体,通过对象之间的协作辅助客户端实现用户需求。
代码实现 Step1 封装最底层 -- 通讯层
internal class HttpUtilManagerBigOne {private const string ApiKey = ""; //您的API Key private const string ApiSecret = ""; //您的API Secret private static readonly HttpUtilManagerBigOne Instance = new HttpUtilManagerBigOne(); //单例模式private HttpUtilManagerBigOne() {}public static HttpUtilManagerBigOne GetInstance() { return Instance; }public string GetToken() { DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1)); long timestamp = Convert.ToInt64( ((long) (DateTime.Now - startTime).TotalMilliseconds).ToString(CultureInfo.InvariantCulture) .PadRight(19, '0')); IDictionary payload = new Dictionary { {"type", "OpenAPI"}, {"sub", ApiKey}, {"nonce", timestamp} }; byte[] secretKey = Encoding.Default.GetBytes(ApiSecret); string token = JWT.Encode(payload, secretKey, JwsAlgorithm.HS256); return token; }public string RequestHttpGet(string url, string param, bool withToken = false) { if (string.IsNullOrEmpty(url)) throw new ArgumentNullException(); if (string.IsNullOrEmpty(param)==false) { if (url.EndsWith("?")) { url = url + param; } else { url = url + "?" + param; } }HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest; if (request == null) return string.Empty; request.ProtocolVersion = HttpVersion.Version10; request.Method = "GET"; request.Timeout = 30000; if (withToken) { string token = "Bearer " + GetToken(); request.Headers.Add("authorization", token); }ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; ServicePointManager.Expect100Continue = true; try { HttpWebResponse response = (HttpWebResponse) request.GetResponse(); Stream stream = response.GetResponseStream(); if (stream == null) return string.Empty; StreamReader reader = new StreamReader(stream, Encoding.UTF8); return reader.ReadToEnd(); } catch { return string.Empty; } }public string RequestHttpPost(string url, Dictionary arguments) { int i = 0; StringBuilder builder = new StringBuilder(); foreach (KeyValuePair item in arguments) { if (i > 0) { builder.Append("&"); } builder.AppendFormat("{0}={1}", item.Key, item.Value); i++; }HttpWebRequest request = (HttpWebRequest) WebRequest.Create(url); request.Method = "POST"; request.ContentType = "application/x-www-form-urlencoded"; string token = "Bearer " + GetToken(); request.Headers.Add("authorization", token); ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12; ServicePointManager.Expect100Continue = true; byte[] data = https://www.it610.com/article/Encoding.UTF8.GetBytes(builder.ToString()); request.ContentLength = data.Length; using (Stream reqStream = request.GetRequestStream()) { reqStream.Write(data, 0, data.Length); reqStream.Close(); } try { HttpWebResponse resp = (HttpWebResponse) request.GetResponse(); Stream stream = resp.GetResponseStream(); if (stream == null) return string.Empty; StreamReader streamReader = new StreamReader(stream, Encoding.UTF8); return streamReader.ReadToEnd(); } catch { return string.Empty; } } }

Step2 封装中间层
internal class RestApiBigOne { public string ApiEntryPoint = @"https://big.one/api/v2/"; public string GetPing() { HttpUtilManagerBigOne httpUtil = HttpUtilManagerBigOne.GetInstance(); string url = ApiEntryPoint + "ping"; string param = ""; string result = httpUtil.RequestHttpGet(url, param); return result; }public string GetTickers() { HttpUtilManagerBigOne httpUtil = HttpUtilManagerBigOne.GetInstance(); string url = ApiEntryPoint + "tickers"; string param = ""; string result = httpUtil.RequestHttpGet(url, param); return result; }public string GetTicker(string marketId) { HttpUtilManagerBigOne httpUtil = HttpUtilManagerBigOne.GetInstance(); string url = ApiEntryPoint + "markets/" + marketId + "/ticker"; string param = "market_id=" + marketId; string result = httpUtil.RequestHttpGet(url, param); return result; }public string GetOrderBook(string marketId) { HttpUtilManagerBigOne httpUtil = HttpUtilManagerBigOne.GetInstance(); string url = ApiEntryPoint + "markets/" + marketId + "/depth"; string param = "market_id=" + marketId; string result = httpUtil.RequestHttpGet(url, param); return result; }public string GetMarketTrade(string marketId) { HttpUtilManagerBigOne httpUtil = HttpUtilManagerBigOne.GetInstance(); string url = ApiEntryPoint + "markets/" + marketId + "/trades"; string param = "market_id=" + marketId; string result = httpUtil.RequestHttpGet(url, param); return result; }public string GetMarket() { HttpUtilManagerBigOne httpUtil = HttpUtilManagerBigOne.GetInstance(); string url = ApiEntryPoint + "markets"; string param = ""; string result = httpUtil.RequestHttpGet(url, param); return result; }public string GetAccount() { HttpUtilManagerBigOne httpUtil = HttpUtilManagerBigOne.GetInstance(); string url = ApiEntryPoint + "viewer/accounts"; string param = ""; string result = httpUtil.RequestHttpGet(url, param, true); return result; }public string GetOrders() { HttpUtilManagerBigOne httpUtil = HttpUtilManagerBigOne.GetInstance(); string url = ApiEntryPoint + "viewer/orders"; string param = ""; string result = httpUtil.RequestHttpGet(url, param, true); return result; }public string GetOrder(string orderId) { HttpUtilManagerBigOne httpUtil = HttpUtilManagerBigOne.GetInstance(); string url = ApiEntryPoint + "viewer/orders/" + orderId; string param = "order_id=" + orderId; string result = httpUtil.RequestHttpGet(url, param, true); return result; }public string CreateOrder(string marketId, string side, string price, string amount) { HttpUtilManagerBigOne httpUtil = HttpUtilManagerBigOne.GetInstance(); string url = ApiEntryPoint + "viewer/orders"; Dictionary param = new Dictionary(); param.Add("market_id", marketId); param.Add("side", side); param.Add("price", price); param.Add("amount", amount); string result = httpUtil.RequestHttpPost(url, param); return result; }public string CancelOrder(string orderId) { HttpUtilManagerBigOne httpUtil = HttpUtilManagerBigOne.GetInstance(); string url = ApiEntryPoint + "viewer/orders/" + orderId + "/cancel"; Dictionary param = new Dictionary(); param.Add("order_id", orderId); string result = httpUtil.RequestHttpPost(url, param); return result; }public string CancelAllOrders(string marketId) { HttpUtilManagerBigOne httpUtil = HttpUtilManagerBigOne.GetInstance(); string url = ApiEntryPoint + "viewer/orders/cancel_all"; Dictionary param = new Dictionary(); param.Add("market_id", marketId); string result = httpUtil.RequestHttpPost(url, param); return result; }public string GetWithdrawal() { HttpUtilManagerBigOne httpUtil = HttpUtilManagerBigOne.GetInstance(); string url = ApiEntryPoint + "viewer/withdrawals"; string param = ""; string result = httpUtil.RequestHttpGet(url, param, true); return result; }public string GetDeposit() { HttpUtilManagerBigOne httpUtil = HttpUtilManagerBigOne.GetInstance(); string url = ApiEntryPoint + "viewer/deposits"; string param = ""; string result = httpUtil.RequestHttpGet(url, param, true); return result; } }

Step3 封装应用层
以获取某交易对 marketId 市场挂单 买单Bid,卖单Ask 为例进行说明。
public class BigOneUtility { private static readonly RestApiBigOne BigOneApi = new RestApiBigOne(); public static void GetOrderBook(string marketId, out List ask, out List bid) { ask = default(List); bid = default(List); string json = BigOneApi.GetOrderBook(marketId); if (string.IsNullOrEmpty(json) == false) { StringReader sr = new StringReader(json); JsonTextReader jsonReader = new JsonTextReader(sr); JsonSerializer serializer = new JsonSerializer(); GetOrderBookJson orderBook = serializer.Deserialize(jsonReader); if (orderBook.data.asks != null) { ask = orderBook.data.asks.OrderBy(a => a.price).ToList(); } if (orderBook.data.bids != null) { bid = orderBook.data.bids.OrderByDescending(a => a.price).ToList(); } } } }

买单结构
public class Bid { /// /// bid price /// public string price { get; set; } /// /// bid amount /// public string amount { get; set; } }

卖单结构
public class Ask { /// /// ask price /// public string price { get; set; } /// /// ask amount /// public string amount { get; set; } }

总结 到此为止,向大家介绍了自己重构 BigOne API 的整体思路,即利用分层的思想把不同功能的对象放在不同的层中,来为上一层提供服务,减少对象之间的耦合。
这是自动运行四个交易对 PRS-USDTBTM-USDTEOS-USDTONE-USDT 的截图,在这个市场里存在很多的套利机会,只要我们肯学习,再懂一些编程的技术,就会拥有大量的机会。
技术图文(如何进行代码的重构(以封装|技术图文:如何进行代码的重构?以封装 BigOne API 为例))
文章图片
自动化交易 好的,今天就到这里吧! See You!
对了,到目前为止已经有9名同学 通过解码 Huffman Code 得到团队的报名方式。
  • 如何加入 LSGO 软件技术团队?
团队的招新仍在进行中,对我们感兴趣的同学欢迎与我联系,我会亲自带着大家学习,一起成长!
相关图文:
  • 如何利用 C# 实现 K 最邻近算法?
  • 如何利用 C# 实现 K-D Tree 结构?
  • 如何利用 C# + KDTree 实现 K 最邻近算法?
  • 如何利用 C# 对神经网络模型进行抽象?
  • 如何利用 C# 实现神经网络的感知器模型?
  • 如何利用 C# 实现 Delta 学习规则?
  • 如何利用 C# 爬取带 Token 验证的网站数据?
  • 如何利用 C# 向 Access 数据库插入大量数据?
  • 如何利用 C# 开发「桌面版百度翻译」软件!
  • 如何利用 C# 开发「股票数据分析软件」(上)
  • 如何利用 C# 开发「股票数据分析软件」(中)
  • 如何利用 C# 开发「股票数据分析软件」(下)
  • 如何利用 C# 爬取「财报说」中的股票数据?
  • 如何利用 C# 爬取 One 持有者返利数据!
  • 如何利用 C# 爬取Gate.io交易所的公告!
  • 如何利用 C# 爬取BigOne交易所的公告!
  • 如何利用 C# 爬取 ONE 的交易数据?
  • 如何利用 C# 爬取「猫眼电影:热映口碑榜」及对应影片信息!
  • 如何利用 C# 爬取「猫眼电影专业版:票房」数据!
  • 如何利用 C# 爬取「猫眼电影:最受期待榜」及对应影片信息!
  • 如何利用 C# 爬取「猫眼电影:国内票房榜」及对应影片信息!
  • 如何利用 C# + Python 破解猫眼电影的反爬虫机制?
  • 如何利用BigOne的API制作自动化交易系统 -- 身份验证
  • 如何利用BigOne的API制作自动化交易系统 -- 获取账户资产
  • 如何利用BigOne的API制作自动化交易系统 -- 订单系统

    推荐阅读