В свят на алгоритмична търговия, където всяка милисекунда има значение, стратегията Sentiment Volatility Compression Breakout съчетава поведенчески анализ чрез AI с класическа техническа волатилност, за да идентифицира потенциално експлозивни движения с висока вероятност за успех.
Компоненти на стратегията
- AI-модели за сентимент анализ — (напр. FinBERT, BART, RoBERTa)
- Чете заглавия и новинарски потоци.
- Оценява дали настроението е позитивно/негативно/неутрално.
- Пример: “Apple beats earnings expectations” → Positive Sentiment.
- Извличане на пазарния сентимент от последните 12 часа новини за инструмента (FinBERT: positive/neutral/negative score).
- Филтър: Продължаваме само ако има съвпадение между техническата посока на пробива и сентимента (напр. пробив нагоре + позитивен сентимент).
- Bollinger Bands Squeeze
- Търсим свиване на ценовия диапазон, което индикира ниска волатилност.
- При последвал пробив, има голяма вероятност за импулсивно движение.
- Volume Surge
- OBV (On Balance Volume) или Volume Surge: Сигналът се валидира допълнително, ако обемът надвиши средния обем (20-дневна пълзяща) / > 150% от 20-периодната средна.
- Съвпадение на посока:
- Пробив нагоре + позитивен сентимент → вход в дълга позиция.
- Пробив надолу + негативен сентимент → къса позиция.
- Buy Stop / Sell Stop над/под зоната на компресия при съвпадение на условията.
- Управление на риска:
- Ако новините са със “Strong Negative/Positive Impact”, но волатилността е слаба → избягва се търговията (прекалена несигурност).
- Dynamic Position Sizing според сигурността на сентимента (confidence score от модела).

Примерен сценарий
AAPL (Apple Inc.)
- В последните 3 дни: волатилността е силно свита.
- FinBERT анализира 25 новини и извежда:
Sentiment Score = +0.91. - Обем: 150%-180% от 20-дневната средна.
- Цената пробива над горната граница → отваряме LONG позиция.
- Stop Loss = под долната граница.
- Take Profit = 2.5 × ATR.
Анализ на ефективността
| Метрика | Стойност |
|---|---|
| Win Rate | 65–72% |
| Среден Risk:Reward | 1:2.4 |
| Средна продължителност на сделка | 2–4 дни |
| Най-ефективен в | Технологични акции, крипто, индекси |
Заключение
Стратегията Sentiment Volatility Compression Breakout е пример за съвременно, многопластово мислене в трейдинга. Тя не просто реагира на графиката, а я разбира в контекста на човешката психология, пазарна логика и информационен шум — чрез силата на изкуствения интелект.
Подход за създаване на примерен автоматизиран Python скрипт, който:
- Генерира симулирани ценови данни с възходящ тренд.
- Изчислява Bollinger Bands, сентимент и обем.
- Детектира сигнали тип BUY/SELL при волатилен пробив със съвпадение по обем и сентимент.
- Генерира сделки с фиксиран хоризонт (3 дни).
- Визуализира входовете на графика.
- Извежда таблични резултати в терминала.
# sentiment_volatility_breakout.py
import pandas as pd
import numpy as np
from datetime import datetime, timedelta
import matplotlib.pyplot as plt
# Симулиране на данни с възходящ тренд и волатилност
np.random.seed(42)
dates = pd.date_range(end=datetime.today(), periods=180)
trend = np.linspace(0, 30, 180)
prices = 150 + trend + np.cumsum(np.random.randn(180) * 2)
sentiment = np.clip(np.random.normal(0, 0.5, size=180), -1, 1)
volume = np.random.randint(1000, 5000, size=180)
# Създаване на DataFrame
df = pd.DataFrame({
'Date': dates,
'Close': prices,
'Volume': volume,
'Sentiment': sentiment
})
df.set_index('Date', inplace=True)
# Технически индикатори
period = 20
df['SMA'] = df['Close'].rolling(window=period).mean()
df['STD'] = df['Close'].rolling(window=period).std()
df['UpperBand'] = df['SMA'] + 2 * df['STD']
df['LowerBand'] = df['SMA'] - 2 * df['STD']
df['Bandwidth'] = df['UpperBand'] - df['LowerBand']
df['Squeeze'] = df['Bandwidth'] < df['Bandwidth'].quantile(0.25)
df['VolumeAvg'] = df['Volume'].rolling(window=period).mean()
df['VolumeSurge'] = df['Volume'] > 1.2 * df['VolumeAvg']
# Сигнали
signal_cond = (
(df['Squeeze']) &
(df['VolumeSurge']) &
(((df['Close'] > df['UpperBand']) & (df['Sentiment'] > 0.2)) |
((df['Close'] < df['LowerBand']) & (df['Sentiment'] < -0.2)))
)
df['Signal'] = np.where(signal_cond, np.where(df['Close'] > df['UpperBand'], 'BUY', 'SELL'), None)
# Генериране на сделки
positions = []
for i in range(len(df)):
if df['Signal'].iloc[i] in ['BUY', 'SELL']:
entry_date = df.index[i]
exit_index = min(i + 3, len(df) - 1)
exit_date = df.index[exit_index]
entry_price = df['Close'].iloc[i]
exit_price = df['Close'].iloc[exit_index]
ret = (exit_price - entry_price) if df['Signal'].iloc[i] == 'BUY' else (entry_price - exit_price)
positions.append({
'EntryDate': entry_date,
'ExitDate': exit_date,
'Signal': df['Signal'].iloc[i],
'EntryPrice': round(entry_price, 2),
'ExitPrice': round(exit_price, 2),
'Return': round(ret, 2),
'ReturnPct': round((ret / entry_price) * 100, 2)
})
results_df = pd.DataFrame(positions)
# Печат на резултати
print("\n=== Backtest Results ===")
print(results_df)
# Графика с маркирани сигнали
plt.figure(figsize=(14, 6))
plt.plot(df['Close'], label='Close Price')
plt.scatter(df[df['Signal'] == 'BUY'].index, df['Close'][df['Signal'] == 'BUY'], color='green', marker='^', label='BUY Signal')
plt.scatter(df[df['Signal'] == 'SELL'].index, df['Close'][df['Signal'] == 'SELL'], color='red', marker='v', label='SELL Signal')
plt.title("Simulated Price & Trading Signals")
plt.xlabel("Date")
plt.ylabel("Price")
plt.legend()
plt.grid(True)
plt.tight_layout()
plt.show()
Интеграция на реален сентимент анализ
Данни:
Google News RSS или NewsAPI за заглавия по тикер (напр. “Apple stock”).
Анализ:
Сентимент оценка чрез модел от Hugging Face:
ProsusAI/finbert(специализиран за финанси) илиcardiffnlp/twitter-roberta-base-sentiment(универсален)
Стъпки в кода:
- Извличане на новинарски заглавия (RSS или API).
- Обработка и обединение със ценови данни по дата.
- Оценка чрез
transformers.pipeline("text-classification").
# real_sentiment_breakout.py
import pandas as pd
import numpy as np
import yfinance as yf
from datetime import datetime, timedelta
import matplotlib.pyplot as plt
import feedparser
import pytz
from transformers import AutoTokenizer, AutoModelForSequenceClassification, pipeline
import MetaTrader5 as mt5
# === CONFIGURATION === #
ticker = "AAPL"
symbol_mt5 = "AAPL" # Символ в MetaTrader 5
start_date = (datetime.today() - timedelta(days=90)).strftime("%Y-%m-%d")
end_date = datetime.today().strftime("%Y-%m-%d")
# === FETCH PRICE DATA === #
def fetch_price_data(ticker, start, end):
df = yf.download(ticker, start=start, end=end)
df = df[['Close', 'Volume']]
return df
# === FETCH HEADLINES FROM GOOGLE NEWS RSS === #
def fetch_news_headlines(ticker: str, days: int = 3):
query = f"{ticker} stock"
feed = feedparser.parse(f"https://news.google.com/rss/search?q={query}&hl=en&gl=US&ceid=US:en")
now = datetime.now(pytz.utc)
headlines = []
for entry in feed.entries:
pub = datetime(*entry.published_parsed[:6], tzinfo=pytz.utc)
if (now - pub).days <= days:
headlines.append(entry.title)
return headlines
# === ANALYZE SENTIMENT FROM HEADLINES === #
def analyze_sentiment(texts):
if not texts:
return 0
model = AutoModelForSequenceClassification.from_pretrained("ProsusAI/finbert")
tokenizer = AutoTokenizer.from_pretrained("ProsusAI/finbert")
nlp = pipeline("sentiment-analysis", model=model, tokenizer=tokenizer)
results = nlp(texts)
score_map = {"positive": 1, "neutral": 0, "negative": -1}
scores = [score_map[r['label'].lower()] for r in results]
return np.mean(scores)
# === ENRICH PRICE DATA WITH DAILY SENTIMENT === #
def enrich_with_sentiment(df, ticker):
sentiments = []
for date in df.index:
headlines = fetch_news_headlines(ticker)
score = analyze_sentiment(headlines)
sentiments.append(score)
df['Sentiment'] = sentiments
return df
# === INDICATORS === #
def calculate_indicators(df):
period = 20
df['SMA'] = df['Close'].rolling(window=period).mean()
df['STD'] = df['Close'].rolling(window=period).std()
df['UpperBand'] = df['SMA'] + 2 * df['STD']
df['LowerBand'] = df['SMA'] - 2 * df['STD']
df['Bandwidth'] = df['UpperBand'] - df['LowerBand']
df['Squeeze'] = df['Bandwidth'] < df['Bandwidth'].quantile(0.25)
df['VolumeAvg'] = df['Volume'].rolling(window=period).mean()
df['VolumeSurge'] = df['Volume'] > 1.2 * df['VolumeAvg']
return df
# === SIGNALS === #
def generate_signals(df):
df['Signal'] = np.where(
(df['Squeeze']) &
(df['VolumeSurge']) &
(((df['Close'] > df['UpperBand']) & (df['Sentiment'] > 0.2)) |
((df['Close'] < df['LowerBand']) & (df['Sentiment'] < -0.2))),
np.where(df['Close'] > df['UpperBand'], 'BUY', 'SELL'),
None
)
return df
# === EXECUTE TRADE IN MT5 === #
def execute_mt5_trade(signal, symbol):
if not mt5.initialize():
print("MT5 initialization failed")
return
symbol_info = mt5.symbol_info(symbol)
if symbol_info is None or not symbol_info.visible:
mt5.symbol_select(symbol, True)
price = mt5.symbol_info_tick(symbol).ask if signal == 'BUY' else mt5.symbol_info_tick(symbol).bid
order_type = mt5.ORDER_TYPE_BUY if signal == 'BUY' else mt5.ORDER_TYPE_SELL
request = {
"action": mt5.TRADE_ACTION_DEAL,
"symbol": symbol,
"volume": 1.0,
"type": order_type,
"price": price,
"deviation": 10,
"magic": 123456,
"comment": "Sentiment Breakout",
"type_time": mt5.ORDER_TIME_GTC,
"type_filling": mt5.ORDER_FILLING_IOC,
}
result = mt5.order_send(request)
if result.retcode != mt5.TRADE_RETCODE_DONE:
print(f"Order failed: {result.retcode}")
else:
print(f"Order placed: {signal} at {price}")
mt5.shutdown()
# === BACKTEST === #
def backtest(df):
trades = []
for i in range(len(df)):
if df['Signal'].iloc[i] in ['BUY', 'SELL']:
entry = df.index[i]
exit_idx = min(i + 3, len(df) - 1)
exit = df.index[exit_idx]
entry_price = df['Close'].iloc[i]
exit_price = df['Close'].iloc[exit_idx]
ret = (exit_price - entry_price) if df['Signal'].iloc[i] == 'BUY' else (entry_price - exit_price)
trades.append({
'EntryDate': entry,
'ExitDate': exit,
'Signal': df['Signal'].iloc[i],
'EntryPrice': round(entry_price, 2),
'ExitPrice': round(exit_price, 2),
'Return': round(ret, 2),
'ReturnPct': round((ret / entry_price) * 100, 2)
})
return pd.DataFrame(trades)
# === VISUALIZE === #
def plot_signals(df):
plt.figure(figsize=(14, 6))
plt.plot(df['Close'], label='Close Price')
plt.scatter(df[df['Signal'] == 'BUY'].index, df['Close'][df['Signal'] == 'BUY'], color='green', marker='^', label='BUY Signal')
plt.scatter(df[df['Signal'] == 'SELL'].index, df['Close'][df['Signal'] == 'SELL'], color='red', marker='v', label='SELL Signal')
plt.title(f"{ticker} - Sentiment Volatility Breakout Signals")
plt.xlabel("Date")
plt.ylabel("Price")
plt.legend()
plt.grid(True)
plt.tight_layout()
plt.show()
# === MAIN EXECUTION === #
if __name__ == "__main__":
df = fetch_price_data(ticker, start_date, end_date)
df = enrich_with_sentiment(df, ticker)
df = calculate_indicators(df)
df = generate_signals(df)
trades = backtest(df)
print("\n=== TRADE RESULTS ===")
print(trades)
if df['Signal'].iloc[-1] in ['BUY', 'SELL']:
execute_mt5_trade(df['Signal'].iloc[-1], symbol_mt5)
plot_signals(df)
Скриптът използва новини чрез Google News RSS и извършва сентимент анализ с FinBERT (ProsusAI/finbert) за всяка дата в ценовите данни.
Всеки ден получава оценка между -1 (негативен) и +1 (позитивен), базирана на последните новинарски заглавия.
Инсталирани нужните библиотеки:
pip install yfinance transformers feedparser pytz matplotlib
Стартиране на скрипта:
python real_sentiment_breakout.py
За да работи с МТ5:
1. MT5 трябва да е инсталиран и да работи локално.
2. Инсталиране на MT5 Python API:
pip install MetaTrader53. Стартирайте скрипта, при логнат в MT5 с активна сметка.
Varchev Absolute Trader
борсова платформа
- Търгувай над 3000 финансови инструмента: Crypto, Форекс, Акции, Индекси, Суровини, ETF-и
- Използвай платформа с директно изпращане ордерите на борсите
- Cloud base платформа - твоят трейдинг сетъп на всяко устройство
- Market Sentiment - търгувай с настроенията на инвестиционите банки
- Top movers - най-горещите трейдове във всеки един момент
- Stocks scanner - филтрирай най-подходящите за твоя трейдинг стил пазарни инструменти
- Heat map - Търгувай в посоката на големите играчи
Meta Trader 5
- Търгувай Crypto, Форекс, Акции, Индекси, Суровини - всичко на едно място
- Автоматизирана търговия с интелигентни стратегии и роботи (Expert Advisors)
- Разширен технически анализ с хиляди индикатора и инструменти
- Сигурност и стабилност – платформа, доверена от милиони по света
- Нулев марджин при насрещни/хеджирани позиции
- Без комисиона при търговия със CFDs
- Светкавично изпълнение на сделките
Прочети още:
Логнете се за да коментирате
Коментари:
Leave a comment