LOADING...
LOADING...
LOADING...
当前位置: 玩币族首页 > 新闻观点 > 在Signals框架的设计中利用六边形架构

在Signals框架的设计中利用六边形架构

2019-07-10 不详 来源:网络
这是我们关于Signals平台技术方面系列文章的续篇。让我们再次深入研究一个运行许多后台进程的系统的基本原理,它允许任何人简单地创建、测试和部署策略来增强加密货币交易体验。

自从我们开始开发Signals平台以来,我们一直专注于定义交易模型的核心组件——Signals框架。我们的目标是使库非常稳定,只有当我们使用对客户端有利的一些特性扩展API时,才需要发布库的新版本。我们知道我们不能每次提高某个方法的性能或修复某个bug时都强迫我们的交易员升级他们的框架版本。另一方面,我们还希望框架非常灵活,能够支持各种数据流和指示器组合,而不需要修改库代码本身。 本文展示了如何应用六边形架构原则来解决所描述的挑战。

领域层

实现稳定性和灵活性的关键是使Signals Framework库尽可能轻量级。在六边形的体系结构中,该库基本上代表了Signals网络的领域,模型包括策略、数据序列、市场、交换、货币对、各种类型的订单、数据市场和指标市场。关于领域逻辑,我们只添加了与构建自动化交易策略相关的方法。有设置策略数据和指标、记录数据流更新执行的回调、进入和退出市场头寸、日志记录等功能。该领域的一个重要部分也是策略属性,如实际市场时间、当前头寸和未决订单,这些属性用于做出交易决策。

端口和适配器

您可能想知道,当策略基类中有诸如EnterLongLimit之类的方法或诸如Time之类的属性时,我们如何才能声称库是轻量级的。当然,必须有一些代码负责创建顺序并将其一直发布到UI,以及Time属性背后的一些逻辑中,它将策略时间与所有数据流同步。当然,您是对的,但是实际执行逻辑的代码位于Signals框架代码库之外。在库中,我们只依赖于端口的接口,如下面的代码片段所示。

public abstract class StrategyBase : IStrategy
{
private IEnumerable<Market> StrategyMarkets;
private IStrategyTimeProvider StrategyTimeProvider;
private IStrategyOrdersManager StrategyOrdersManager;
private IStrategyLogger StrategyLogger;

public DateTime Time => StrategyTimeProvider.CurrentTime;

public abstract void Setup(DataMarketplace data, IndicatorsMarketplace indicators);

public IOrder EnterLongLimit(double limitPrice, string label = null)
{
return StrategyOrdersManager
.AddEntryPendingOrder(Market, StrategyPositionType.Long,
limitPrice, OrderType.Limit, label);
}

....
}

在这个策略基类的预览中,IStrategyTimeProvider、IStrategyOrdersManager和IStrategyLogger都只是Signals框架代码库中的端口。实现接口(适配器)的类位于库的外部,位于策略执行服务代码基的内部。基本上,我们使用反转控制来保持框架库不受所有基础设施依赖的影响,因为端口只是在Signals框架中声明的接口。适配器是实现实际业务逻辑和引用数据库驱动程序、消息代理客户机、日志提供者等的适配器。

数据流和指标模块

端口和适配器使Signals框架中的域函数非常小,因为它们只包含将参数传递给端口的代码。这种方法适用于已经成为Signals框架API一部分的方法。但我们需要一个不同的解决方案来支持基于数据和指标市场的各种订阅模型。我们不希望在市场上每次引入新的技术指标或新的数据流类型时,都发布Signals框架库的新版本。

更重要的是,我们希望避免框架包对各种数据流和指示器模块的依赖。相反,我们需要从这些包中引用Signals框架库,以使用数据集、市场和其他域模型。因此,我们决定每个指示器和数据流都有自己的库,其中包含其域模型定义。当用户想要使用它时,他们必须在策略代码编辑器中向库添加引用。

在下面的代码中,您可以看到GoogleTrends数据流的一个假设实现,它可以用于对给定市场的情绪分析。它包含GoogleTrend和googletrendoptions域模型的定义。还有一个datamarketplace扩展方法GoogleTrends(TimeSpan trendStartOffset, string currency)的实现,它为策略开发人员提供了一个很好的接口,可以在一个emarketplace中指定谷歌趋势流。GoogleTrends(5年,“BTC”)API调用。

using Signals.Framework;

public class GoogleTrend
{
public DateTime Timestamp { get; set; }
public string Currency { get; set; }
public double Interest { get; set; }
}

public class GoogleTrendOptions
{
public TimeSpan TrendStartOffset { set; set; }
public string Currency { get; set; }
}

//extension method so that we can define Google Trends stream as
//market.GoogleTrends(TimeSpan.FromDays(365*5), "BTC") in strategy Setup method
public static class GoogleTrendsDataMarketPlaceExtension
{
public static IDataSeries<GoogleTrend> GoogleTrends(this DataMarketPlace marketPlace,
TimeSpan trendStartOffset,
string currency)
{
var options = new GoogleTrendOptions
{
TrendStartOffset = trendStartOffset,
Currency = currency
}

return marketPlace.ConnectDataSeries<GoogleTrend, GoogleTrendOptions>(options);
}
}

您可能已经注意到,这里没有连接到实际数据源的实现。依赖于第三方提供者的代码位于数据流驱动程序集中,它直接由策略执行服务引用。这样,策略只包含对数据流的域模型的引用,我们可以随时升级数据流驱动程序实现,而不用担心是否有一些更改会对实现的策略产生负面影响。

设计成果

最后,Signals矿机库的体系结构是这样的。

可以看到,Signals框架程序集、数据流程序集和指示器程序集不依赖于任何基础设施组件。这使它们保持轻量级,不依赖于其他包,只使用域模型代码。策略执行服务中的数据流驱动程序和适配器处理基础设施代码,并引用消息传递、数据库和API处理所需的所有模块。

本设计的主要优点是:

· 升级很容易——我们可以发布新版本的策略执行服务或数据流驱动程序,而不用担心会破坏策略代码的更改。
· bug空间更小——由于从策略中引用的包是轻量级的,并且几乎不包含逻辑,所以没有太多的空间用于编码错误,而且我们不必仅仅为了一些bug修复而发布新版本。
· 安全性——我们不必担心有人可以通过反编译框架或数据流的程序集并读取代码来探究逻辑和基础设施的细节,因为它们只包含最终用户可以访问的模型和方法。
· 稳定性——自从Signals平台的最初版本发布以来,我们仍然使用相同版本的Signals框架、数据流和指示器程序集。但是,我们对数据流驱动程序和Signals框架的适配器实现进行了多次升级。这样,最终用户就可以从改进的性能和消除的bug中获益,而不需要他们采取任何行动。

—-

编译者/作者:不详

玩币族申明:玩币族作为开放的资讯翻译/分享平台,所提供的所有资讯仅代表作者个人观点,与玩币族平台立场无关,且不构成任何投资理财建议。文章版权归原作者所有。

LOADING...
LOADING...