I metodi di William Gann (Parte III): L'astrologia funziona?
Introduzione
Gli operatori dei mercati finanziari sono alla costante ricerca di nuovi metodi di analisi e previsione del mercato. Anche i concetti più incredibili non vengono tralasciati. Uno degli approcci non standard e completamente unici è l'uso dell'astrologia nel trading, reso popolare dal famoso trader William Gann.
Abbiamo già parlato degli strumenti di Gann nei nostri articoli precedenti. Ecco la prima e la seconda parte. Ci concentreremo ora sull'esplorazione dell'impatto delle posizioni planetarie e stellari sui mercati mondiali.
Cerchiamo di combinare le tecnologie più moderne e le conoscenze più antiche. Utilizzeremo il linguaggio di programmazione Python e la piattaforma MetaTrader 5 per trovare il collegamento tra i fenomeni astronomici e i movimenti della coppia EURUSD. Tratteremo la parte teorica dell'astrologia in finanza e ci cimenteremo nella parte pratica dello sviluppo di un sistema di previsione.
Inoltre, ci occuperemo della raccolta e della sincronizzazione di dati astronomici e finanziari, della creazione di una matrice di correlazione e della visualizzazione dei risultati.
Basi teoriche dell'astrologia in finanza
Mi interesso di questo argomento da molto tempo e oggi voglio condividere le mie riflessioni sull'influenza dell'astrologia sui mercati finanziari. Si tratta di un settore davvero affascinante, anche se piuttosto controverso.
L'idea di base dell'astrologia finanziaria, a mio avviso, è che i movimenti dei corpi celesti siano in qualche modo correlati ai cicli di mercato. Questo concetto ha una lunga e ricca storia ed è stato reso popolare soprattutto da William Gann, un famoso trader del secolo scorso.
Ho riflettuto a lungo sui principi fondamentali di questa teoria. Per esempio, l'idea di ciclicità afferma che i movimenti di stelle e pianeti sono di natura ciclica, così come i movimenti del mercato. Per quanto riguarda gli aspetti planetari, alcuni ritengono che certe posizioni planetarie abbiano una forte influenza sui mercati. E i segni zodiacali? Si ritiene che anche il passaggio dei pianeti attraverso le diverse costellazioni zodiacali influisca in qualche modo sul mercato.
Anche i cicli lunari e l'attività solare sono degni di nota. Ho visto opinioni secondo cui le fasi lunari sono associate a fluttuazioni a breve termine del mercato, mentre le eruzioni solari sono associate a tendenze a lungo termine. Ipotesi interessanti, vero?
William Gann è stato un vero e proprio pioniere in questo campo. Sviluppò una serie di strumenti, come il famoso quadrato dei 9, basati su astronomia, geometria e sequenze di numeri. I suoi lavori suscitano ancora oggi un acceso dibattito.
Naturalmente, non si può ignorare che la comunità scientifica nel suo complesso è scettica nei confronti dell'astrologia. In molti Paesi è ufficialmente riconosciuta come pseudoscienza. E, in tutta franchezza, non esistono ancora prove certe dell'efficacia dei metodi astrologici in campo finanziario. Spesso, alcune correlazioni osservate si rivelano semplicemente il risultato di pregiudizi cognitivi.
Nonostante ciò, sono molti i trader che difendono strenuamente le idee dell'astrologia finanziaria.
Per questo motivo ho deciso di fare una ricerca personale. Vorrei cercare di dare una valutazione obiettiva dell'influenza dell'astrologia sui mercati finanziari utilizzando metodi statistici e big data. Chissà, forse scopriremo qualcosa di interessante. In ogni caso, sarà un viaggio affascinante nel mondo dove stelle e grafici azionari si incrociano.
Panoramica delle librerie Python applicate
Avrò bisogno di un intero arsenale di librerie Python.
Per iniziare, ho deciso di utilizzare il pacchetto Skyfield per ottenere dati astronomici. Ho passato molto tempo a scegliere lo strumento giusto e Skyfield mi ha colpito per la sua precisione. Con il suo aiuto, sarò in grado di raccogliere informazioni sulle posizioni dei corpi celesti e sulle fasi lunari con un'altissima precisione in cifre decimali - tutto ciò che è necessario per i miei set di dati.
Per quanto riguarda i dati di mercato, la mia scelta è caduta sulla libreria ufficiale MetaTrader 5 per Python. Permette di scaricare i dati storici sulle coppie di valute e, se necessario, di aprire operazioni.
Pandas diventerà il nostro fedele compagno di lavoro con i dati. Ho usato molto questa libreria in passato ed è semplicemente indispensabile per lavorare con le serie temporali. Lo userò per la pre-elaborazione e la sincronizzazione di tutti i dati raccolti.
Per l'analisi statistica ho scelto la libreria SciPy. La sua ampia funzionalità è impressionante, in particolare gli strumenti per l'analisi di correlazione e regressione. Spero che mi aiutino a trovare modelli interessanti.
Per visualizzare i risultati, ho deciso di utilizzare i miei vecchi amici - Matplotlib e Seaborn. Adoro queste librerie per la loro flessibilità nella creazione di grafici. Sono certo che aiuteranno a visualizzare tutti i risultati.
L'intero set è assemblato. È come assemblare un potente PC con componenti eccellenti. Ora abbiamo tutto ciò che serve per condurre uno studio completo sull'influenza dei fattori astrologici sui mercati finanziari. Non vedo l'ora di immergermi nei dati e iniziare a testare le mie ipotesi!
Raccolta dei dati astronomici
import pandas as pd import numpy as np from skyfield.api import load, wgs84, utc from skyfield.data import mpc from datetime import datetime, timedelta import requests # Loading planet ephemerides planets = load('de421.bsp') earth = planets['earth'] ts = load.timescale() def get_planet_positions(date): t = ts.from_datetime(date.replace(tzinfo=utc)) planet_positions = {} planet_ids = { 'mercury': 'MERCURY BARYCENTER', 'venus': 'VENUS BARYCENTER', 'mars': 'MARS BARYCENTER', 'jupiter': 'JUPITER BARYCENTER', 'saturn': 'SATURN BARYCENTER', 'uranus': 'URANUS BARYCENTER', 'neptune': 'NEPTUNE BARYCENTER' } for planet, planet_id in planet_ids.items(): planet_obj = planets[planet_id] astrometric = earth.at(t).observe(planet_obj) ra, dec, _ = astrometric.radec() planet_positions[planet] = {'ra': ra.hours, 'dec': dec.degrees} return planet_positions def get_moon_phase(date): t = ts.from_datetime(date.replace(tzinfo=utc)) eph = load('de421.bsp') moon, sun, earth = eph['moon'], eph['sun'], eph['earth'] e = earth.at(t) _, m, _ = e.observe(moon).apparent().ecliptic_latlon() _, s, _ = e.observe(sun).apparent().ecliptic_latlon() phase = (m.degrees - s.degrees) % 360 return phase def get_solar_activity(date): # Get solar activity data from NOAA API url = f"https://services.swpc.noaa.gov/json/solar-cycle/observed-solar-cycle-indices.json" response = requests.get(url) data = response.json() # Convert date to 'YYYY-MM' format target_date = date.strftime("%Y-%m") # Find the closest date in the data closest_data = min(data, key=lambda x: abs(datetime.strptime(x['time-tag'], "%Y-%m") - datetime.strptime(target_date, "%Y-%m"))) return { 'sunspot_number': closest_data.get('ssn', None), 'f10.7_flux': closest_data.get('f10.7', None) } def calculate_aspects(positions): aspects = {} planets = list(positions.keys()) for i in range(len(planets)): for j in range(i+1, len(planets)): planet1 = planets[i] planet2 = planets[j] ra1 = positions[planet1]['ra'] ra2 = positions[planet2]['ra'] angle = abs(ra1 - ra2) % 24 angle = min(angle, 24 - angle) * 15 # Convert to degrees if abs(angle - 0) <= 10 or abs(angle - 180) <= 10: aspects[f"{planet1}_{planet2}"] = "conjunction" if abs(angle - 0) <= 10 else "opposition" elif abs(angle - 90) <= 10: aspects[f"{planet1}_{planet2}"] = "square" elif abs(angle - 120) <= 10: aspects[f"{planet1}_{planet2}"] = "trine" return aspects start_date = datetime(2024, 4, 1, tzinfo=utc) end_date = datetime(2024, 5, 31, tzinfo=utc) current_date = start_date astronomical_data = [] while current_date <= end_date: planet_positions = get_planet_positions(current_date) moon_phase = get_moon_phase(current_date) try: solar_activity = get_solar_activity(current_date) except Exception as e: print(f"Error getting solar activity for {current_date}: {e}") solar_activity = {'sunspot_number': None, 'f10.7_flux': None} aspects = calculate_aspects(planet_positions) data = { 'date': current_date, 'moon_phase': moon_phase, 'sunspot_number': solar_activity.get('sunspot_number'), 'f10.7_flux': solar_activity.get('f10.7_flux'), **planet_positions, **aspects } astronomical_data.append(data) current_date += timedelta(days=1) print(f"Processed: {current_date}") # Convert data to DataFrame df = pd.DataFrame(astronomical_data) # Save data to CSV file df.to_csv('astronomical_data_2018_2024.csv', index=False) print("Data saved to astronomical_data_2018_2024.csv")
Questo codice Python raccoglie dati astronomici che utilizzeremo in futuro per le analisi di mercato.
Il codice utilizza il periodo compreso tra il 1° gennaio 2018 e il 31 maggio 2024 e raccoglie una serie di dati quali:
- Posizioni dei pianeti: Venere, Mercurio, Marte, Giove, Saturno, Urano e Nettuno.
- Fasi lunari
- Attività solare
- Aspetti dei pianeti (come i pianeti sono allineati tra loro)
Lo script comprende l'importazione della libreria, il ciclo principale e il salvataggio dei dati in formato Excel. Il codice utilizza la già citata libreria Skyfield per calcolare le posizioni dei pianeti, Pandas per i dati e le richieste per ottenere i dati sull'attività solare.
Tra le funzioni degne di nota vi sono get_planet_positions() per ottenere le posizioni dei pianeti (ascensione retta e declinazione), get_moon_phase() per trovare la fase lunare corrente, get_solar_activity() per l'invio diretto dei dati sull'attività solare dall'API NOAA e calculate_aspects() per calcolare gli aspetti - le posizioni dei pianeti in relazione tra loro.
Ogni giorno, come parte del ciclo, raccogliamo tutti i dati. Di conseguenza, salviamo tutto in un file Excel per l’uso futuro.
Ottenere dati finanziari tramite MetaTrader 5
Per ottenere i dati finanziari, utilizzeremo la libreria MetaTrader 5 per Python. La libreria ci permetterà di scaricare dati finanziari direttamente dal broker e di ricevere le serie temporali dei prezzi per qualsiasi strumento. Ecco il codice per il caricamento dei dati storici:
import MetaTrader5 as mt5
import pandas as pd
from datetime import datetime
# Connect to MetaTrader5
if not mt5.initialize():
print("initialize() failed")
mt5.shutdown()
# Set query parameters
symbol = "EURUSD"
timeframe = mt5.TIMEFRAME_D1
start_date = datetime(2018, 1, 1)
end_date = datetime(2024, 12, 31)
# Request historical data
rates = mt5.copy_rates_range(symbol, timeframe, start_date, end_date)
# Convert data to DataFrame
df = pd.DataFrame(rates)
df['time'] = pd.to_datetime(df['time'], unit='s')
# Save data to CSV file
df.to_csv(f'{symbol}_data.csv', index=False)
# Terminate the connection to MetaTrader5
mt5.shutdown()
Lo script si collega al terminale di trading, riceve i dati su EURUSD D1, quindi crea un dataframe e lo salva in un singolo file CSV.

Sincronizzazione di dati astronomici e finanziari
Abbiamo quindi dati sull'astronomia, ma anche dati su EURUSD. Ora dobbiamo sincronizzarli. Combiniamo i dati per data in modo che un unico set di dati contenga tutte le informazioni necessarie, sia finanziarie che astronomiche.
import pandas as pd
# Load data
astro_data = pd.read_csv('astronomical_data_2018_2024.csv')
financial_data = pd.read_csv('EURUSD_data.csv')
# Convert date columns to datetime
astro_data['date'] = pd.to_datetime(astro_data['date'])
financial_data['time'] = pd.to_datetime(financial_data['time'])
# Merge data
merged_data = pd.merge(financial_data, astro_data, left_on='time', right_on='date', how='inner')
# Save merged data
merged_data.to_csv('merged_astro_financial_data.csv', index=False)
Lo script carica tutti i dati salvati, formatta le colonne delle date in formato datetime e combina i set di dati per data. Il risultato è un file CSV che contiene tutti i dati necessari per le analisi future.
Analisi statistica delle correlazioni
Andiamo avanti. Abbiamo un insieme comune, un set di dati comuni, ed è ora di scoprire se nei dati ci sono relazioni tra astronomia e movimenti di mercato. Utilizzeremo le funzioni corr() della libreria pandas. Inoltre, combineremo entrambi i codici in uno solo.
Ecco lo script finale:
import pandas as pd
import numpy as np
from skyfield.api import load, wgs84, utc
from skyfield.data import mpc
from datetime import datetime, timedelta
import requests
import MetaTrader5 as mt5
import seaborn as sns
import matplotlib.pyplot as plt
# Part 1: Collecting astronomical data
# Loading planetary ephemerides
planets = load('de421.bsp')
earth = planets['earth']
ts = load.timescale()
def get_planet_positions(date):
t = ts.from_datetime(date.replace(tzinfo=utc))
planet_positions = {}
planet_ids = {
'mercury': 'MERCURY BARYCENTER',
'venus': 'VENUS BARYCENTER',
'mars': 'MARS BARYCENTER',
'jupiter': 'JUPITER BARYCENTER',
'saturn': 'SATURN BARYCENTER',
'uranus': 'URANUS BARYCENTER',
'neptune': 'NEPTUNE BARYCENTER'
}
for planet, planet_id in planet_ids.items():
planet_obj = planets[planet_id]
astrometric = earth.at(t).observe(planet_obj)
ra, dec, _ = astrometric.radec()
planet_positions[planet] = {'ra': ra.hours, 'dec': dec.degrees}
return planet_positions
def get_moon_phase(date):
t = ts.from_datetime(date.replace(tzinfo=utc))
eph = load('de421.bsp')
moon, sun, earth = eph['moon'], eph['sun'], eph['earth']
e = earth.at(t)
_, m, _ = e.observe(moon).apparent().ecliptic_latlon()
_, s, _ = e.observe(sun).apparent().ecliptic_latlon()
phase = (m.degrees - s.degrees) % 360
return phase
def get_solar_activity(date):
url = f"https://services.swpc.noaa.gov/json/solar-cycle/observed-solar-cycle-indices.json"
response = requests.get(url)
data = response.json()
target_date = date.strftime("%Y-%m")
closest_data = min(data, key=lambda x: abs(datetime.strptime(x['time-tag'], "%Y-%m") - datetime.strptime(target_date, "%Y-%m")))
return {
'sunspot_number': closest_data.get('ssn', None),
'f10.7_flux': closest_data.get('f10.7', None)
}
def calculate_aspects(positions):
aspects = {}
planets = list(positions.keys())
for i in range(len(planets)):
for j in range(i+1, len(planets)):
planet1 = planets[i]
planet2 = planets[j]
ra1 = positions[planet1]['ra']
ra2 = positions[planet2]['ra']
angle = abs(ra1 - ra2) % 24
angle = min(angle, 24 - angle) * 15 # Convert to degrees
if abs(angle - 0) <= 10 or abs(angle - 180) <= 10:
aspects[f"{planet1}_{planet2}"] = "conjunction" if abs(angle - 0) <= 10 else "opposition"
elif abs(angle - 90) <= 10:
aspects[f"{planet1}_{planet2}"] = "square"
elif abs(angle - 120) <= 10:
aspects[f"{planet1}_{planet2}"] = "trine"
return aspects
# Collecting astronomical data
start_date = datetime(2024, 3, 1, tzinfo=utc)
end_date = datetime(2024, 7, 30, tzinfo=utc)
current_date = start_date
astronomical_data = []
while current_date <= end_date:
planet_positions = get_planet_positions(current_date)
moon_phase = get_moon_phase(current_date)
try:
solar_activity = get_solar_activity(current_date)
except Exception as e:
print(f"Error getting solar activity for {current_date}: {e}")
solar_activity = {'sunspot_number': None, 'f10.7_flux': None}
aspects = calculate_aspects(planet_positions)
data = {
'date': current_date,
'moon_phase': moon_phase,
'sunspot_number': solar_activity.get('sunspot_number'),
'f10.7_flux': solar_activity.get('f10.7_flux'),
**planet_positions,
**aspects
}
astronomical_data.append(data)
current_date += timedelta(days=1)
print(f"Processed: {current_date}")
# Convert data to DataFrame and save
astro_df = pd.DataFrame(astronomical_data)
astro_df.to_csv('astronomical_data_2018_2024.csv', index=False)
print("Astronomical data saved to astronomical_data_2018_2024.csv")
# Part 2: Retrieving financial data via MetaTrader5
# Initialize connection to MetaTrader5
if not mt5.initialize():
print("initialize() failed")
mt5.shutdown()
# Set request parameters
symbol = "EURUSD"
timeframe = mt5.TIMEFRAME_D1
start_date = datetime(2024, 3, 1)
end_date = datetime(2024, 7, 30)
# Request historical data
rates = mt5.copy_rates_range(symbol, timeframe, start_date, end_date)
# Convert data to DataFrame
financial_df = pd.DataFrame(rates)
financial_df['time'] = pd.to_datetime(financial_df['time'], unit='s')
# Save financial data
financial_df.to_csv(f'{symbol}_data.csv', index=False)
print(f"Financial data saved to {symbol}_data.csv")
# Shutdown MetaTrader5 connection
mt5.shutdown()
# Part 3: Synchronizing astronomical and financial data
# Load data
astro_df = pd.read_csv('astronomical_data_2018_2024.csv')
financial_df = pd.read_csv('EURUSD_data.csv')
# Convert date columns to datetime
astro_df['date'] = pd.to_datetime(astro_df['date']).dt.tz_localize(None)
financial_df['time'] = pd.to_datetime(financial_df['time'])
# Merge data
merged_data = pd.merge(financial_df, astro_df, left_on='time', right_on='date', how='inner')
# Save merged data
merged_data.to_csv('merged_astro_financial_data.csv', index=False)
print("Merged data saved to merged_astro_financial_data.csv")
# Part 4: Statistical analysis of correlations
# Select numeric columns for correlation analysis
numeric_columns = merged_data.select_dtypes(include=[np.number]).columns
# Create lags for astronomical data
for col in numeric_columns:
if col not in ['open', 'high', 'low', 'close', 'tick_volume', 'spread', 'real_volume']:
for lag in range(1, 6): # Create lags from 1 to 5
merged_data[f'{col}_lag{lag}'] = merged_data[col].shift(lag)
# Update list of numeric columns
numeric_columns = merged_data.select_dtypes(include=[np.number]).columns
# Calculate correlation matrix
correlation_matrix = merged_data[numeric_columns].corr()
# Create heatmap of correlations
plt.figure(figsize=(20, 16))
sns.heatmap(correlation_matrix, annot=False, cmap='coolwarm', vmin=-1, vmax=1, center=0)
plt.title('Correlation Matrix of Astronomical Factors (with Lags) and EURUSD Prices')
plt.tight_layout()
plt.savefig('correlation_heatmap_with_lags.png')
plt.close()
# Output the most significant correlations with the closing price
significant_correlations = correlation_matrix['close'].sort_values(key=abs, ascending=False)
print("Most significant correlations with the closing price:")
print(significant_correlations)
# Create a separate correlation matrix for astronomical data with lags and the current price
astro_columns = [col for col in numeric_columns if col not in ['open', 'high', 'low', 'tick_volume', 'spread', 'real_volume']]
astro_columns.append('close') # Add the current closing price
astro_correlation_matrix = merged_data[astro_columns].corr()
# Create heatmap of correlations for astronomical data with lags and the current price
import seaborn as sns
import matplotlib.pyplot as plt
# Increase the header and axis label font
plt.figure(figsize=(18, 14))
sns.heatmap(astro_correlation_matrix, annot=False, cmap='coolwarm', vmin=-1, vmax=1, center=0, cbar_kws={'label': 'Correlation'})
plt.title('Correlation matrix of astronomical factors (with lags) and current EURUSD price', fontsize=24)
plt.xlabel('X-axis Label', fontsize=30)
plt.ylabel('Y-axis Label', fontsize=30)
plt.xticks(fontsize=30)
plt.yticks(fontsize=30)
plt.tight_layout()
plt.savefig('astro_correlation_heatmap_with_lags.png')
plt.close()
print("Analysis completed. Results saved in CSV and PNG files.")
Questo script visualizza una mappa delle correlazioni tra tutti i numeri del set di dati e una matrice di tutte le correlazioni in formato heatmap, oltre a produrre un elenco delle correlazioni più significative con i prezzi di chiusura.
La presenza o l'assenza di una correlazione non implica la presenza o l'assenza di una relazione causale. Anche se trovassimo forti correlazioni tra i dati astronomici e i movimenti dei prezzi, ciò non significherebbe che un fattore determini l'altro e viceversa. Sono necessarie nuove ricerche, poiché la mappa di correlazione è solo la cosa più elementare.

Se ci avviciniamo all'argomento, non siamo in grado di trovare alcuna correlazione significativa nei dati. Non ci sono chiare correlazioni tra i dati astronomici del passato e gli indicatori di mercato.

L'apprendimento automatico in soccorso
Ho pensato a cosa fare dopo e ho deciso di applicare un modello di apprendimento automatico. Ho realizzato due script utilizzando la libreria CatBoost che cercano di prevedere i prezzi futuri utilizzando i dati del dataset come caratteristiche. Ecco il primo dei modelli - un modello di regressione:
import pandas as pd
import numpy as np
from catboost import CatBoostRegressor
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error, mean_absolute_error, r2_score
import matplotlib.pyplot as plt
from sklearn.preprocessing import LabelEncoder
# Loading data
data = pd.read_csv('merged_astro_financial_data.csv')
# Converting date to datetime
data['date'] = pd.to_datetime(data['date'])
# Creating lags for financial data
for col in ['open', 'high', 'low', 'close']:
for lag in range(1, 6): # Creating lags from 1 to 5
data[f'{col}_lag{lag}'] = data[col].shift(lag)
# Creating lags for astronomical data
astro_cols = ['mercury', 'venus', 'mars', 'jupiter', 'saturn', 'uranus', 'neptune']
for col in astro_cols:
data[f'{col}_ra'] = data[col].apply(lambda x: eval(x)['ra'] if pd.notna(x) else np.nan)
data[f'{col}_dec'] = data[col].apply(lambda x: eval(x)['dec'] if pd.notna(x) else np.nan)
for lag in range(1, 6): # Lags from 1 to 5
data[f'{col}_ra_lag{lag}'] = data[f'{col}_ra'].shift(lag)
data[f'{col}_dec_lag{lag}'] = data[f'{col}_dec'].shift(lag)
data.drop(columns=[col, f'{col}_ra', f'{col}_dec'], inplace=True)
# Converting aspects to numerical features
aspect_cols = ['mercury_saturn', 'venus_mars', 'venus_jupiter', 'venus_uranus',
'mars_jupiter', 'mars_uranus', 'jupiter_uranus', 'mercury_neptune',
'venus_saturn', 'venus_neptune', 'mars_saturn', 'mercury_venus',
'mars_neptune', 'mercury_uranus', 'saturn_neptune', 'mercury_jupiter',
'mercury_mars', 'jupiter_saturn']
# Using LabelEncoder for encoding aspects
label_encoders = {}
for col in aspect_cols:
label_encoders[col] = LabelEncoder()
data[col] = label_encoders[col].fit_transform(data[col].astype(str))
# Filling missing values with mean values for numeric columns
numeric_cols = data.select_dtypes(include=[np.number]).columns
data[numeric_cols] = data[numeric_cols].fillna(data[numeric_cols].mean())
# Removing rows with missing values
data = data.dropna()
# Preparing features and target variable
features = [col for col in data.columns if col not in ['date', 'time', 'close']]
X = data[features]
y = data['close']
# Splitting data into training and testing sets
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=1)
# Creating and training the CatBoost model
model = CatBoostRegressor(iterations=500, learning_rate=0.1, depth=9, random_state=1)
model.fit(X_train, y_train, eval_set=(X_test, y_test), early_stopping_rounds=200, verbose=100)
# Evaluating the model
y_pred = model.predict(X_test)
mse = mean_squared_error(y_test, y_pred)
mae = mean_absolute_error(y_test, y_pred)
r2 = r2_score(y_test, y_pred)
print(f"Mean Squared Error: {mse}")
print(f"Mean Absolute Error: {mae}")
print(f"R-squared Score: {r2}")
# Visualizing feature importance
feature_importance = model.feature_importances_
feature_names = X.columns
sorted_idx = np.argsort(feature_importance)
pos = np.arange(sorted_idx.shape[0]) + 0.5
plt.figure(figsize=(12, 6))
plt.barh(pos, feature_importance[sorted_idx], align='center')
plt.yticks(pos, np.array(feature_names)[sorted_idx])
plt.xlabel('Feature Importance')
plt.title('Feature Importance')
plt.show()
# Predicting the next value
def predict_next():
# Selecting the last row of data
last_data = data.iloc[-1]
input_features = last_data[features].values.reshape(1, -1)
# Prediction
prediction = model.predict(input_features)
print(f"Prediction for the next closing price: {prediction[0]}")
# Example of using the function to predict the next value
predict_next()

Il secondo modello è di classificazione:
import pandas as pd
import numpy as np
from skyfield.api import load, utc
from datetime import datetime, timedelta
import requests
import MetaTrader5 as mt5
import seaborn as sns
import matplotlib.pyplot as plt
from catboost import CatBoostClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score, classification_report, confusion_matrix
from sklearn.preprocessing import LabelEncoder
# Part 1: Collecting astronomical data
planets = load('de421.bsp')
earth = planets['earth']
ts = load.timescale()
def get_planet_positions(date):
t = ts.from_datetime(date.replace(tzinfo=utc))
planet_positions = {}
planet_ids = {
'mercury': 'MERCURY BARYCENTER',
'venus': 'VENUS BARYCENTER',
'mars': 'MARS BARYCENTER',
'jupiter': 'JUPITER BARYCENTER',
'saturn': 'SATURN BARYCENTER',
'uranus': 'URANUS BARYCENTER',
'neptune': 'NEPTUNE BARYCENTER'
}
for planet, planet_id in planet_ids.items():
planet_obj = planets[planet_id]
astrometric = earth.at(t).observe(planet_obj)
ra, dec, _ = astrometric.radec()
planet_positions[planet] = {'ra': ra.hours, 'dec': dec.degrees}
return planet_positions
def get_moon_phase(date):
t = ts.from_datetime(date.replace(tzinfo=utc))
eph = load('de421.bsp')
moon, sun, earth = eph['moon'], eph['sun'], eph['earth']
e = earth.at(t)
_, m, _ = e.observe(moon).apparent().ecliptic_latlon()
_, s, _ = e.observe(sun).apparent().ecliptic_latlon()
phase = (m.degrees - s.degrees) % 360
return phase
def get_solar_activity(date):
url = f"https://services.swpc.noaa.gov/json/solar-cycle/observed-solar-cycle-indices.json"
response = requests.get(url)
data = response.json()
target_date = date.strftime("%Y-%m")
closest_data = min(data, key=lambda x: abs(datetime.strptime(x['time-tag'], "%Y-%m") - datetime.strptime(target_date, "%Y-%m")))
return {
'sunspot_number': closest_data.get('ssn', None),
'f10.7_flux': closest_data.get('f10.7', None)
}
def calculate_aspects(positions):
aspects = {}
planets = list(positions.keys())
for i in range(len(planets)):
for j in range(i+1, len(planets)):
planet1 = planets[i]
planet2 = planets[j]
ra1 = positions[planet1]['ra']
ra2 = positions[planet2]['ra']
angle = abs(ra1 - ra2) % 24
angle = min(angle, 24 - angle) * 15 # Convert to degrees
if abs(angle - 0) <= 10 or abs(angle - 180) <= 10:
aspects[f"{planet1}_{planet2}"] = "conjunction" if abs(angle - 0) <= 10 else "opposition"
elif abs(angle - 90) <= 10:
aspects[f"{planet1}_{planet2}"] = "square"
elif abs(angle - 120) <= 10:
aspects[f"{planet1}_{planet2}"] = "trine"
return aspects
# Part 2: Obtaining financial data through MetaTrader5
def get_financial_data(symbol, start_date, end_date):
if not mt5.initialize():
print("initialize() failed")
mt5.shutdown()
return None
timeframe = mt5.TIMEFRAME_D1
rates = mt5.copy_rates_range(symbol, timeframe, start_date, end_date)
mt5.shutdown()
financial_df = pd.DataFrame(rates)
financial_df['time'] = pd.to_datetime(financial_df['time'], unit='s')
return financial_df
# Part 3: Synchronizing astronomical and financial data
def sync_data(astro_df, financial_df):
astro_df['date'] = pd.to_datetime(astro_df['date']).dt.tz_localize(None)
financial_df['time'] = pd.to_datetime(financial_df['time'])
merged_data = pd.merge(financial_df, astro_df, left_on='time', right_on='date', how='inner')
return merged_data
# Part 4: Training the model and making predictions
def train_and_predict(merged_data):
# Converting aspects to numerical features
aspect_cols = [col for col in merged_data.columns if '_' in col and col not in ['date', 'time']]
label_encoders = {}
for col in aspect_cols:
label_encoders[col] = LabelEncoder()
merged_data[col] = label_encoders[col].fit_transform(merged_data[col].astype(str))
# Creating lags for financial data
for col in ['open', 'high', 'low', 'close']:
for lag in range(1, 6):
merged_data[f'{col}_lag{lag}'] = merged_data[col].shift(lag)
# Creating lags for astronomical data
astro_cols = ['mercury', 'venus', 'mars', 'jupiter', 'saturn', 'uranus', 'neptune']
for col in astro_cols:
merged_data[f'{col}_ra'] = merged_data[col].apply(lambda x: eval(x)['ra'] if pd.notna(x) else np.nan)
merged_data[f'{col}_dec'] = merged_data[col].apply(lambda x: eval(x)['dec'] if pd.notna(x) else np.nan)
for lag in range(1, 6):
merged_data[f'{col}_ra_lag{lag}'] = merged_data[f'{col}_ra'].shift(lag)
merged_data[f'{col}_dec_lag{lag}'] = merged_data[f'{col}_dec'].shift(lag)
merged_data.drop(columns=[col, f'{col}_ra', f'{col}_dec'], inplace=True)
# Filling missing values with mean values for numeric columns
numeric_cols = merged_data.select_dtypes(include=[np.number]).columns
merged_data[numeric_cols] = merged_data[numeric_cols].fillna(merged_data[numeric_cols].mean())
merged_data = merged_data.dropna()
# Creating binary target variable
merged_data['price_change'] = (merged_data['close'].shift(-1) > merged_data['close']).astype(int)
# Removing rows with missing values in the target variable
merged_data = merged_data.dropna(subset=['price_change'])
features = [col for col in merged_data.columns if col not in ['date', 'time', 'close', 'price_change']]
X = merged_data[features]
y = merged_data['price_change']
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=1)
model = CatBoostClassifier(iterations=500, learning_rate=0.1, depth=9, random_state=1)
model.fit(X_train, y_train, eval_set=(X_test, y_test), early_stopping_rounds=200, verbose=100)
y_pred = model.predict(X_test)
accuracy = accuracy_score(y_test, y_pred)
clf_report = classification_report(y_test, y_pred)
conf_matrix = confusion_matrix(y_test, y_pred)
print(f"Accuracy: {accuracy}")
print("Classification Report:")
print(clf_report)
print("Confusion Matrix:")
print(conf_matrix)
# Visualizing feature importance
feature_importance = model.feature_importances_
feature_names = X.columns
sorted_idx = np.argsort(feature_importance)
pos = np.arange(sorted_idx.shape[0]) + 0.5
plt.figure(figsize=(12, 6))
plt.barh(pos, feature_importance[sorted_idx], align='center')
plt.yticks(pos, np.array(feature_names)[sorted_idx])
plt.xlabel('Feature Importance')
plt.title('Feature Importance')
plt.show()
# Predicting the next value
def predict_next():
last_data = merged_data.iloc[-1]
input_features = last_data[features].values.reshape(1, -1)
prediction = model.predict(input_features)
print(f"Price change prediction (0: will decrease, 1: will increase): {prediction[0]}")
predict_next()
# Main program
start_date = datetime(2023, 3, 1)
end_date = datetime(2024, 7, 30)
astro_data = []
current_date = start_date
while current_date <= end_date:
planet_positions = get_planet_positions(current_date)
moon_phase = get_moon_phase(current_date)
try:
solar_activity = get_solar_activity(current_date)
except Exception as e:
print(f"Error getting solar activity for {current_date}: {e}")
solar_activity = {'sunspot_number': None, 'f10.7_flux': None}
aspects = calculate_aspects(planet_positions)
astro_data.append({
'date': current_date,
'mercury': str(planet_positions['mercury']),
'venus': str(planet_positions['venus']),
'mars': str(planet_positions['mars']),
'jupiter': str(planet_positions['jupiter']),
'saturn': str(planet_positions['saturn']),
'uranus': str(planet_positions['uranus']),
'neptune': str(planet_positions['neptune']),
'moon_phase': moon_phase,
**solar_activity,
**aspects
})
current_date += timedelta(days=1)
astro_df = pd.DataFrame(astro_data)
symbol = "EURUSD"
financial_data = get_financial_data(symbol, start_date, end_date)
if financial_data is not None:
merged_data = sync_data(astro_df, financial_data)
train_and_predict(merged_data) Purtroppo, nessuno dei modelli offre una grande precisione. L'accuratezza della classificazione è leggermente superiore al 50%, il che significa che possiamo prevedere altrettanto facilmente sulla base del lancio di una moneta.

Forse il risultato può essere migliorato, poiché il modello di regressione è stato poco considerato e in effetti è possibile prevedere i prezzi utilizzando le posizioni planetarie e l'attività della Luna e del Sole. Se sarò dell'umore giusto, scriverò un altro articolo su questo argomento.
Risultati
È quindi giunto il momento di riassumere i risultati. Dopo aver condotto una semplice analisi e aver scritto due modelli di previsione, vediamo i risultati dello studio sul potenziale impatto dell'astrologia sul mercato.
Analisi di correlazione. La mappa di correlazione ottenuta non ha rivelato alcuna forte correlazione tra le posizioni planetarie e il prezzo di chiusura dell'EURUSD. Tutte le nostre correlazioni sono inferiori a 0,3, il che ci dà ragione di credere che la posizione di stelle o pianeti non sia affatto collegata ai mercati finanziari.
Modello di regressione CatBoost. I risultati finali del modello di regressione hanno mostrato una scarsa capacità di prevedere con precisione i prezzi di chiusura futuri sulla base dei dati astronomici.
Le metriche di prestazione del modello risultanti, come MSE, MAE e R al quadrato, sono molto deboli e spiegano molto male i dati. Allo stesso tempo, il modello mostra che le caratteristiche più importanti sono i lag e i valori di prezzo precedenti, piuttosto che le posizioni dei pianeti. Quindi, questo significa che il prezzo è un indicatore migliore della posizione di qualsiasi pianeta del nostro sistema solare?
Modello di classificazione CatBoost. Il modello di classificazione è estremamente scarso nel prevedere i futuri aumenti o diminuzioni dei prezzi. L'accuratezza supera a malapena il 50%, il che conferma che l'astronomia non funziona nel mercato reale.
Conclusioni
I risultati dello studio sono abbastanza chiari - i metodi dell'astrologia e i tentativi di prevedere i prezzi sul mercato reale sulla base di dati astronomici sono completamente inutili. Forse tornerò su questo argomento, ma per ora gli insegnamenti di William Gann sembrano tentativi di mascherare soluzioni non funzionanti create solo per vendere libri e corsi di trading.
È possibile che un modello migliorato che utilizzi anche i valori dell'angolo di Gann, i valori del quadrato dei 9 e i valori della griglia di Gann abbia prestazioni migliori? Non lo sappiamo ancora. Sono un po' deluso dai risultati dello studio.
Ma continuo a pensare che gli angoli di Gann possano essere utilizzati in un modo o nell'altro per ottenere previsioni di prezzo funzionanti. Il prezzo influenza gli angoli in un modo o nell'altro, reagisce ad essi, come è evidente dai risultati dello studio precedente. È anche possibile che gli angoli possano essere utilizzati come caratteristiche di lavoro per l'addestramento dei modelli. Proverò a creare un set di dati di questo tipo e a vedere cosa ne esce fuori.
Tradotto dal russo da MetaQuotes Ltd.
Articolo originale: https://www.mql5.com/ru/articles/15625
Avvertimento: Tutti i diritti su questi materiali sono riservati a MetaQuotes Ltd. La copia o la ristampa di questi materiali in tutto o in parte sono proibite.
Questo articolo è stato scritto da un utente del sito e riflette le sue opinioni personali. MetaQuotes Ltd non è responsabile dell'accuratezza delle informazioni presentate, né di eventuali conseguenze derivanti dall'utilizzo delle soluzioni, strategie o raccomandazioni descritte.
Arriva il Nuovo MetaTrader 5 e MQL5
I metodi di William Gann (parte II): Creazione dell'indicatore Quadrato di Gann
Utilizza i canali MQL5.community e le chat di gruppo
I metodi di William Gann (Parte I): Creazione dell'indicatore Angoli di Gann
- App di trading gratuite
- Oltre 8.000 segnali per il copy trading
- Notizie economiche per esplorare i mercati finanziari
Accetti la politica del sito e le condizioni d’uso

Seguendo le orme del Ghana, per amore della purezza dell'esperienza, non avreste dovuto prendere EURUSD ma, ad esempio, i futures sul cotone. E lo strumento è all'incirca lo stesso e i cicli astronomici possono essere in esso, dopo tutto, l'agricoltura.