Максимизировать субпродукт значений столбца Python - PullRequest
1 голос
/ 01 мая 2020

Я хочу максимизировать sumproduct двух столбцов в кадре данных. Например, если я могу купить что-то, а затем продать это позже (т.е. я могу сохранить это), как бы я написал какой-нибудь код Python, чтобы решить это для меня?

Это очень простой пример. Если вы построите график цен, вы увидите, что они низкие летом, а высокие зимой. Если нет никаких ограничений, и я хочу купить 100 лотов, я бы купил все 100 в 9 июля, стоив мне 900 (так как это самый дешевый месяц). Тогда я буду хранить его до февраля (так как это самый дорогой месяц) и продавать его за 13,5, получая 1350, то есть прибыль 450.

Если по какой-то причине максимум я могу купить и продать за месяц 30 лотов, тогда я бы купил 30 в июне, июле и августе, затем 10 в сентябре. Я продал бы 10 в декабре, затем 30 в январе, феврале и марте. Я бы сделал все это для того, чтобы максимизировать общую сумму денег, которую я могу заработать [то есть сумму всей цены * продано минус сумма цены * (куплено)].

В общей строке показано, что я заработаю 450 или 362,5 в этих ситуациях. Я только что сделал это, просто глядя на это, поскольку это очень очевидно. Но как я могу заставить Python сделать это для меня? Я посмотрел на страницу оптимизации SciPy, но не зашел слишком далеко.

По сути, я хочу максимизировать общую строку, выделяя определенное количество покупок и продаж в каждом месяце - нацеливаясь на максимум, который я могу купить в самые дешевые месяцы с разливом в следующие самые дешевые месяцы и т. д. 1015 *, затем продажи по максимальным ценам, а затем распродажа в следующие самые дорогие месяцы и т. д. c.

Итак, если у меня будет 100 лотов покупай и цены меняются завтра, тогда как меняется моя стратегия. Например, если июнь достиг 8, я должен перенести максимальную покупку на июнь.

import datetime as dt
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd


start_date = dt.datetime(2019, 4, 1)
end_date = dt.datetime(2020, 3, 1)
dates = pd.date_range(start_date, end_date, freq='MS')

df = pd.DataFrame([10.5, 10, 9.5, 9, 9.5, 10, 10.5, 12, 12.5, 13, 13.5, 12.75],
                      columns=['Price'],
                      index=dates)

df['No Constraints'] = [0, 0, 0, -100, 0, 0, 0, 0, 0, 0, 100, 0]
df['Money In (Out) No Constraints'] = df['Price'] * df['No Constraints']

df['Max 30'] = [0, 0, -30, -30, -30, -10, 0, 0, 10, 30, 30, 30]
df['Money In (Out) Max 30']= df['Price'] * df['Max 30']

df.loc['Total'] = df.sum(axis=0)

1 Ответ

0 голосов
/ 01 мая 2020

Для вашей первой ситуации стратегия довольно проста: всякий раз, когда цена повышается, вы покупаете как можно больше, когда цена падает, вы продаете все, а в конце года вы продаете их все. Я не совсем понимаю ваши слова, у вас есть 100 долларов, а цена 9, как вы покупаете 100? Мой код выглядит так:

prices = [10.5, 10, 9.5, 9, 9.5, 10, 10.5, 12, 12.5, 13, 13.5, 12.75]

my_money = [100]*(len(prices)+1)
my_stock = [0]*(len(prices)+1)
for i in range(len(prices)):
    if i != len(prices) - 1 and prices[i + 1] > prices[i]:
        buy = my_money[i]//prices[i]
        my_money[i+1] =my_money[i]%prices[i]
        my_stock[i+1] = my_stock[i] + buy
    else:
        my_money[i+1] =my_money[i] + prices[i] * my_stock[i]
        my_stock[i+1] = 0

print(my_money)
print(my_stock)

Во втором случае, если я снова не понял ваше описание, ваша стратегия явно далека от идеальной. С одной стороны, цена постоянно снижается в течение первых нескольких месяцев, поэтому вы можете продолжать покупать 30 в течение первых месяцев и продолжать продавать их в течение последних нескольких месяцев. Реализация этого алгоритма может быть немного сложна для понимания. Мне нравится думать с точки зрения дня и запасов, так что теперь будет так. По сути, у вас есть двумерный массив my_money [day] [num_of_stock], это максимальное количество денег, которое вы можете иметь, если у вас есть num_of_stock количество акций на day число дней. my_money[day+1][j] - это максимум (my_money [день] [i] + цены [день] * (i - j)), где i - это все возможное количество акций, которые вы держите в предыдущий день, а j - количество акций, которые вы может провести сегодня, учитывая ваши ограничения. И, наконец, ваша максимальная награда - my_money [-1] [0], то есть наибольшее количество денег, которое вы можете иметь, не имея на руках запаса в последний день. Это немного сложно, но я думаю, что код лучше объясняет это. см. код:

prices = [10.5, 10, 9.5, 9, 9.5, 10, 10.5, 12, 12.5, 13, 13.5, 12.75]
MAXSELL = 30

my_money = [[] for _ in range(len(prices)+1)]
my_money[0].append(0)

for day in range(len(prices)):
    j = 0
    while(j < len(my_money[day]) + MAXSELL):
        max_stock = min(len(my_money[day]),j + MAXSELL + 1)
        min_stock = max(0 , j - MAXSELL)
        moneyj = max([(my_money[day][i] + prices[day] * (i - j)) 
                      for i in range(min_stock, max_stock)])
        my_money[day + 1].append(moneyj)
        j += 1
print(my_money[-1][0])

Выходное значение 472,5, что больше, чем ваш результат.

В качестве альтернативы, если у вас все еще есть денежный лимит (100), и вы не можете потратить на отрицательно, этот слегка измененный код делает следующее:

my_money = [[] for _ in range(len(prices)+1)]
my_money[0].append(100)

for day in range(len(prices)):
    j = 0
    while(True):
        max_stock = min(len(my_money[day]),j + MAXSELL + 1)
        min_stock = max(0 , j - MAXSELL)
        moneyj = max([(my_money[day][i] + prices[day] * (i - j)) 
                      for i in range(min_stock, max_stock)])
        if moneyj > 0: 
            my_money[day + 1].append(moneyj)
            j += 1
        else:
            break
print(my_money[-1][0])

, что, как и ожидалось, дает тот же результат, что и в случае 1, поскольку максимум 30 покупок / продаж невозможно, если у вас есть только 100 * 1015 $

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...