Монте-карло, Таттелеком и pythonanywhere


В этой заметке я расскажу, как на бесплатном хостинге для питона использовать метод Монте-Карло для предсказания повышения цены акций Таттелеком на 10% за следующие 30 дней.



Хостинг для питона

На самом деле подойдет любой платный, наверно на всех уже есть питон последних версий. У меня есть платных хостингов и вдс, но в данном случае я использую еще и бесплатный, так как а) не все яйца в одной корзине и б) а зачем платить если есть бесплатно? В общем вот - pythonanywhere.com – регистрируйтесь, заводите акк.

Новичкам там будет не очень понятно (я к своему стыду тоже не сразу разобрался). Но в целом можно потратить время, нелишнее. Вкратце – создаете новое web приложение, закидываете файлы, перезагружаете и смотрите что получилось.

У меня вот тут все сейчас up7.pythonanywhere.com/monte-karlo

Метод Монте-Карло

Метод Монте-Карло — это мощный статистический инструмент, который может помочь трейдеру фондовой биржи в анализе рисков, прогнозировании и принятии решений. Вот несколько способов его применения:

  1. Оценка рисков и управление капиталом. Метод Монте-Карло позволяет моделировать тысячи возможных сценариев движения цены актива на основе исторической волатильности. Это помогает трейдеру:
    • Рассчитать вероятность убытков (Value at Risk, VaR).
    • Определить оптимальный размер позиции (позиционирование).
    • Оценить, как разные стратегии могут вести себя в экстремальных условиях (стресс-тестирование).
  2. Тестирование торговых стратегий. Вместо проверки стратегии на ограниченной истории (бэктест), можно сгенерировать множество случайных траекторий цены и проверить, как часто стратегия дает прибыль. Это помогает:
    • Избежать переоптимизации (кривой подгонки под исторические данные).
    • Увидеть, устойчива ли стратегия к разным рыночным условиям.
  3. Прогнозирование цен (с осторожностью!). Хотя точный прогноз невозможен, метод Монте-Карло позволяет:
    • Смоделировать разные сценарии (например, рост, падение, боковое движение).
    • Оценить вероятность достижения ценой определенных уровней (например, тейк-профита или стоп-лосса).
  4. Оптимизация портфеля. Трейдер может использовать Монте-Карло для:
    • Анализа корреляции между активами.
    • Поиска оптимального распределения капитала (например, в рамках модели Марковица, но с учетом случайных колебаний).
Пример использования

Допустим, трейдер хочет оценить, какова вероятность того, что акция поднимется на 10% в течение месяца. Метод Монте-Карло может:
  1. Взять историческую волатильность акции.
  2. Сгенерировать 10 000 случайных путей цены.
  3. Посчитать, в каком проценте случаев цена падает на 10%.
Ограничения метода
  • Зависит от качества входных данных (например, если волатильность резко изменится, прогнозы будут неточными).
  • Не учитывает черные лебеди (редкие, но катастрофические события).
  • Требует вычислительных ресурсов.
Код

Файл app.py (точка входа и роутинг нашего flask сервера)

# -*- coding: utf-8 -*-
import os
import numpy as np
import pandas as pd
from flask import Flask, render_template, request
import io
import base64
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
import logging

app = Flask(__name__)

def read_custom_data(ticker):
    file_path = f"/home/up7/myflaskapp/static/data/{ticker.lower()}.txt"

    logging.debug(f"Читаем данные из файла: {file_path}")

    if not os.path.exists(file_path):
        raise Exception(f"Файл не найден: {file_path}")

    try:
        df = pd.read_csv(
            file_path,
            sep=';',
            names=['TICKER', 'PER', 'DATE', 'TIME', 'CLOSE', 'VOL'],
            skiprows=1,
            encoding='utf-8'
        )
    except Exception as e:
        raise Exception(f"Не удалось обработать файл: {e}")

    df['DATE'] = pd.to_datetime(df['DATE'], format='%Y%m%d')
    df.set_index('DATE', inplace=True)
    df.sort_index(inplace=True)

    return df['CLOSE']

def simulate_stock_price(ticker, days=21, simulations=100):
    try:
        data = read_custom_data(ticker)
    except Exception as e:
        return {'error': str(e)}

    if len(data) < 2:
        return {'error': "Недостаточно данных для анализа"}

    log_returns = np.log(data / data.shift(1)).dropna()
    mu = log_returns.mean()
    sigma = log_returns.std()
    initial_price = data[-1]

    if np.isnan(mu) or np.isnan(sigma) or sigma <= 0:
        return {'error': 'Некорректные параметры моделирования'}

    shocks = np.random.normal(mu - 0.5 * sigma**2, sigma, size=(days, simulations))
    price_paths = np.zeros((days + 1, simulations))
    price_paths[0] = initial_price
    price_paths[1:] = initial_price * np.cumprod(np.exp(shocks), axis=0)

    final_prices = price_paths[-1]
    gain_threshold = initial_price * 1.1  # +10% от текущей цены
    probability_gain = np.mean(final_prices > gain_threshold) * 100

    plot_url = generate_plot(price_paths)

    return {
        'ticker': ticker,
        'initial_price': round(initial_price, 5),
        'probability_gain': round(probability_gain, 2),
        'plot_url': plot_url
    }

def generate_plot(price_paths):
    plt.figure(figsize=(10, 6))
    plt.plot(price_paths[:, :100], linewidth=1, alpha=0.5)
    plt.title("Моделирование цены")
    plt.xlabel("Дни")
    plt.ylabel("Цена")
    plt.grid(True)

    img = io.BytesIO()
    plt.savefig(img, format='png')
    img.seek(0)
    plt.close()

    return base64.b64encode(img.getvalue()).decode('utf8')

@app.route('/')
def index():
    # Главная страница — список ссылок
    links = [
        {"title": "Монте-Карло", "url": "/monte-karlo"},
        {"title": "Страница 2", "url": "#"},
        {"title": "Страница 3", "url": "#"}
    ]
    return render_template('main.html', links=links)

@app.route('/monte-karlo', methods=['GET', 'POST'])
def monte_karlo():
    result = None
    if request.method == 'POST':
        ticker = request.form['ticker'].strip().lower()
        result = simulate_stock_price(ticker)
    return render_template('index.html', result=result)

if __name__ == '__main__':
    app.run(debug=True)
Шаблон

<!DOCTYPE html>
<html lang="ru">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Метод Монте-Карло для акций</title>
    <link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
</head>
<body>
<h1>Прогноз цены акций</h1>

<form method="POST">
    <input type="text" name="ticker" placeholder="Введите тикер" required>
    <input type="submit" value="Анализировать">
</form>

{% if result %}
<div style="margin-top: 20px;">
    {% if result.error %}
        <p style="color:red;">{{ result.error }}</p>
    {% else %}
        <p><strong>Тикер:</strong> {{ result.ticker }}</p>
        <p><strong>Начальная цена:</strong> {{ result.initial_price }}</p>
        <p><strong>Вероятность повышения на 10%:</strong> {{ result.probability_gain }}%</p>

        {% if result.plot_url %}
            <img src="data:image/png;base64,{{ result.plot_url }}" alt="График">
        {% endif %}
    {% endif %}
</div>
{% endif %}

</body>
</html>
Что получилось

Узнаем вероятность того, что Таттелеком увеличится на 10% за следующие 30 дней. Вводим тикер ttlk и получаем график с вероятностями. up7.pythonanywhere.com/monte-karlo. Результаты каждый раз будут получаться разные, учтите.
Автор этого материала - я - Пахолков Юрий. Я оказываю услуги по написанию программ на языках Java, C++, C# (а также консультирую по ним) и созданию сайтов. Работаю с сайтами на CMS OpenCart, WordPress, ModX и самописными. Кроме этого, работаю напрямую с JavaScript, PHP, CSS, HTML - то есть могу доработать ваш сайт или помочь с веб-программированием. Пишите сюда.

тегизаметки, python, акции



Управление движением картинки с клавиатуры на JavaScript
Урок 19. Наследование и конструкторы C#
Урок 21. Java автоупаковка, статический импорт, типы данных и кое-что еще