确实,中间喂价需要纳入计算来确定喂价合理范围。
一些参数都需要更多优化,包括计算间隔,1小时是否合适?是否10分钟更合适?这个可以再考虑,先拿1小时作推演。
感觉溢价较低时让喂价快速向市场价方向回归还是需要的,i=0.9i是基于这方面考虑,可能需要选择更好收敛算法。
再次强调一个词:静差。
静差又称余差。在控制系统中,比例调节器的输入、输出量之间存在着对应的比例关系,变化量经比例调节达到平衡时,不能恢复到给定值时的称为“静差”。(来自百度百科:https://baike.baidu.com/item/%E9%9D%99%E5%B7%AE)
积分项的目的就是为了减小甚至消除静差。也就是说,溢价在0附近时,合理喂价不一定在0附近。
i=0.9i这种做法,反而是干扰了积分项的作用。
实际上,当 premium 变小时, premium/Ti 也会变小,也就是增加的积分并不多,属于自动微调。
当premium较小时,p的部分已经相当小,主要对premium进行校正的因子就是i了,也就是说,i已经在合理值附近。那么,这里主动让i也减小,显然就不对,会造成反向震荡导致premium增大。
更新:
Pdex:内盘bitCNY价格
Pf: 当前喂价
premium:溢价百分比
Premium0: 一小时前的溢价百分比
Ti=10; Td=1;p=4
convergence factor = 0.96
get Pdex, Pf, premium;
premium0=premium;
k=1+p*pemium;
d=0, i= Pf/Pdex-k; ##设置初始值使得初始喂价等于当前喂价
while True:
get Pdex, Pf, premium;
if (上次执行后计时器已过去一小时):
i+=premium/Ti;
d=Td*(premium-premium0);
premium0=premium;
if -1%<premium<1%:
i=i*convergence factor; ##溢价接近0时逐步减小积分环节影响,以免引起震荡
k=1+p*pemium; ##去除产生k的复杂分段公式,直接线性,因为积分环节已经可以保证补偿不断增加,而且也无必要过多在意MSSR限制。
if i+k+d>1:
feed price = Pdex*min(i+k+d, 1.5, 1.2*Pf/Pdex) ##向上调价时,喂价不超过内盘价1.5倍,不超过当前喂价1.2倍
else:
feed price = Pdex*max(i+k+d, 0.91*Pf/Pdex)##向下调价时,喂价不得低于当前喂价0.91倍。
再推演下:
当 premium 一个小时从 0% 变成 1%,也就是 1.00变成1.01,此时 i=0.001, k=1.04, d=0.01,喂价 1.051
premium维持1%不变,i=(0.001+0.001)*0.96=0.00192,k=1.04,d=0,喂价 1.04192(震荡)
premium 维持 1% ,i=(0.00192+0.001)*0.96=0.0028,k=1.04,d=0,喂价1.0428(缓慢积累)
premium 从1%变成2%, i=(0.0028+0.002)=0.0048,k=1.08,d=0.01,喂价1.0948
premium 维持 2%,i=(0.0048+0.002)=0.0068, k=1.08,d=0,喂价1.0868(震荡)
premium 从2%变成3%,i=(0.0068+0.003)=0.0098,k=1.12,d=0.01,喂价1.1398
premium 维持 3%,i=0.0098+0.003=0.0128,k=1.12,d=0,喂价1.1328
premium 维持 3%再过10小时,i=0.0128+0.003*10 = 0.0428, k=1.12, d=0, 喂价1.1628
这个看起来好一点了。个人感觉:计时器 30 分钟左右比较合适;积分可以更快点;微分可以再调小点。
还是要解决中间价问题。如果大家都用这个算法或者类似算法,那么才可以不考虑中间价问题。