A commodities trader oversees a secure vault facility with a maximum capacity of 500 kilograms, dedicated to storing refined platinum. At the beginning of Quarter 1, the trader holds 150 kilograms of platinum. Each quarter, the trader assesses the current inventory, sells any amount of platinum up to the available stock at the prevailing selling price, then purchase platinum at the current purchase price for the season, while ensuring that the total inventory does not exceed the vault's capacity (requires selling first before buying). The selling and purchase prices for platinum for each quarter are as follows:

| Quarter | Selling Price ($/kg) | Purchase Price ($/kg) |
|---------|-----------------------|-----------------------|
| 1       | 30,000               | 32,000               |
| 2       | 35,000               | 36,000               |
| 3       | 40,000               | 38,000               |
| 4       | 36,000               | 33,000               |
| 5       | 38,000               | 39,000               |
| 6       | 42,000               | 40,000               |

The trader's objective is to devise an optimal strategy for buying and selling platinum over the six quarters to maximize total profit. What is the maximum achievable profit?

Problem type: LP (Small: 18 variables, 12 constraints, 34 nonzeros)

Mathematical model:
Set:
1. Quarter
The set of quarters, \( Q = \{1, 2, ..., QuarterNum\} \)

Parameter:
1. QuarterNum
6
2. VaultCapacity
500
3. InitialInventory
150
4. SellingPrice
[30000, 35000, 40000, 36000, 38000, 42000]
5. PurchasePrice
[32000, 36000, 38000, 33000, 39000, 40000]

Decision variable:
1. SellingAmount
Continuous variable, \( SellingAmount_q \forall q \in Q \), where \( SellingAmount_q \) is the amount of platinum sold in quarter \( q \).
2. PurchaseAmount
Continuous variable, \( PurchaseAmount_q \forall q \in Q \), where \( PurchaseAmount_q \) is the amount of platinum purchased in quarter \( q \).
3. Inventory
Continuous variable, \( Inventory_q \forall q \in Q \), where \( Inventory_q \) is the amount of platinum in the vault at the end of quarter \( q \).

Objective:
1. Maximize the total profit from selling platinum. 
max: \sum_{q \in Q} (SellingPrice[q] * SellingAmount[q] - PurchasePrice[q] * PurchaseAmount[q])

Constraint:
1. Initial inventory constraint.
Inventory[1] = InitialInventory + PurchaseAmount[1] - SellingAmount[1]
2. Inventory balance constraint.
Inventory[q] = Inventory[q-1] + PurchaseAmount[q] - SellingAmount[q] \forall q \in Q, q > 1
3. Inventory capacity constraint.
Inventory[q] \leq VaultCapacity \forall q \in Q
4. Selling amount constraint.
SellingAmount[q] \leq Inventory[q-1] \forall q \in Q, q > 1
5. Initial selling amount constraint.
SellingAmount[1] \leq InitialInventory
6. Non-negativity constraint.
PurchaseAmount[q] \geq 0 \forall q \in Q
SellingAmount[q] \geq 0 \forall q \in Q
7. Inventory non-negativity constraint.
Inventory[q] \geq 0 \forall q \in Q

Type:
Continuous, Linear, Linear
LP

Gurobi implementation:
import gurobipy as gp
from gurobipy import GRB


def solve_platinum_trading(
    vault_capacity=500,
    initial_inventory=150,
    selling_price=[30000, 35000, 40000, 36000, 38000, 42000],
    purchase_price=[32000, 36000, 38000, 33000, 39000, 40000]):
    """
    Solves the platinum trading optimization problem.
    """
    # --- 1. Model Creation ---
    model = gp.Model("PlatinumTrading")

    # --- 2. Parameters & Sets ---
    quarter_num = len(selling_price)
    quarters = range(1, quarter_num + 1)

    # --- 3. Decision Variables ---
    selling_amount = model.addVars(quarters, lb=0, name="SellingAmount")
    purchase_amount = model.addVars(quarters, lb=0, name="PurchaseAmount")
    inventory = model.addVars(quarters,
                              lb=0,
                              ub=vault_capacity,
                              name="Inventory")

    # --- 4. Objective Function ---
    # Maximize total profit
    objective = gp.quicksum(selling_price[q - 1] * selling_amount[q] -
                            purchase_price[q - 1] * purchase_amount[q]
                            for q in quarters)
    model.setObjective(objective, GRB.MAXIMIZE)

    # --- 5. Constraints ---
    # Constraint 1: Initial inventory constraint
    model.addConstr(inventory[1] == initial_inventory + purchase_amount[1] -
                    selling_amount[1], "InitialInventory")

    # Constraint 2: Inventory balance constraint
    model.addConstrs(
        (inventory[q] == inventory[q - 1] + purchase_amount[q] -
         selling_amount[q] for q in range(2, quarter_num + 1)),
        "InventoryBalance")

    # Constraint 3: Selling amount must be less than or equal to inventory
    model.addConstr(selling_amount[1] <= initial_inventory,
                    "InitialInventoryLimit")
    model.addConstrs((selling_amount[q] <= inventory[q - 1]
                      for q in range(2, quarter_num + 1)), "InventoryLimit")

    # --- 6. Solve the Model ---
    model.optimize()

    # --- 7. Return Results ---
    if model.status == GRB.OPTIMAL:
        return {"status": "optimal", "obj": model.ObjVal}
    else:
        return {"status": f"{model.status}"}


# Run the solver function
if __name__ == "__main__":
    result = solve_platinum_trading()
    print(result)


Solution status: OPTIMAL
Optimal objective value: 13300000