python - 将 R 转换为 Python 用于微观市场结构零智能算法,无法让市场事件的生成正常工作
问题描述
我有以下 R 代码,我想将其更改为 Python,但遇到了失误。运行代码时,似乎在发出取消买单或卖单时,它使用可用的买单数量或可用的卖单数量之一(nb,ns),因此当代码运行时,它会在多次生成后用完订单的事件。所以看来我试图实现的生成功能没有生成足够的订单。因此,订单减少的速度比增加的速度快。这就是为什么我的代码会出现 keyerror 的原因,因为它最终会出现在我的书中找不到的用于取消买单或卖单的 posns。下面是 R 代码,然后是 Python 代码。
R 代码。
#Book setup
L <- 30 #Set number of price levels to be included in iterations
# Generate initial book
LL <- 1000 #Total number of levels in buy and sell books
# Initialize book with asymptotic depth of 5 shares
initializeBook5 <- function()
{
Price <<- -LL:LL
# Book shape is set to equal long-term average from simulation
buySize <<- c(rep(5,LL-8),5,4,4,3,3,2,2,1,rep(0,LL+1))
sellSize <<- c(rep(0,LL),0,1,2,2,3,3,4,4,5,rep(5,LL-8))
book <<- data.frame(Price, buySize, sellSize )
if(logging==T){eventLog <<- as.data.frame(matrix(0,nrow=numEvents,ncol=2))
colnames(eventLog)<<-c("Type","Price")
count <<- 0
eventType <<- c("LB","LS","CB","CS","MB","MS")
eventDescr <<- NA}
}
#Various utility functions
bestOffer <- function(){min(book$Price[book$sellSize>0])}
bestBid <- function(){max(book$Price[book$buySize>0])}
spread <- function(){bestOffer()-bestBid()}
mid <- function(){(bestOffer()+bestBid())/2}
#Functions to find mid-market
bidPosn<-function()length(book$buySize[book$Price<=bestBid()])
askPosn<-function()length(book$sellSize[book$Price<=bestOffer()])
midPosn<-function(){floor((bidPosn()+askPosn())/2)}
#Display center of book
go <- function(){book[(midPosn()-20):(midPosn()+20),]}
#Display book shape
bookShape<-function(band){c(book$buySize[midPosn()+(-band:0)],book$sellSize[midPosn()+1:band])}
bookPlot<-function(band){
plot((-band:band),bookShape(band),
col="red",type="l",xlab="Price",ylab="Quantity")
}
#Choose from L whole numbers in (1,...,L) with uniform probability
pick <- function(m){sample(1:m,1)}
# Switch logging on
logging <- T
#Buy limit order
limitBuyOrder <- function(price=NA){
if (is.na(price))
{prx <<- (bestOffer()-pick(L))}
else prx <<-price
if(logging==T){eventLog[count,]<<- c("LB",prx)}
book$buySize[book$Price==prx]<<-book$buySize[book$Price==prx]+1}
#Sell limit order
limitSellOrder <- function(price=NA){
if (is.na(price))
{prx <<- (bestBid()+pick(L))}
else prx <<-price
if(logging==T){eventLog[count,] <<- c("LS",prx)}
book$sellSize[book$Price==prx]<<-book$sellSize[book$Price==prx]+1}
#Cancel buy order
cancelBuyOrder<-function(price=NA){
q<-pick(nb)
tmp <- cumsum(rev(book$buySize)) #Cumulative buy size from 0
posn <- length(tmp[tmp>=q]) #gives position in list where cumulative size >q
prx <<- book$Price[posn]
if (!is.na(price)) {prx <<-price}
if(logging==T){eventLog[count,]<<- c("CB",prx)}
book$buySize[posn]<<-book$buySize[posn]-1}
#Cancel sell order
cancelSellOrder<-function(price=NA){
q<-pick(ns)
tmp <- cumsum(book$sellSize) #Cumulative sell size from 0
posn <- length(tmp[tmp<q])+1
prx <<- book$Price[posn]
if (!is.na(price)) {prx <<-price}
if(logging==T){eventLog[count,]<<- c("CS",prx)}
book$sellSize[posn]<<-book$sellSize[posn]-1}
#Market buy order
marketBuyOrder <- function(){
prx <<- bestOffer()
if(logging==T){eventLog[count,]<<- c("MB",prx)}
book$sellSize[book$Price==prx]<<-book$sellSize[book$Price==prx]-1}
#Market sell order
marketSellOrder <- function(){
prx <<- bestBid()
if(logging==T){eventLog[count,]<<- c("MS",prx)}
book$buySize[book$Price==prx]<<-book$buySize[book$Price==prx]-1}
#Generate an event and update the buy and sell books
#Note that limit orders may be placed inside the spread
generateEvent <- function()
{
nb <<- sum(book$buySize[book$Price>=(bestOffer()-L)]); # Number of cancelable buy orders
ns <<- sum(book$sellSize[book$Price<=(bestBid()+L)]); # Number of cancelable sell orders
eventRate <- nb*delta+ns*delta + mu +2*L*alpha;
probEvent <- c(L*alpha,L*alpha,nb*delta,ns*delta,mu/2,mu/2)/eventRate;
m <- sample(1:6, 1, replace = TRUE, probEvent); #Choose event type
switch(m,
limitBuyOrder(),
limitSellOrder(),
cancelBuyOrder(),
cancelSellOrder(),
marketBuyOrder(),
marketSellOrder()
);
}
logging <- F
lambda <- 1
mus <- c(10,8,10,10)
nus <- c(1/5,1/5,1/6,1/8)
avgBookShapes<-as.data.frame(matrix(0,nrow=41,ncol=4))
for(i in 1:4){
mu<-mus[i]
nu<-nus[i]
initializeBook5()
numEvents <- 100000 # Average over 100,000 events
avgBookShape <- bookShape(20)/numEvents
for(count in 2:numEvents){
generateEvent()
avgBookShape <- avgBookShape+bookShape(20)/numEvents
}
avgBookShapes[,i]<-avgBookShape
}
Python代码
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
import random
import math
class Zibook():
def __init__(self,ll,l,alpha,mu,delta,num_events,logging=False):
self.ll = ll #total number of levels in buy and sell
self.l = l # set number of price levels to be included in iterations
self.alpha = alpha
self.mu = mu
self.delta = delta
self.num_events = num_events
self.logging = logging
price = np.array(list(range(-self.ll,self.ll +1,1)))
buy_size = np.array([5]*(self.ll-8) + [5,4,4,3,3,2,2,1] + [0]*(self.ll+1))
sell_size = np.array([0]*(self.ll) + [0,1,2,2,3,3,4,4,5] +[5]*(self.ll-8))
book = pd.DataFrame(index=price,columns=['Price','Buy Size','Sell Size','Type'])
book['Price'] = price
book['Buy Size'] = buy_size
book['Sell Size'] = sell_size
book = book.reset_index(drop=True)
self.book = book
event_type = ['LB','LS','CB','CS','MB','MS']
event_descr = np.nan
x = list(range(0,self.num_events,1))
event_log = pd.DataFrame(index=x,columns=['Type','Price'])
self.event_log = event_log
nb = sum(self.book.loc[self.book.Price >= (self.best_offer()-self.l), 'Buy Size']) #number of cancellable buy orders
ns = sum(self.book.loc[self.book.Price <= (self.best_bid()+self.l), 'Sell Size']) #number of cancellable sell order
self.nb = nb
self.ns = ns
def best_offer(self):
df = self.book
a = df.loc[df['Sell Size'] > 0,'Price'].min()
return a
def best_bid(self):
df = self.book
b = df.loc[df['Buy Size']>0 ,'Price'].max()
return b
def spread(self):
spread = (self.best_offer() - self.best_bid())/2
return spread
def mid(self):
mid = (self.best_offer() + self.best_bid())/2
return mid
def bidposn(self):
df = self.book
a = len(df.loc[df.Price <= self.best_bid(),'Buy Size'])-1
return a
def askposn(self):
df = self.book
a = len(df[df['Price'] <= self.best_offer()]['Sell Size']) -1
return a
def midposn(self):
df = self.book
a = ((self.bidposn()+self.askposn())//2)
return a
def centerbook(self):
df = self.book
mid = self.midposn()
return df[mid-20:mid +21]
def bookshape(self,band):
df = self.book
mid = self.midposn()
x = np.arange(-band,0)
y = [df.loc[(mid+el),'Buy Size'] for el in x]
x1 = np.arange(0,band+1 )
z = [df.loc[(mid + el), 'Sell Size'] for el in x1]
seq3 = np.concatenate((y,z),axis=0)
return seq3
def bookplot(self,band):
x = list(range(-band,band+1,1))
seq3 = self.bookshape(band)
plt.plot(x,seq3, color='red')
plt.xlabel('Price')
plt.ylabel('Quantity')
return plt.show()
def pick(self,l):
a= np.random.choice(l,1,replace=True,p=[1/l]*l)
return a[0]
def limitbuyorder(self,price=None):
if price == None :
price = (self.best_offer() - self.pick(self.l))
else:
price = price
df = self.book
if self.logging == True:
count = 0
eventlog = self.event_log
eventlog.loc[count,'Price'] = price
eventlog.loc[count,'Type'] = 'LB'
df.loc[df.Price==price,'Buy Size'] += 1
def limitsellorder(self,price=None):
if price == None :
price = (self.best_bid() + self.pick(self.l))
else:
price = price
df = self.book
if self.logging == True:
count = 0
eventlog = self.event_log
eventlog.loc[count,'Price'] = price
eventlog.loc[count,'Type'] = 'LS'
df.loc[df.Price==price,'Sell Size'] += 1
def cancelbuyorder(self,price=None):
df = self.book
if price == None:
q = self.pick(self.nb)
tmp = np.array(df['Buy Size'].to_list()[::-1]).cumsum()
posn = len(tmp[tmp>=q]) - 1
price = df.Price[posn]
df.loc[posn,'Buy Size'] -= 1
else:
price = price
df.loc[df.Price==price,'Buy Size'] -= 1
if self.logging == True:
count = 0
eventlog = self.event_log
eventlog.loc[count,'Price'] = price
eventlog.loc[count,'Type'] = 'CB'
def cancelsellorder(self,price=None):
#global ns
df = self.book
if price == None:
q = self.pick(self.ns)
tmp = np.array(df['Sell Size'].to_list()).cumsum()
posn = len(tmp[tmp<q])
price = df.Price[posn]
df.loc[posn,'Sell Size'] -= 1
else:
price = price
df.loc[df.Price==price,'Sell Size'] -= 1
if self.logging == True:
count = 0
eventlog = self.event_log
eventlog.loc[count,'Price'] = price
eventlog.loc[count,'Type'] = 'CS'
def marketbuyorder(self,price=None):
df = self.book
price = self.best_offer()
if self.logging == True:
count = 0
eventlog = self.event_log
eventlog.loc[count,'Price'] = price
eventlog.loc[count,'Type'] = 'MB'
df.loc[df.Price==price,'Sell Size'] -= 1
def marketsellorder(self,price=None):
df = self.book
price = self.best_bid()
if self.logging == True:
count = 0
eventlog = self.event_log
eventlog.loc[count,'Price'] = price
eventlog.loc[count,'Type'] = 'MS'
df.loc[df.Price==price,'Buy Size'] -= 1
def generateevent(self):
df = self.book
nb = sum(df.loc[df.Price >= (self.best_offer()-self.l), 'Buy Size']) #number of cancellable buy orders
ns = sum(df.loc[df.Price <= (self.best_bid()+self.l), 'Sell Size']) #number of cancellable sell order
eventRate = nb*self.delta +ns*self.delta + self.mu + 2*self.l*self.alpha
probEvent = (self.l*self.alpha + self.l*self.alpha + nb*self.delta + ns*self.delta + self.mu*0.5 + self.mu*0.5)/eventRate
a = np.random.choice(6,1,replace=True,p=[probEvent/6]*6)
idx = a[0]
z= [self.limitbuyorder(),self.limitsellorder(),self.cancelbuyorder(),self.cancelsellorder(),self.marketbuyorder(),self.marketsellorder()]
return z[idx]
alpha = 1
mu = 10
delta = 1/5
num_events = 100000
'''
a = Zibook(1000,30,alpha,mu,delta,num_events,logging=False)
a.limitbuyorder(price =a.best_bid())
a.limitbuyorder(price =a.best_bid())
a.bookplot(20)
#print(a.generateevent())
#print(a.cancelbuyorder(price=None))
'''
lalpha = [1,1,1,1]
lmu = [10,8,10,10]
ldelta = [1/5,1/5,1/6,1/8]
length = len(lalpha)
Avgbookshapes = np.array([])
num_events = 100000
for i in range(0,length,1):
alpha = lalpha[i]
mu = lmu[i]
delta=ldelta[i]
a = Zibook(1000,30,alpha,mu,delta,num_events,logging=False)
for i1 in range(0,100,1):
a.generateevent()
#print(i1)
avgbookshape = a.bookshape(20)/num_events
#print(avgbookshape.shape)
for i3 in range(2,num_events+1,1):
a.generateevent()
#print(i3)
avgbookshape2 = a.bookshape(20)/num_events
#print(avgbookshape2.shape)
avgbookshape += avgbookshape2
Avgbookshapes = np.append(Avgbookshapes,avgbookshape)
np.save('my_array',Avgbookshapes)
任何帮助将不胜感激(此算法的背景是它对微观市场结构的零智能模拟https://github.com/zecophy/MTH9879-Market-Microstructure-Models/blob/master/HW1/9879HW1_Chenyu_Zhao_graded.ipynb)
解决方案
刚刚意识到我没有在 generateevent 函数中正确写出概率。但是代码仍然衰减到0个订单下面是python中的修改代码有人知道为什么订单会衰减而不是像R代码中那样增长吗?:
def generateevent(self):
df = self.book
nb = sum(df.loc[df.Price >= (self.best_offer()-self.l), 'Buy Size'])
ns = sum(df.loc[df.Price <= (self.best_bid()+self.l), 'Sell Size']) #number of cancellable sell order
eventRate = nb*self.delta +ns*self.delta + self.mu + 2*self.l*self.alpha
probEvent = np.array([self.l*self.alpha, self.l*self.alpha , nb*self.delta, ns*self.delta,self.mu*0.5,self.mu*0.5])/eventRate
#print(probEvent)
a = np.random.choice(6,1,replace=True,p=probEvent)
idx = a[0]
z= [self.limitbuyorder(),self.limitsellorder(),self.cancelbuyorder(),self.cancelsellorder(),self.marketbuyorder(),self.marketsellorder()]
return z[idx]
推荐阅读
- common-lisp - 评估 Common Lisp 宏的参数
- excel - 尝试为 VBA 创建匹配和复制功能
- python - 查找和使用形状位置 Python pptx
- python - 如何将数据框除以同一数据框的另一列
- javascript - 替换对象数组中的字符
- github-api - 特定回购的 Stargazer 计数
- php - 弹出在 php 退出意图中发布的电子邮件表单
- javascript - React Hooks - 本地天气 API
- javascript - Javascript Html 树
- ruby-on-rails - Rails 测试跳过自定义验证或自定义验证不起作用?