Excel + Python自制带UI的金融小工具
Fintech概念正受到不少互联网金融公司的热捧,主要是指代那些可用于撕裂传统金融服务方式的高新技术。越来越多的企业开辟了新的部门去研究各种各样能让自己产品增值的科技类产品。尤其是在很多互联网金融公司,业务分析师BA(Business Analyst),又称产品经理受到大家的追捧,虽然身处西二旗等ITer聚集地,但是他们做的工作与金融街上的白领们并无不同,他们是无所不懂的金融达人,顶着各个海外名校金融数学系的Master光环,手持CFA,CPA,FRM,AFP/CFP,CIIA,ACCA等等。既然是在IT公司做需求分析的工作,除了需要出具需求说明书,然后将需求翻译成程序员能够理解的说明文档,不可避免的也需要做一些测试的工作。现在各种工具琳琅满目,各种智能的自动化测试平台也在全面普及,越来越多的人工工作被取代,于是测试工程师经常会接到任务说:写个工具给BA用,让他们可以参与测试。说起来容易做起来难,对于大部分金融达人来说,代码对于他们无异于普通人看哥德巴赫猜想的手稿,如何让他们能够参与进来,能够更多地参与测试成为了测试工程师更多关注的问题。
前段时间正好接到了一个需求,由于业务需要计算期权费,BA需要计算出最优的数据组合,但是输入有3个参数,每个参数有40个数据,且数据是保留到小数点后15位,这样算下来的排列组合多到一个BA不可能在2周内找到最优解,更不要提在需求文档里明确写上排列组合的期望结果。如果BA写不出来,对于不懂金融的开发和测试,就更是一头雾水,无从下手,怎么能让BA自己算出来需要的数据呢?试了下Excel+Python的解决方案,基本满足了BA的需求,唯一需要BA支持的就是输入的excel需要按照规定的格式制作,以便程序读取。比如第一列是执行价,第二列是买入期权,第三列是卖出期权:
我们对应在代码里需要读取写入Excel里面的数据,依然使用最熟悉的xlrd和xlwt包。之所以把路径之类的都参数化,主要是为了生成UI之后,BA使用起来更方便。
# 获取文件
input_file_path = input.get()
print("Input File Path: " + input_file_path)
output_file_path = input_file_path.replace("option price caculator.xlsx", "new file.xls")
print("Output File Path: " + output_file_path)在Java中我们一般会使用BigDecimal来进行金融数据的处理,但是在Python中,虽然也有BigDecimal包,但是处理起来会出现各种各样不明原因的报错,所以我们选择了float类型。
# 打开文件
workbook = xlrd.open_workbook(input_file_path)
# 获取sheet内容
sheet1 = workbook.sheet_by_index(0)
# 获取整列的值
orgstrike = sheet1.col_values(0)
orgcall = sheet1.col_values(1)
orgput = sheet1.col_values(2)
# 更改格式
strike =
call =
put = 计算完成后,然后生成新的excel来保存处理过的数据,在不同的Sheet中保存不同的计算结果以便查看。如果需要多次运行且结果可以被覆盖,则加上cell_overwirte_ok = True就可以了。
# 创建文件
file = xlwt.Workbook()
sheet1 = file.add_sheet("符合条件", cell_overwrite_ok=True)
sheet1.write(0, 0, 'call')
sheet1.write(0, 1, 'strike')
sheet1.write(0, 2, 'put')
sheet1.write(0, 3, 'strike')
sheet1.write(0, 4, 'callNeg')
sheet1.write(0, 5, 'strike')
sheet2 = file.add_sheet("不符合条件", cell_overwrite_ok=True)
sheet2.write(0, 0, 'call')
sheet2.write(0, 1, 'strike')
sheet2.write(0, 2, 'put')
sheet2.write(0, 3, 'strike')
sheet2.write(0, 4, 'callNeg')
sheet2.write(0, 5, 'strike')
接下来就是完成BA需求里面逻辑计算,排列组合的部分了,由于需求不同,我就不展示这部分代码了,有个提示在这个地方,如果需要在console里面打印出浮点,请使用如下代码:
print("call: %04d(%18.14f); put: %04d(%18.14f); callneg: %04d(%18.14f)"
% (i + 1, strike, j + 1, strike, k + 1, strike))
这样我们逻辑部分就完成了,下面就要进行UI部分的设计和制作了,由于技(懒)术(惰)原因,我们还是使用Python来做,一气呵成。
import tkinter.font as tkFont 对于一般的BA的需求来说,一个输入文件,一个输出文件足够了,所以我们也本着极简的原则做一个UI,成品如下,贴入输入文件的路径,点击GO后,会显示输出文件的链接,点击链接可以打开生成的文件:
在Pycharm的Console里,我们可以看到打印出来的结果:
在文件夹里,我们会找到新生成的文件new file.xls:
在这个文件里,有我们需要的所有符合条件和不符合条件的排列组合:
想做出这样的效果,网上有很多tkFont的教程可以参考。有几点需要提示,tkFont在Python2和3中的使用方法不一样,请先确认自己使用的版本。部分代码如下:
# Title
root.title("Option Price Calculator")
# Input File
labelFilePath = Label(root, text=" Input File: ")
labelFilePath.grid(row=0, sticky=E)
# Textbox
input = StringVar()
entryFilePath = Entry(root, width=80, textvariable=input)
entryFilePath.grid(row=0, column=1)
# Go
buttonGo = Button(root, text="GO", width=5)
buttonGo.bind("<Button-1>", lambda event: OptionPriceCalc.read_excel(event, input))
buttonGo.bind("<Button-1>", lambda event: show_output_file_path(event, input))
buttonGo.grid(row=0, column=3, padx=5, sticky=E+W)
# Output File
labelOutput = Label(root, text="Output File: ")
labelOutput.grid(row=1, sticky=E)完成需求后,BA提出了新的看法,对于点击连接后是否直接打开,我们是可以控制的:
def show_output_file_path(event, input):
output = input.get().replace("option price caculator.xlsx", "new file.xls")
ft = tkFont.Font(family="Calibri", size=11, underline=1)
labelOutputFile = Label(root, text=output, fg="blue", font=ft)
labelOutputFile.grid(row=1, column=1, sticky=W+N+S)
# Click Go -> Click File Name
labelOutputFile.bind("<ButtonPress-1>", lambda event: open_file(output))
# Click Go -> Open File Automatically
# labelOutputFile.bind("<ButtonPress-1>", os.startfile(output))有了这个模板,BA提出新需求后,我们只需要更改UI文件中调用的方法名,就可以了!
厉害了
页:
[1]