公平博弈必输策略及Python改进

公平博弈必输策略及Python改进,第1张

概述公平博弈必输策略及Python改进前言一、算术原因二、逻辑原因三、Python改进总结前言考虑一个场景:一名投机人每次拿出当前本金的10%进行抛硬币测试(公平博弈,输赢均50%),一共测试60次,最终输赢各30次,那么他的本金将是多少?计算:x=1.1^30*0.9^30*100%=0.99^30*100%

公平博弈必输策略及Python改进前言一、算术原因二、逻辑原因三、Python改进总结

前言

考虑一个场景:一名投机人每次拿出当前本金的10%进行抛硬币测试(公平博弈,输赢均50%),一共测试60次,最终输赢各30次,那么他的本金将是多少?

计算:x = 1.1^30 * 0.9^30 * 100% = 0.99^30 * 100% =73.97%

这就带来了一个问题:一个公平博弈,如果策略不妥,那么长期下来有可能是必输。

注:该问题,与“一支股票经历10%涨停30次,10%跌停30次,最终价格如何”,实质是一样的。

一、算术原因

从算术角度来说,胜率必须略高于52.5%,长期才可以不输。以1000次为例:
1. 1 525 ∗ 0. 9 475 = 1. 1 50 ∗ 0.9 9 475 = 0.9916 ≈ 1 1.1^{525} * 0.9^{475} = 1.1^{50} * 0.99^{475} = 0.9916 \approx 1 1.1525∗0.9475=1.150∗0.99475=0.9916≈1
但是,根据大数理论,硬币实验次数越多,概率越趋近50%。当实验次数足够多时,胜率略高于52.5%的可能性变得微乎其微,因此就必输了。

二、逻辑原因

从逻辑角度来说,落后之时减少投入,而领先之时增大投入,是不妥的。以起始10000为例:
1)先输后赢,则10000输1000,变成9000,再赢900,变为9900
2)先赢后输,则10000赢1000,变成11000,再输1100,变为9900

只有反过来,落后时增大投入,而领先时减少投入,才是合理的。比如:
1)先输后赢,10000变9000,增加投入1100,赢后变10100
2)先赢后输,10000变11000,减少投入900,输后变10100

然而,这种策略也存在两个问题:一是有点类似倍投法,假如一开始连输几次,有输光的风险;二是领先之时,资金大了,而每次投入要变少,资金利用率降低了。

三、Python改进

事实上,“每次拿出当前本金10%”的方案,不如“固定金额”方案。套用在购买基金的场景,前者类似“固定份额”定投方案,后者是“固定金额”定投方案。

现在试一试改进方案:
1)以某天净值x0为基准
2)当净值突破至下一个基准:上涨为x0的2倍,下跌为x0的一半,切换基准
3)当上一次 *** 作之后,净值变化超过3%,则再次 *** 作:如下跌,则补仓(倍数见下),如上涨且持有,则减仓(倍数见下,不足则清完为止)
4)当净值在[1, 2)倍x0时,倍数为1倍;净值在[0.9, 1)倍x0时,倍数为2倍;…;净值在[0.5, 0.6)倍x0时,倍数为6倍。但是,如果当前持仓过多(大于该倍数的2倍),那么补仓倍数仅为1倍(减仓倍数不影响)

以下是该方案的Python源码,在Jupyter notebook里面分三段:

import requestsimport timeimport execJsfileTest = './data/accTest.csv'jjTest = '001630'def getUrl(fscode):    head = 'http://fund.eastmoney.com/Pingzhongdata/'    tail = '.Js?v='+ time.strftime("%Y%m%d%H%M%s",time.localtime())    return head+fscode+tail# 根据基金代码获取净值def getWorth(fscode):    content = requests.get(getUrl(fscode))    JsContent = execJs.compile(content.text)    name = JsContent.eval('fS_name')    code = JsContent.eval('fS_code')    #单位净值走势    netWorthTrend = JsContent.eval('Data_netWorthTrend')    #累计净值走势    ACWorthTrend = JsContent.eval('Data_ACWorthTrend')    netWorth = []    ACWorth = []    for dayWorth in netWorthTrend:        netWorth.append(dayWorth['y'])    for dayACWorth in ACWorthTrend:        ACWorth.append(dayACWorth[1])    return netWorth, ACWorthACWorthTestfile = open(fileTest, 'w')_, ACWorth = getWorth(jjTest)if len(ACWorth) > 0:    ACWorthTestfile.write(",".join(List(map(str, ACWorth))))    ACWorthTestfile.write("\n")    print('{} data downloaded'.format(jjTest))ACWorthTestfile.close()

第一段如上,在天天基金网爬基金。001630是天弘中证计算机主题ETF联接C,有两个特点:
1)在支付宝基金里面,买入0费率,持有7天卖出0费率
2)该基金2015年7月成立的,至今(2021年2月)5年多,成立以来累计涨跌幅约-10%(目前基金净值约0.9元),10多亿大小

import csvwith open(fileTest) as f:    row = csv.reader(f, delimiter=',')    for r in row:        #去掉记录为None的数据(当天数据缺失)        r = [float(x) for x in r if x != 'None']show_days = 1500 #仅用最近的show_days天数(1年约250交易日)if len(r) > show_days:    r = r[len(r)-show_days:]x0 = r[0] #当前基准x1 = x0 #已存净值x2 = x0 #上次 *** 作时净值a = 10000 #标准份额(1倍)y = 0 #当前持有倍数z = 0 #累计盈利(含浮盈浮亏)s = [0] #历史盈利率(不乘以标准份额,即z/a)t = [0] #历史倍数乘以0.1(即0.1y,乘以0.1是为了图形显示)for i in range(1,len(r)):    x3 = r[i]    #刷新浮盈浮亏    if y > 0:        z += a * y * (x3 - x1)    s.append(z/a)    #净值变化超过基准    if (x3 >= x0 * 2) or (x3 < x0 / 2):        #下跌,则买入1倍份额        if x3 < x2:            y += 1        #反之,如有则卖出1倍份额        elif y > 0:            y -= 1        #刷新        x0 = x3        x1 = x3        x2 = x3    #上一次 *** 作至今,净值变化超过3%    elif (x3 > x2 * 1.03) or (x3 < x2 * 0.97):        if x3 >= x0:            # [x0, 2x0)采用1倍            i = 1        else:            i = 2 + int(10 * (1 - x3 / x0))            #但如果当前持仓过多,则补仓仅采用1倍(减仓不受影响)            if (y > 2 * i) and (x3 < x2):                i = 1        #下跌,则买入i倍份额        if x3 < x2:            y += i        #反之,如持有则卖出i倍份额        else:            if y > i:                y -= i            else:                y = 0        #刷新        x1 = x3        x2 = x3    else:        x1 = x3    t.append(y * 0.1)print('累计盈亏为:{:.0f}'.format(z))

第二段就是之前说的“改进方案”的实现。注意:当持仓过多而补仓时,以及基准切换时,倍数都用1。
该基金成立至今5年半,近1400交易日(show_days=1500亦即全部显示)。

import numpy as npfrom matplotlib import pyplot as pltplt.rcParams['Font.sans-serif']='SimHei'plt.rcParams['axes.unicode_minus']=Falser_plot = np.array(r).reshape(-1, 1)s_plot = np.array(s).reshape(-1, 1)t_plot = np.array(t).reshape(-1, 1)# 图表显示fig=plt.figure(figsize=(15,6))plt.plot(r_plot, color='blue', label='基金净值')plt.plot(s_plot, color='red', label='盈亏情况')plt.plot(t_plot, color='yellow', label='持仓情况')plt.legend(loc='upper left')plt.show()

第三段代码就是画图了,贴图如下:

蓝色线就是001630的净值。看似很平,1元上下,其实最低值是0.485元,最高值是1.0826元。
黄色线是持仓倍数情况,红色线是盈亏情况。在最惨的时候(净值0.5元左右),倍数近20倍(黄纵坐标要乘以10),浮盈浮亏约-1.5(假定1万份为1倍,即浮亏1.5万);目前净值0.9元左右,浮盈浮亏为5(同理,浮盈5万)。

如果把show_days改设为250,亦即查看近1年的情况,则图片如下所示:


近一年最高持仓倍数为6,当前浮盈7千多(1万份1倍)。

注意:因为001630持有7天卖出0费率,且基金是按照先进先出原则卖出的,因此本文忽略了持仓不足7天而卖出的惩罚费率情况。如实战,则自行注意之。

总结

本文针对特色基金001630(基本面尚可,人气较旺,表现较差),提出了一种“温和”补仓的策略------落后时略增加倍数。当然,其它基金也是可以的,试过10多个基金(都是7天0费率的)。

关于基金补仓减仓,凭感觉,两种策略都是可行的:一种即是本文的“上次 *** 作后变化超3%”,另一种是“连涨连跌几天”。或者两者结合:5天当中4-5天涨,且涨幅超3%;5天当中4-5天跌,且跌幅超3%。采用5天是比较好的(5个交易日必满足持有7天)。这些策略我也在测试中,大同小异,不另贴了。

有一种直觉,现在“韭菜”不喜欢买股票,而喜欢买基金了。尤其是女白领。于是,有些光棍跑到基金板块留言“交友启事”,蛮有趣。

总结

以上是内存溢出为你收集整理的公平博弈必输策略及Python改进全部内容,希望文章能够帮你解决公平博弈必输策略及Python改进所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/1189381.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-03
下一篇 2022-06-03

发表评论

登录后才能评论

评论列表(0条)

保存