历史上,所有经济活动都是建立在中介机构之上的。 双方之间任何甚至简单的交易都伴随着各种中介机构的介入,包括银行,交易所,票据交换所等。 排除中介人可能会使交互更加有效。 那么,为什么不尝试在区块链的基础上构建一个新的,去中心化的基础架构呢? 在这篇文章中,我们将讨论如何开始我们的基础设施之旅:我们开发了区块链交易,并最终进行了回购-由证券担保的货币贷款。

短期债券
我们在区块链上进行的第一个场外金融交易是MTS移动运营商的短期债券发行,国家清算所(NSD)参与了此次发行。 这是所有存托机构的“中央银行”。 存托机构是基础结构中介机构,保留证券所有者的记录并进行发行。
在该交易中,MTS通过调用智能合约的功能,在区块链中记录了将证券出售给Sberbank的意愿表达,并在区块链中确认其同意交易条款。 NSD收到了双方签署的抗辩令,并在其会计系统中执行了抗辩令。 此外,区块链还显示了证券和货币交易参与者的账户。
在该项目中,我们选择了开放源代码
Hyperledger Fabric 1.1平台,该平台旨在创建封闭的企业区块链解决方案。 公共区块链在这里不合适,因为我们需要确保数据隐私。 我们在以太坊区块链上实施的M.Video在Sberbank的分解试验中遇到了这样的限制。 相比之下,Hyperledger Fabric允许您将交易中的所有参与者放置在专用渠道中,他们可以在其中交换任何必要的信息,并使用功能齐全的智能合约对其进行处理。
MTS债券发行项目的源代码已在GitHub上公开上传。 甚至无需深入研究工作算法,您就可以了解到,在交易的生命周期中,区块链在清算订单的传输中所起的作用不大。 另一方面,根据这些说明,帐户余额发生了变化-因此,从业务逻辑的角度来看,这比简单的电子文档管理服务更有趣。
该解决方案的主要优势是多功能性。 “两个交易对手和一个注册商”计划几乎涵盖了场外交易市场中的所有交易,并且变化很小-大部分是一般的商业交易。
回购1.0
在关于区块链的一个新项目中,我们决定展示如何在去中心化系统中实施回购协议-借贷证券。 通常,这些和其他OTC交易通过中介机构进行-托存机构,票据交换所,经纪人。
在该项目中,我们与Sberbank和外国合作伙伴签订了回购协议。 它已经使用了Hyperledger Fabric 1.2版。 与MTS债券相比,我们有两个区别:
- 交易中只有两个参与者连接到区块链,其存放人Euroclear和Clearstream通过传统数据传输渠道从Sberbank及其对手方的后台收到所有订单。
- 在智能合约中,我们实施了复杂的业务逻辑:将用作贷款抵押品的证券的每日报价下载到了区块链中,并且智能合约考虑了抵押品成本的变化,折扣,退出交易所的日历等参数,计算了提前还款的需求和金额。 没有分布式注册表,就无法获得参与者之间计算算法的这种P2P同步。 这比双方独立计算债务和金额要方便得多-无需费时的对帐,无需确认。
交易对手之间在渠道内组织了聊天和工作流程。 它们上的数据存储在区块链中。 分布式注册表中的每次更改后,渠道成员都会收到一封电子邮件警报。
我们从法律角度制定了“ REPO 1.0”。 在一家大型律师事务所的帮助下,对伦敦高等法院的案件进行了分析。 此外,银行及其交易对手的EDS使用不同的密码算法。
REPO 1.0如何工作?
交易的每一方都有自己的区块链节点。 所有节点在P2P网络中相互连接。 假设您需要达成协议。 我们在交易各方之间部署智能合约,其中对金融工具进行了充分描述。

在我们完成合同创建后,交易员将其签字。 客户还审查并签署合同。 然后对签名进行审查和验证。 在这种情况下,交易是根据英国法律进行的,有关电子数字签名的数据已输入GMRA文件中。 为了由客户进行签名,需要验证签名证书中是否存在授权人。 最后,客户接受合同并同意所有条件。 您可以将任意数量的文档附加到已签订的合同中。
此后,合同将获得“工作中”状态。 加载新的市场价格后,将自动重新计算“进行中”的合同。 如果合同中有担保,则采用市场价格,重新计算“贷款价值”(LTV)-贷款额与担保价值之比。 LTV是回购交易中的关键术语之一,其含义已在合同中规定。 股票价格急剧上涨-LTV变得比GMRA所指示的要少(涉及英国法律时)。 因此,由于考虑到新价格,银行将证券返还给客户(作为一种选择),因此证明银行拥有更高的安全性。
但是,如果LTV变大,则该程序允许您打印抵押品通知-向客户发出有关需要增加额外安全性(股票或金钱)的通知,以便LTV值恢复为初始值。 以前,附带通知只能通过邮件发送,为此创建了单独的文档,并且在创建这些文档期间,LTV可能会再次更改。 现在,我们可以在线查看与客户端相同的计算,我们可以轻松地进行交互。
此外,该计划每天都在考虑利息的情况下确定股票回购的价格。 如果客户在加载市场价格时不同意该价格,他会查看完整的重新计算日志-什么是什么,变成了什么,加载了什么价格,来自何处。 然后,聊天讨论开始。
REPO 2.0
我们希望区块链上的REPO能够根据我们的内部逻辑启动真实资产的移动。 但是在REPO 1.0中,由于在连接西方存托机构方面存在组织上的困难,我们尚未能够实现这一目标。 因此,我们开始了新的Repo 2.0试验。 他有两个目标:
- 交易应在两方和托管人的参与下进行,以充分利用MTS债券项目的基础设施。
- 需要授权区块链重新评估抵押品并建立保证金催缴,该催缴催缴可以由连接到分布式网络的托管机构自动执行。
NSD立即想连接到该项目。 为了使区块链中发起的交易落入管辖国内金融市场的联邦法律的保守领域,我们与律师合作制定了一份五页的电子文档管理协议补充协议。 该文件已由交易各方和NSD签署。
NSD在此交易中充当交换所。 他执行了有关资金和证券流动的所有指示。 此交易是根据俄罗斯法律完成的。
客户接受了带有电子签名的合同。 然后,该协议被Sberbank签署并接受-它检查了所有参数是否符合必要的值以及接受客户人员的权限。 此后,合同开始生效。 NSD上传了市场数据,重新计算了智能合约。
REPO 2.0如何工作?
为了部署网络并使用链代码与客户端接口进行交互,我们使用了
Fabric Starter解决方案。 它提供了REST API,而不是HLF的标准grpc接口,在我们的案例中,它显着降低了集成的复杂性。

网络如下。 在Docker服务器上进行预安装之后,三个方面中的每一个都启动了Fabric Starter,后者创建了带有节点组件的容器。 这些组件包括一个用于与其他组织进行交互的外部同位体以及一个REST API服务,节点通过该服务与客户端应用程序进行交互。 在Starter启动时,还配置了区块链网络,并创建了一个专用渠道,在其中安装了具有背书策略的链代码。 在我们的案例中,每笔交易都必须具有所有三个参与者的签名。
在测试阶段,使用Docker Swarm来组织参与者服务器的连接,但是,为了达成一项真正的协议,他们切换到了DNS。 该平台本身负责消息传输;数据通过TLS加密通过Internet传输。
问题的技术方面
在HLF上开发分布式应用程序的过程非常传统地开始-从数据结构和链代码(实际上是一组存储过程)开始,对它们的调用导致从分类账中存储,修改或读取这些结构。 该平台允许使用各种编程语言来开发链代码和用于本地存储的DBMS。 我们分别更喜欢Go和CouchDB。
在我们的数据模型中,回购项目的核心要素是合同本身及其附属义务。 它们是针对两个飞行员中的每个飞行员以及追加保证金而创建的。 与基于“订单”本质的MTS债券模型相比,该体系结构向前迈了一大步。 还为证券创建了独立的对象,从而对它们进行了部分标记。 但是在进行帐户管理和虚拟虚拟货币化实验的过程中,我们决定推迟到该解决方案的下一个版本。
我们解决方案的主要功能:
- 创建合同。
- 与您的EDS签订合同,确认已接受合同条款。
- 下载市场价格并开始重新计算抵押品价值。 它偏离设定的阈值导致了新的追加保证金义务。
- 反映义务的状况。
在技术方面,重估程序在这里最有趣。 让我们更详细地分析它。
在业务流程中,应在Oracle(由NSD执行的“ REPO 2.0”试点)将更新后的证券报价上载到系统后,每天执行一次该程序。
func (t *CIBContract) recalculationData(stub shim.ChaincodeStubInterface, loadData *loadDataType, curDay string) pb.Response {...}
该过程的主要周期遍历所有已更新其报价的证券。
for _, securities := range loadData.Securities {...}
接下来,进行几次检查。 例如,如果今天接收市场数据的交易所是休息日,则不应进行重新计票。
if t.checkHoliday(stub, contract.Settings.Calendars) == "yes" { hisYes := historyType{curDay, "LoadData. Calendar", "System", "LoadData. Today is holiday ! No load market data to contract !"} ... contract.History = append(contract.History, hisYes) … err = stub.PutState(contrID, contractJSONasBytes) }
为了计算更新的债券价格,应将累计的息票收益率(NDC)添加到加载的净价格中。 该试点为计算NKD的30/360方案提供了支持。
priceIzm = float64(securities.Price + float64(securities.CouponRate)*float64((int(settlementDate.Year()) - int(dateStart.Year()))*360 + (int(settlementDate.Month()) - int(dateStart.Month()))*30 + (int(settlementDate.Day()) - int(dateStart.Day())))*100/360/100) curCurrVal = priceIzm
如果交易货币不同于证券的报价货币,则进行兑换。
if contract.GeneralTerms.PurchasePrice.Currency != securities.Currency { curCurrName = securities.Currency + "-" + contract.GeneralTerms.PurchasePrice.Currency for _, currency := range loadData.Currencies { if currency.Name == curCurrName { curCurrVal = priceIzm * currency.Value } } }
现在我们需要计算LTV。 保留故事的旧系数值。
oldCurLTV := contract.MarginingTerms.CurrentLTV
必须考虑在交易有效期内执行的追加保证金要求。 需求可以来自双方,并且有两种形式:
- 证券。 如果有价证券的市场价格下跌,借款人将提供额外的有价证券。 如果价格上涨,债权人归还部分担保。
- 钱 借款人提前偿还了不再由廉价抵押品支付的那部分贷款。 贷方根据抵押品价值的增加而增加贷款额。
在第一种情况下,只需更新抵押品中的证券数量。 并且如果要靠它们赚钱,还必须累积交易附加条款中规定的获利能力。
for _, addCollateral := range contract.MarginingTerms.AddCollateral { currSumCollateral := addCollateral.Sum + (addCollateral.Sum*contract.MarginingTerms.RateOnCashMargin*float64(deltaColDate) / float64(contract.MarginingTerms.Basis))/100 ... allSumCollateral = allSumCollateral + currSumCollateral ... ht := historyType{curDay, System", "LoadData. Recalculation data(addCollateral) Contract " + contrID + " - currSumCollateral: " + strconv.FormatFloat(float64(currSumCollateral), 'f', 2, 64) ... } ... contract.History = append(contract.History, ht) }
我们计算回购的总金额-实际上,这是我们需要偿还的带息贷款的金额。
rePurchasePriceCur := contract.GeneralTerms.PurchasePrice.Sum + (contract.GeneralTerms.PurchasePrice.Sum*contract.GeneralTerms.RepoRate*float64(deltaSigningDate)/float64(contract.MarginingTerms.Basis))/100
现在我们计算LTV系数。 为此,我们从回购价格中减去现金证券,然后将结果值除以证券中的证券总值。 债权人贷记的金额标有“-”,并将添加到回购价格中。
contract.MarginingTerms.CurrentLTV = (rePurchasePriceCur - allSumCollateral) * float64(100) / (float64(contract.GeneralTerms.PurchasedSecurities.Quantity) * curCurrVal)
最后,我们计算合同中的触发器。 如果LTV值偏离指定的通道,则相同的过程将创建追加保证金的订单对象。
contract = t.checkTriggerEvents(stub, "LoadData", contract, curDay, securities)
并将信息写入历史记录以在UI上显示。
ht := historyType{curDay, "System", "LoadData. Recalculation data(change curLTV, ADTV) Contract " + contrID + " - oldCurLTV: " + strconv.FormatFloat(float64(oldCurLTV), 'f', 2, 64) + ", newCurLTV: " + strconv.FormatFloat(float64(contract.MarginingTerms.CurrentLTV), 'f', 2, 64)...} contract.History = append(contract.History, ht)
总结一下
这种方案不仅适用于证券和合约,而且还适用于其他情况。 例如,对于具有不同电价,不同时间的不同连接的电力供应。 或通过保理-通过发货信号向供应商提供贷款。 在经济学中有许多用例,每个人都必须使用自己的数据源进行验证。
我们的目标是创建一个网络,该网络将银行之间以及全国范围内的客户相互连接,并使用智能合约在其中描述不是加密货币而是传统经济合约的金融工具。 这样的网络将是稳定,开放的,并且,正如它应该在P2P网络中一样,这里没有人会具有特殊的地位。