Stock trading -- how to represent and convert the state

Posted by sunnyk on Thu, 23 Dec 2021 19:15:40 +0100

The simplest version: only one trading opportunity, buy and sell one day: buy and sell stocks 1

//For each day i, as long as you know which day is the smallest in front, you can know the maximum profit ending with i
    int maxProfit(vector<int>& prices) {
        int buyDay = 0;
        int maxProfit = 0;
        for(int i=1;i<prices.size();i++){
            if(prices[i]<prices[buyDay])
                buyDay = i;
            int tempProfit = prices[i] - prices[buyDay];
            maxProfit = max(maxProfit,tempProfit);
        }
        return maxProfit;
    }

Unlimited Trading: buying and selling stocks 2

You can complete as many transactions as possible (buying and selling a stock multiple times)

 //Continuous holding can also be regarded as buying and selling. Anyway, the number of times is unlimited
    int maxProfit(vector<int>& prices) {
        int profitSum = 0;
        for(int i=1;i<prices.size();i++){
            if(prices[i] < prices[i-1] ){
                continue;
            }
            profitSum += prices[i] - prices[i-1]; //Buy and sell as long as there is profit
        }
        return profitSum;
    }

The second writing method, general solution, state transition.

//dp[i][1] holds shares on day I, and dp[i][0] does not hold shares on day I
    int maxProfit(vector<int>& prices) {
        int dp[100005][2];
        dp[0][0] = 0; 
        dp[0][1] = -prices[0];  //If you buy initially, the profit until day 0 is negative
        for(int i=1;i<prices.size();i++){
        
            dp[i][0] = max(dp[i-1][1] + prices[i], dp[i-1][0]); //Not held = not held the previous day or held the previous day + sold today
            dp[i][1] = max(dp[i-1][1], dp[i-1][0] - prices[i]); //Holding = holding the previous day or not holding the previous day + buying today

        }
        return dp[prices.size()-1][0];  
    }

Including freezing period

My original idea was that according to the above 2, I only need to judge the time of buying d p [ i ] = d p [ i − 1 ] [ 0 ] − p r i c e dp[i]=dp[i-1][0] - price dp[i]=dp[i − 1] [0] − price whether i-1 was sold the day before, the judgment logic is to see whether dp[i-2][0] is the same as [i-1]. However, the reason for this is that the freezing period will have an impact on the later. Therefore, it is impossible to simply confirm the optimal value of dp[i][0] in day I. you seem to be the best at present, but your freezing pair may delay the later big list. Therefore, the freezing period should also be part of the state.

If [0] is not held

  • Sell today - it will affect the next day
  • Sell yesterday, or sell before, postpone before - it has no impact on the future

In order to distinguish, let's sell today or [0], and record those not sold today as [2]

Sort out the state transition:
dp[i][1] = dp[i-1][1] o r or or dp[i-1][2] - price
dp[i][0] = dp[i-1][1] + price
dp[i][2] = dp[i-1][0] o r or or dp[i-1][2]

int maxProfit(vector<int>& prices) {
        int n = prices.size();
        vector<vector<int> > dp(n,vector<int>(3,0)); //0 means to sell today (no buying later), 1 means to hold now, and 2 means to sell yesterday and before
        dp[0][1] = -prices[0];

        for(int i=1; i<n; i++){
            dp[i][0] = dp[i-1][1] + prices[i];
            dp[i][1] = max(dp[i-1][1],dp[i-1][2]-prices[i]);
            dp[i][2] = max(dp[i-1][0],dp[i-1][2]);
        }
        return max(dp[n-1][0],dp[n-1][2]);
    }

We found that this type of question is not difficult to think about the state transition. The important thing is to analyze several states.

General solution to the stock problem: give you the daily price of the stock, limit you to only buy and sell K times, and seek the maximum income.

In order to obtain the income of K transactions on the nth day, the usual idea of dynamic planning is: dp[n][k]
Therefore, we can think of using dp[i][j] to represent the profit of j transactions up to day I.

There are only three choices for us to think about every day: sell, buy and keep
Because sell and buy have a preorder relationship, we must have buy in front of them to sell. Therefore, our state must add one dimension to indicate whether we have bought in front.

  • dp[][][0] means no buy
  • dp[][][1] indicates that it has been bought

state transition
(buy indicates entering the next transaction j+1)

From this, we deduce our formula: the value of dp represents profit

d p [ i ] [ j ] [ 0 ] = m a x ( d p [ i − 1 ] [ j ] [ 0 ] , d p [ i − 1 ] [ j ] [ 1 ] + p r i c e s [ i ] ) dp[i][j][0] = max( dp[i-1][j][0], dp[i-1][j][1] + prices[i]) dp[i][j][0]=max(dp[i−1][j][0],dp[i−1][j][1]+prices[i])

d p [ i ] [ j ] [ 1 ] = m a x ( d p [ i − 1 ] [ j ] [ 1 ] , d p [ i − 1 ] [ j − 1 ] [ 0 ] − p r i c e s [ i ] ) dp[i][j][1] = max(dp[i-1][j][1], dp[i-1][j-1][0]-prices[i]) dp[i][j][1]=max(dp[i−1][j][1],dp[i−1][j−1][0]−prices[i])

Note the initial state, that is, when i-1 may not exist and j-1 may not exist in the transition.
i == 0: dp[0][][1] = -prices[i] / / indicates initial purchase
j == 0: dp[][0][1] = -inf / / indicates impossible

 int maxProfit(vector<int>& prices) {
        int dp[100005][3][2] = {0};
        int inf = 1000000000;
    
        for(int i=0;i<prices.size();i++){
            for(int k=0;k<=2;k++){                   
                //In the middle, I-1 and k-1 do not exist
                if( k==0 ){
                    dp[i][k][1] = -inf;
                    continue;
                }
                if(i==0){
                    dp[i][k][1] = -prices[i]; 
                    continue;
                }
                dp[i][k][0] = max(dp[i-1][k][0],dp[i-1][k][1]+prices[i]);
                dp[i][k][1] = max(dp[i-1][k][1],dp[i-1][k-1][0]-prices[i]);
            }
        }
        return dp[prices.size()-1][2][0];
    }