关于德州扑克 solver

最近一直在看gtowizard来学习德州扑克,作为数学系毕业的人,突然本能开始好奇solver背后的数学原理。对solver的理解,一直停留在通过算法得到不同场景下的“Nash Equilibrium strategy”,作为大三听过game theory 课程的人来说,我明白纳什均衡策略指的是在某个特定场景下,没有人能通过单独改变自己的策略来获得更高的收益的一组策略。然而这个均衡策略是怎么计算出来的,我对此仍然一无所知。

于是在网上尝试搜索了一下,看到了一位大佬在知乎上分享的他自己写solver的经历:

https://zhuanlan.zhihu.com/p/352336898

这篇文章里提到最常用的,也是作者自己的solver运用的一个算法:cfr ( counterfactual regret minimization)以及其变种。这个做法类似于假设对方策略是固定的,我方要怎么调整得到更优的解。然后互相博弈,最后达到一个稳定的纳什均衡状态。由于策略树过于庞大,因此还有一些概念类似于压缩(action abstraction)的方法,来优化整体的运算速度。(也有点类似于现在学习扑克的将flop,turn的牌分类的方法,来减少自己所需要记忆的策略数量)。

关于cfr算法的paper,可以看以下这篇文章:

https://www.ma.imperial.ac.uk/~dturaev/neller-lanctot.pdf (Surprisingly from Imperial College lol)

这只是一个大概的了解,希望之后可以在了解背后的数学之后对我自己理解德扑有所帮助。另外,我其实挺欣赏作者在这篇知乎文章最后的观点:

“我对之后线上德州扑克的环境是悲观的,本就所剩无几的线上德州社区环境必定终将消失,到时候,线上所有的“鱼”都会流失,只剩下孤独的bot互相竞技。不过换个视角,这又何尝不是一件好事呢?本来就在德州中寻找乐趣的人在线下欢乐的面基,而妄想在德州扑克中赚钱的人在线上用bot杀个你死我活,各取所需,挺好挺好。”

虽然有了计算机之后,很多有限策略完全信息博弈游戏都已经被攻克了(各种棋类,包括围棋),但是这世界上最有意思的,不仍然是人和人之间的博弈么?这又让我想起了年初看的IEM SC2 和国际象棋世界冠军赛,只要不认输,即使胜率只有0.37%,在1/4决赛就BO5以0:2 落后,即使路上各种艰难险阻,也依然无法抵挡李培楠和丁立人站上顶峰。冷漠的机器,在看到胜机之后就不会再给任何机会,但是人不一样,人类确实会犯错,人类会有情绪波动,这种波动恰恰是人类的比赛所独有的魅力。王天一,在网上一个月输的中象比赛比他一年输的都多(绝大部分都是软件),但这并不妨碍他是中国象棋历史上最强。除此以外,他自己也承认,他师从的是软件。我们应该正视solver对自己扑克技术的提升,而不是仅仅让solver成为我们拿来在网上战胜别人的工具。

如果要和象棋AI做类比,我觉得对于preflop的计划,就像是象棋里的开局,开局基本能达成一种共识,基本上不需要做太多调整。对于flop 到turn,这就是类似于棋类的中盘,也是着重考验计算能力的地方了。对于棋类,是策略深度的计算,也就是常说的“能看到几步”。然而对于德扑,这个考验的就是对于范围,以及下注尺度,下注频率的理解与计算了。

我想对于德州扑克,我的未来的计划一定是去参加线下的锦标赛,去用我自己的实力,在线下去和人面对面得竞争。有的时候,只有人和人的博弈才能体现出一些机器所无法显现的光辉与魅力吧。

在这里对自己,也对所有想在扑克上有所提升的人说一句:

加油!学习solver,让自己成为更好的自己吧。

Advanced in Financial machine learning : Part 2- Chapter 2: financial data structure

2.2 Essential types of financial data

4 types of data:

Fundamental dataMarket dataAnalytics dataAlternative data
AssetsPriceAnalyst recommendCCTV image
LiabilitiesVolumeCredit ratingsGoogle searches
SalesDividendEarning expectationTwitter Chats
EarningsOpen InterestNews sentimentMeta data
MacroQuotes

2.2.1 Fundamental data

Definition

Fundamental data encompasses information that can be found in regulatory filings and business analytics.

Characteristics

  1. The available time of the data is not at the end of period.
    • The first quarter financial report of AAPL is not publised on 01-Apr of the year, so if we set the available time of the fundamental data at the end of the first quarter, we might be involved in using future data and cause issue in future test and real trading
  2. Backfilled and reinstate of fundamental data
    • Some of the fundamental data might be missing or wrong at its initial release, so in the future, the missing data might be filled and wrong data might be corrected. If we still assign the available time of these data the same as rest of the data, we might be involved in using future data.
  3. Low frequent hence little value remained unexploited
    • Being so accessible to the marketplace, it is rather unlikely that there is much value left to be exploited. Still, it may be useful in combination with other data types.

Market Data

Definition

Market data includes all trading activity that takes place in an exchange (like CME) or trading venue (like MarketAxess).

Characteristics

  1. Data provider has given you a raw feed, which could be difficult to process
    • Data provider has given you a raw feed, with all sorts of unstructured information, like FIX messages that allow you to fully reconstruct the trading book, or the full collection of BWIC (bids wanted in competition) responses
  2. Market Data could be very abundant and storage could be a problem.

Analytic Data

Definition

You could think of analytics as derivative data, based on an original source, which could be fundamental, market, alternative, or even a collection of other analytics.

Characteristics

  1. The negative aspects are that analytics may be costly, the methodology used in their production may be biased or opaque, and you will not be the sole consumer.

Alternative Data

Definition

  1. Alternative data was differentiated by:
    • Produced by individual ( social media, news etc.)
    • Business process ( transaction, corporate data, government agency etc.)
    • sensors( satellites, geolocation, weather etc.)

Characteristics

  1. alternative data is that it is primary information, that is, information that has not made it to the other sources.
  2. Two problematic aspects of alternative data
    • Cost
    • Privacy

随笔

我觉得,这个世界上最痛苦的事情,莫过于看着自己喜欢的人和别人在一起了。

我知道自己太难喜欢上一个人了,所以对于喜欢的人,我真的很难放弃。虽然我知道她已经有了对象,我还是没有办法自已。人类就是这样一种奇怪的动物, 对于得不到的东西,总有一种天然的不愿意放弃的想法。

有些人甚至愿意为此做出非理智的行为。

我不会去强调自己不属于这样的人群,因为我有的时候也会被内心的情绪牵着鼻子走,唯一值得庆幸的是我已经开始渐渐学会如何去掌握应对这种情绪的办法了。痛苦会有,难受会有,但是如果这一切是我变强所必须经历的,那我愿意去承受它。

现在的我面对这样的情况野无能为力。我愿意,我能做的,也只有去把自己变得更好吧。

曾经的我并没想清楚自己到底要什么,经历了这件事情,我反而意识到,自己一直害怕失败,不管是在学习,工作上,都在下意识地逃避着什么,如果我连失败都不愿去接受的话,那提高从何谈起不是么。

希望我能有看到自己改变的成果的那一天吧。

随笔

Huge Depression.

上面两个词是我过去几个月最真实的写照。看到太多厉害的人,能赚很多钱的人,能做出很厉害的科研成果的人,会很多乐器的人,很有领导力的人,很有运动天赋的人。

回国头来看我自己,我觉得我自己没有什么拿得出手的本事。

曾经有一段时间自己特别消极,觉得自己什么都不会做,什么都做不好。但是当我真正沉静下来,我觉得带着这样一种消极的心态做事,是不可能让自己有任何的进步的。曾经的我是害怕面对失败的,因此本能地逃避自己做不到地事情,自己不可能做成的事情。

我一直都在害怕,害怕别人的拒绝,害怕别人的批评,害怕被人的离开,害怕别人的不肯定,害怕自己的失败。

但是我到底在害怕一些什么呢?这些东西到底有什么值得害怕的呢?为什么我会这么在意别人的眼光,我到底为什么会活得这么得憋屈?

就在这一刻,我突然意识到,人不能给自己贴上这样的标签。我不能在还没开始做一件事情就对自己说我不行,就害怕失败,放弃那份冲劲。这可能是我最缺少,也是我现在最需要得到的东西了吧。以后不管做什么事情,永远是你能行,即使失败了一次,两次,我也绝对不可能就这样倒下。

What does not kill me , only makes me stronger. 所有杀不死的我的,都会让我变得更加强大。

杂谈·序

最近突然萌生出想要建立这个专栏的念头,是由于有的时候对一些事情,很想发表一些自己的观点和看法,但是并没有什么合适的场所和机会。既然专栏的标题叫做杂谈,那也就说明了我并不会对自己在这个专栏里所想探讨的题材做一个约束。我自己是一个特别”杂”的人,对很多事情都有点兴趣,对很多事情都有一些自己的想法。因此我觉得我应该把这些看法和想法记录下,等到之后再回过头来看看,说不定也会是一件有趣的事情。

在这个专栏里,对于任何的 人 事 物 的评价和看法都是本人的主观意见, 欢迎理性的讨论与交流,谢绝任何非理智的行为。

 

 

Question 673. Number of Longest Increasing Subsequence

Link

https://leetcode.com/problems/number-of-longest-increasing-subsequence/

My code:

class Solution:
    def findNumberOfLIS(self, nums: List[int]) -> int:
        if len(nums) ==0: return 0
        if len(nums) ==1: return 1
        #The list contains the maximum length end up with ith element in the nums
        ResultList = [[1,1]]
        #The dictionary provides the number of list given in the list
        for i in range(1,len(nums)):
            IndexList = []
            Length =1
            Num = 0
            for j in range(i):
                if nums[i]>nums[j]:
                    Length = max(Length,ResultList[j][0]+1)
                    IndexList.append(j)
            if Length != 1:
                for k in IndexList:
                    if ResultList[k][0] == Length -1:
                        Num += ResultList[k][1]
            if Num == 0:
                Num = 1
            ResultList.append([Length,Num])
        LengthList = [ResultList[i][0] for i in range(len(ResultList))]
        MaxLength = max(LengthList)
        Sum  = 0
        for s in range(len(ResultList)):
            if ResultList[s][0] == MaxLength:
                Sum += ResultList[s][1]
        return Sum

Explanation: There are two main problems in this question:1. How to determine the maximum length 2. How to count all the subsequence with maximum length. Here is the way I solve it. I construct a list L such that L[i] is a list that contains two elements. First element is the maximum length that ends up with element nums[i] and second element is the number of such subsequences. The recursion relation is as follows: for i+1 th element, we first check if it is larger than the chosen previous element. If so, then we know that the length of new List would be the maximum length of subsequence that ends up with chosen previous element plus one. Iterate through the beginning we may get the maximum length that ends up with i+1 th element. Second is to determine the number of the elements that ends up with i+1 th element and equals to the maximum length. So I do the iteration again to find total number. Notice that I initialise the length as 1 and Num as 0 because there is a situation that the i+1 th element might be smaller than all previous elements. In this situation , the maximum length would be one as itself. and the number would be 1 as just itself. Hence we iterate throught the nums list. Then we first find out the maximum length. Then we sum all the numbers that gives the maximum length. Then we return the result.

 

Question 368. Largest Divisible Subset

Link:

https://leetcode.com/problems/largest-divisible-subset/

My Code:

class Solution:
    def largestDivisibleSubset(self, nums: List[int]) -> List[int]:
        SortedNums = sorted(nums)
        if len(nums) == 0:
            return []
        if len(SortedNums ) ==1:
            return SortedNums
        else:
            #Here we design a list dp, dp[j] is the maximum length list end up with nums[j]
            StoreList = [[SortedNums[0]]]
            for i in range(1,len(SortedNums)):
                NewList =[SortedNums[i]]
                length = 1
                for j in range(i):
                    if SortedNums[i]%SortedNums[j] == 0:
                        Temp =  copy.deepcopy(StoreList[j])
                        Temp.append(SortedNums[i])
                        NewList2 = Temp
                        if len(NewList2) > length:
                            NewList = NewList2
                            length  = len(NewList)
                StoreList.append(NewList)
            Length2 = len(StoreList[0])
            ResultList = StoreList[0]
            for k in range(1,len(StoreList)):
                if len(StoreList[k])> Length2:
                    ResultList = StoreList[k]
                    Length2 = len(ResultList)
            return ResultList

Explanation: First, we need to solve the issue how to check the divisibility. The idea is that for any integers a, b , c if a|b, b|c  then a|c. Hence we just need to sort the num list. Then we design a dp list. df[j] is the maximum list end up with j the element in the number list. Then for j+1, we just need to check for any i <j+1, if nums[j+1] is divisible by nums[i] or not. If it is divisible , then we append the number into the maximum list end up with ith element. Then we pick the maximum length of all and take that as the jth element in the list.

Question 357 Count Numbers with Unique Digits

Link:

https://leetcode.com/problems/count-numbers-with-unique-digits/

My Code:

class Solution:
    def countNumbersWithUniqueDigits(self, n: int) -> int:
        import math as m
        ResultList = [1,10]
        for j in range(2,n+1):
            if j<=10:
                Result = ResultList[j-1]+int(9*m.factorial(9)/(m.factorial(10-j)))
                ResultList.append(Result)
            else:
                return ResultList[10]
        return ResultList[n]

Explanation: The idea is clear. First, there are only 10 different digits, so for any n that is larger than 10, we shall consider it exactly as the situation with n = 10. Next, for each n <=10, we construct a dp, dp[n] is the total number of numbers with unique digits with maximum n digits. Then for n+1, we just need to calculate the number of numbers with unique digits  at length equals to n+1, then sum it with dp[n] to get the total number of numbers with unique digits  at length at most n+1. Then return it.

 

Python Package Archive

Introduction

This article is to record all the packages and underlying function I use or will use in the quantitative trading.

Packages

1. Numpy

The whole information of this package can be found at https://numpy.org/ . This is the fundamental packages for scientific computing.

2. Statsmodel

The whole information of this package can be found at https://www.statsmodels.org/stable/index.html. This is a Python module that provides classes and functions for the estimation of many different statistical models, as well as for conducting statistical tests, and statistical data exploration.

3. Pandas

 

4. Tensorflow / Keras