feat: Add ATR EMA target scanner for stock analysis
This commit is contained in:
parent
389975605c
commit
86686125f3
126
src/screener/t_atr_ema_v2.py
Normal file
126
src/screener/t_atr_ema_v2.py
Normal file
@ -0,0 +1,126 @@
|
||||
import os
|
||||
import pandas as pd
|
||||
from datetime import datetime, timedelta
|
||||
from db.db_connection import create_client
|
||||
from indicators.three_atr_ema import ThreeATREMAIndicator
|
||||
from trading.position_calculator import PositionCalculator
|
||||
from screener.t_sunnyband import get_stock_data
|
||||
|
||||
def run_atr_ema_target_scanner(min_price: float, max_price: float, min_volume: int, portfolio_size: float = None):
|
||||
print(f"\n🔍 Scanning for stocks ${min_price:.2f}-${max_price:.2f} with min volume {min_volume:,}")
|
||||
|
||||
# Set time range
|
||||
end_date = datetime.now()
|
||||
start_date = end_date - timedelta(days=1) # Last trading day
|
||||
start_ts = int(start_date.timestamp() * 1000000000)
|
||||
end_ts = int(end_date.timestamp() * 1000000000)
|
||||
|
||||
client = create_client()
|
||||
|
||||
try:
|
||||
# Fetch stock prices within the defined range
|
||||
query = f"""
|
||||
WITH latest_data AS (
|
||||
SELECT
|
||||
ticker,
|
||||
argMax(close, window_start) AS last_close,
|
||||
sum(volume) AS total_volume,
|
||||
max(window_start) AS last_update
|
||||
FROM stock_db.stock_prices
|
||||
WHERE window_start BETWEEN {start_ts} AND {end_ts}
|
||||
GROUP BY ticker
|
||||
HAVING last_close BETWEEN {min_price} AND {max_price}
|
||||
AND total_volume >= {min_volume}
|
||||
)
|
||||
SELECT
|
||||
ticker,
|
||||
last_close,
|
||||
total_volume,
|
||||
last_update
|
||||
FROM latest_data
|
||||
ORDER BY ticker
|
||||
"""
|
||||
|
||||
result = client.query(query)
|
||||
stocks = [(row[0], row[1], row[2], row[3]) for row in result.result_rows]
|
||||
|
||||
if not stocks:
|
||||
print("❌ No stocks found matching criteria.")
|
||||
return
|
||||
|
||||
print(f"\n✅ Found {len(stocks)} stocks matching criteria")
|
||||
|
||||
indicator = ThreeATREMAIndicator()
|
||||
calculator = PositionCalculator(portfolio_size, risk_percentage=1.0, stop_loss_percentage=7.0) if portfolio_size else None
|
||||
bullish_signals = []
|
||||
|
||||
for ticker, current_price, current_volume, last_update in stocks:
|
||||
try:
|
||||
df = get_stock_data(ticker, start_date, end_date, "1D")
|
||||
if df.empty or len(df) < 50:
|
||||
continue
|
||||
|
||||
results = indicator.calculate(df)
|
||||
last_row = results.iloc[-1]
|
||||
prev_row = results.iloc[-2]
|
||||
|
||||
# Check if entry condition is met
|
||||
bullish_entry = (
|
||||
last_row['close'] < last_row['ema'] and
|
||||
prev_row['close'] <= prev_row['lower_band'] and
|
||||
last_row['close'] > prev_row['close']
|
||||
)
|
||||
|
||||
if bullish_entry:
|
||||
entry_price = last_row['close']
|
||||
target_1 = entry_price * 1.10 # 10% profit
|
||||
target_2 = entry_price * 1.20 # 20% profit
|
||||
|
||||
# Trailing stop logic
|
||||
trail_stop = None
|
||||
trail_active = False
|
||||
|
||||
if last_row['close'] >= last_row['upper_band']:
|
||||
trail_active = True
|
||||
highest_price = max(results['high'].iloc[-5:]) # Last 5 days
|
||||
trail_stop = highest_price * 0.98 # 2% below high
|
||||
|
||||
# Position sizing
|
||||
position = calculator.calculate_position_size(entry_price, target_2) if calculator else None
|
||||
position_size = position['position_value'] if position else None
|
||||
|
||||
# Save signal
|
||||
signal_data = {
|
||||
'ticker': ticker,
|
||||
'entry_price': entry_price,
|
||||
'target_1': target_1,
|
||||
'target_2': target_2,
|
||||
'volume': current_volume,
|
||||
'last_update': datetime.fromtimestamp(last_update / 1000000000),
|
||||
'trail_stop': trail_stop,
|
||||
'position_size': position_size
|
||||
}
|
||||
bullish_signals.append(signal_data)
|
||||
|
||||
# Print result
|
||||
print(f"\n🟢 {ticker} @ ${entry_price:.2f}")
|
||||
print(f" 🎯 Target 1: ${target_1:.2f} | Target 2: ${target_2:.2f}")
|
||||
if trail_active:
|
||||
print(f" 🚨 Trailing Stop: ${trail_stop:.2f}")
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Error processing {ticker}: {e}")
|
||||
continue
|
||||
|
||||
# Save results
|
||||
if bullish_signals:
|
||||
output_dir = 'reports'
|
||||
os.makedirs(output_dir, exist_ok=True)
|
||||
output_file = f'{output_dir}/atr_ema_targets_{datetime.now().strftime("%Y%m%d_%H%M")}.csv'
|
||||
pd.DataFrame(bullish_signals).to_csv(output_file, index=False)
|
||||
print(f"\n📁 Saved bullish signals to {output_file}")
|
||||
else:
|
||||
print("❌ No bullish signals found.")
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Error during scan: {e}")
|
||||
Loading…
Reference in New Issue
Block a user