英文:
TypeError: 'float' object is not subscriptable while printing
问题
# 获取指定符号的当前余额
symbols_to_check = ["USDT", "BNB", "BTC", "ETH"]
balances = get_current_balances(symbols_to_check)
print("当前余额:")
for symbol in symbols_to_check:
balance_info = balances.get(symbol, {"free": 0.0})
print(f"{symbol}: 可用 - {balance_info['free']}")
出现以下错误:
Traceback (most recent call last):
File "main.py", line 83, in <module>
print(f"{symbol}: 可用 - {balance_info['free']}")
TypeError: 'float' object is not subscriptable
对于任何对代码结构感兴趣,以提供可能导致错误或更好的实现预测的提示的人,都欢迎,我对Python相当新,也不是最好的开发人员。
<details>
<summary>英文:</summary>
Get the current balances for the specified symbols
symbols_to_check = ["USDT", "BNB", "BTC", "ETH"]
balances = get_current_balances(symbols_to_check)
print("Current Balances:")
for symbol in symbols_to_check:
balance_info = balances.get(symbol, {"free": 0.0})
print(f"{symbol}: Free - {balance_info['free']}")
Throws a following error:
Traceback (most recent call last):
File "main.py", line 83, in <module>
print(f"{symbol}: Free - {balance_info['free']}")
TypeError: 'float' object is not subscriptable
for anyone interested in the hole code structure to provide any tips that might lead to errors or better ideas to implement better predictions are welcome, i am pretty new to python and not the best developer overall.
```
import pandas as pd
import numpy as np
import requests
from binance.client import BinanceAPIException, Client
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import MinMaxScaler
import tensorflow as tf
import schedule
import time
import itertools
tf.config.list_physical_devices('GPU')
# Define parameters
api_key = "YOUR_API_KEY"
api_secret = "YOUR_SECRET_KEY"
base_url = "https://api.binance.com"
symbols = ["BTCUSDT", "ETHUSDT", "BNBUSDT"]
interval = "1h"
limit = 1000
paper_trading = False
# Create a client object
client = Client(api_key, api_secret)
# Create an empty dictionary to store the profits and losses of each symbol
profit_loss_dict = {}
# Define a threshold for trading (can be adjusted)
threshold = {"BTCUSDT": 10, "ETHUSDT": 8, "BNBUSDT": 5}
# Define the tickSize for each symbol
tick_sizes = {"BTCUSDT": 0.01, "ETHUSDT": 0.01, "BNBUSDT":0.1}
# Define the minimum quantity for each symbol
min_quantity = {"BTCUSDT": 0.00036, "ETHUSDT": 0.0059 , "BNBUSDT": 0.045}
# Define a flag to hold after a buy order is executed
hold = False
# Define a function to get the minimum quantity allowed for each symbol
def get_min_quantity(symbol):
return min_quantity.get(symbol, 0.01)
# Modify the get_trimmed_price function to return a tuple (trimmed_price, min_qty)
def get_trimmed_price(target_value, symbol):
tick_size = tick_sizes.get(symbol, 0.01)
trimmed_price = round(target_value / tick_size) * tick_size
return trimmed_price, get_min_quantity(symbol)
# Modify the get_current_balances function to return a dictionary with the actual balances
def get_current_balances(symbols):
try:
# Use the Binance API to get the account information
account_info = client.get_account()
# Create an empty dictionary to store the balances for each symbol
balances = {}
# Find the balance for each specified symbol
for symbol in symbols:
# Find the balance for the specified symbol in the account_info list
balance = next((item for item in account_info['balances'] if item['asset'] == symbol), None)
# If the symbol is found, get the 'free' value, otherwise set it to 0
free_balance = float(balance['free']) if balance else 0.0
balances[symbol] = free_balance
return balances
except Exception as e:
print(f"Error fetching balances: {e}")
return {} # Return an empty dictionary if there is an error
# Get the current balances for the specified symbols
symbols_to_check = ["USDT", "BNB", "BTC", "ETH"]
balances = get_current_balances(symbols_to_check)
print("Current Balances:")
for symbol in symbols_to_check:
balance_info = balances.get(symbol, {"free": 0.0})
print(f"{symbol}: Free - {balance_info['free']}")
# Define a function to get historical data for multiple symbols and save each one to a separate csv file
def get_historical_data(symbols, interval, limit):
# Create an empty list to store the dataframes
dfs = []
# Loop through the symbols
for symbol in symbols:
# Construct the url
url = base_url + "/api/v3/klines"
params = {"symbol": symbol, "interval": interval, "limit": limit}
# Send a get request and parse the response
response = requests.get(url, params=params)
data = response.json()
# Convert the data to a dataframe
df = pd.DataFrame(data, columns=["open_time", "open", "high", "low", "close", "volume", "close_time", "quote_volume","trades", "taker_base_volume", "taker_quote_volume", "ignore"])
# Convert the columns to numeric values
df = df.apply(pd.to_numeric)
# Convert the time columns to datetime format
df["open_time"] = pd.to_datetime(df["open_time"], unit="ms")
df["close_time"] = pd.to_datetime(df["close_time"], unit="ms")
# Add a column for the symbol name
df["symbol"] = symbol
# Add a column for the moving average
df["moving_average"] = np.nan
# Append the dataframe to the list
dfs.append(df)
# Concatenate all the dataframes in the list
df = pd.concat(dfs, ignore_index=True)
# Save the dataframe to a csv file
df.to_csv(f"historical_data_{interval}.csv", index=False)
# Return the dataframe
return df
# Define a function to fetch and update historical data
def update_historical_data():
global df # Use the global df variable
# Get historical data for multiple symbols and save it to a csv file
df = get_historical_data(symbols, interval, limit)
# Schedule the update_historical_data function to run at the specified interval
update_interval_hours = 1 # Set the update interval (in hours)
schedule.every(update_interval_hours).hours.do(update_historical_data)
# Define a function to get real-time data for one symbol
def get_realtime_data(symbol):
# Construct the url
url = base_url + "/api/v3/ticker/price"
params = {"symbol": symbol}
# Send a get request and parse the response
response = requests.get(url, params=params)
data = response.json()
# Convert the data to a float value
price = float(data["price"])
# Return the price
return price
# Check the shape of the dataframe and make sure it has enough rows (at least 250)
# Create the MinMaxScaler in a global scope
scaler = MinMaxScaler()
# Define a function to create a neural network model for one symbol using historical data
def create_model(df, symbol):
global scaler # Use the global scaler variable
# Filter the dataframe by the symbol name
df_symbol = df[df["symbol"] == symbol]
# Select the features and the target
X = df_symbol[["open", "high", "low", "volume"]].values
y = df_symbol["close"].values
# Scale the features to a range of (0, 1)
X = scaler.fit_transform(X)
# Split the data into training and testing sets
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# Create a neural network model using Sequential
model = tf.keras.Sequential([
tf.keras.layers.Dense(64, activation='relu', input_shape=(X_train.shape[1],)),
tf.keras.layers.Dense(32, activation='relu'),
tf.keras.layers.Dense(1) # Output layer, predicting the closing price
])
# Compile the model
model.compile(optimizer='adam', loss='mean_squared_error')
# Train the model
epochs = 50
batch_size = 32
model.fit(X_train, y_train, epochs=epochs, batch_size=batch_size, validation_split=0.2, verbose=0)
# Evaluate the model
loss = model.evaluate(X_test, y_test, verbose=0)
print(f"Model evaluation for {symbol}: Test loss: {loss}")
# Return the model
return model
def update_model():
global df, models, mean_reversion_models
# Check if there is new data available (compare the number of rows with the previous number)
if df is not None and df.shape[0] >= 250: # Assuming 250 rows are needed to create a model
# Loop through the symbols and update the models
for symbol in symbols:
if df[df["symbol"] == symbol].shape[0] >= 250:
model = create_model(df, symbol)
models[symbol] = model
else:
print(f"Not enough data to update the model for {symbol}")
else:
print("Not enough data to update models.")
# Schedule the update_model function to run every hour
schedule.every(1).hour.do(update_model)
risk_tolerance_percentage = 30 # Set your desired risk tolerance percentage here
# Define a function to save the predicted prices with dates and times to a CSV file
def save_predictions(predictions, symbols, datetimes):
df = pd.DataFrame({"symbol": symbols, "predicted_price": predictions, "datetime": datetimes})
df.to_csv("predictions_main_py.csv", index=False)
trade_status = {}
# Create an empty dictionary to store the trimmed prices for each symbol
trimmed_prices = {}
def trade(model, symbol, paper_trading):
global scaler, hold, tick_sizes, min_quantity, trimmed_prices, trade_status, balances
# Get the current price
current_price = get_realtime_data(symbol)
# Add 'global balances' statement to specify the global scope
global balances
if paper_trading:
base_asset_balance = get_current_balances(["USDT"]).get("USDT", {}).get("free", 0.0)
trading_asset_balance = 0.0 # Since we are paper trading, set the trading asset balance to 0
else:
balances = get_current_balances([symbol, "USDT"])
base_asset_balance = balances.get("USDT", {}).get("free", 0.0)
trading_asset_balance = balances.get(symbol, {}).get("free", 0.0)
portfolio_value = base_asset_balance + trading_asset_balance * current_price
# Trim the current price based on tickSize and store in the trimmed_prices dictionary
trimmed_price, min_qty = get_trimmed_price((risk_tolerance_percentage / 100) * portfolio_value, symbol)
trimmed_prices[symbol] = trimmed_price
# Use the model to make predictions for the new data
df_symbol = df[df["symbol"] == symbol]
X_last_row = df_symbol[["open", "high", "low", "volume"]].iloc[-1:].values
X_last_row_scaled = scaler.transform(X_last_row)
prediction = model.predict(X_last_row_scaled)[0][0]
# Check if hold flag is True, and if yes, do not execute buy order
if hold:
_, trading_asset_balance = get_current_balances([symbol])[symbol]["free"]
if trading_asset_balance >= min_qty:
print(f"Holding {symbol} - waiting for sell order to be executed")
else:
print(f"Holding {symbol} - Insufficient quantity to trade. Waiting for sell order to be executed.")
return
if trade_status.get(symbol) == "BOUGHT":
# If the trade status is "BOUGHT", it means we already bought the asset and are waiting for a sell order.
# Check if we have the minimum quantity to sell.
_, trading_asset_balance = get_current_balances([symbol])[symbol]["free"]
if trading_asset_balance >= min_quantity[symbol]:
print(f"Holding {symbol} - Waiting for sell order to be executed.")
else:
print(f"Holding {symbol} - Insufficient quantity to sell. Waiting for sell order to be executed.")
else:
if not paper_trading:
# Calculate the trading quantity based on the position size and current price
quantity = (risk_tolerance_percentage / 100) * portfolio_value / current_price
# Round the quantity according to the tickSize for each symbol
decimals = int(-np.log10(tick_sizes[symbol]))
quantity = round(quantity, decimals)
# Check the available balance for the trading asset
_, trading_asset_balance = get_current_balances([symbol])[symbol]["free"]
# Compare the quantity with the trading asset balance
if quantity > trading_asset_balance:
# If the quantity exceeds the available balance, set it to the available balance
quantity = trading_asset_balance
# If the calculated quantity is less than the minimum quantity allowed, use the minimum allowed quantity
if quantity < min_quantity[symbol]:
quantity = min_quantity[symbol]
print(f"Quantity is less than the minimum allowed for {symbol}. Using the minimum allowed quantity for the trade.")
print(f"Trading {symbol}:")
print(f" Quantity: {quantity}")
print(f" Tick Size: {tick_sizes[symbol]}")
print(f" Current Price: {current_price}")
print(f" Portfolio Value: {portfolio_value}")
print(f" Predicted Price for {symbol}: {prediction}, Current price: {current_price}")
try:
if prediction < trimmed_prices[symbol]:
# Place a market buy order using the client object
order_buy = client.order_market_buy(symbol=symbol, quantity=quantity)
print(order_buy)
print("Market buy order executed.")
# Set trade status to "BOUGHT" after executing the buy order
trade_status[symbol] = "BOUGHT"
# Set hold flag to True after executing the buy order to wait for the sell order
hold = True
else:
print(f"No Buy Signal for {symbol} at current price {current_price}")
except BinanceAPIException as e:
print(f"Error: {e}")
else:
# Use the model to make predictions for the new data
df_symbol = df[df["symbol"] == symbol]
X_last_row = df_symbol[["open", "high", "low", "volume"]].iloc[-1:].values
X_last_row_scaled = scaler.transform(X_last_row)
prediction = model.predict(X_last_row_scaled)[0][0]
print(f"Price prediction for {symbol}: {prediction}, Current price: {current_price}")
# Add the SELL logic here
if trade_status.get(symbol) == "BOUGHT" and prediction > trimmed_prices[symbol]:
try:
# Place a market sell order using the client object
order_sell = client.order_market_sell(symbol=symbol, quantity=min_quantity[symbol])
print(order_sell)
print("Market sell order executed.")
# Reset trade status and hold flag after executing the sell order
trade_status[symbol] = None
hold = False
except BinanceAPIException as e:
print(f"Error: {e}")
# Define a function to save the profits and losses of trade dates for each symbol
def save_profit_loss(profit_loss_dict):
# Convert the dictionary to a dataframe
df = pd.DataFrame.from_dict(profit_loss_dict, orient="index")
# Add a column for the net profit or loss
df["net"] = df["profit"] - df["loss"]
# Save the dataframe to a csv file
df.to_csv("profit_loss.csv", index=True)
# Return the dataframe
return df
# Initialize "profit" and "loss" keys in the profit_loss_dict for each symbol
for symbol in symbols:
profit_loss_dict[symbol] = {"profit": 0, "loss": 0}
# Get the current balances for the specified symbols
symbols_to_check = ["USDT", "BNB", "BTC", "ETH"]
balances = get_current_balances(symbols_to_check)
print("Current Balances:")
for symbol, balance_info in balances.items():
print(f"{symbol}: Free - {balance_info['free']}")
# Call the update_historical_data function to initialize the df variable before creating the models and starting the trading loop
update_historical_data()
# Loop through the symbols and create a model for each one
models = {}
#mean_reversion_models = {} # Create a separate dictionary to store mean reversion models
for symbol in symbols:
# Create a neural network model using historical data
if df.shape[0] >= 250:
model = create_model(df, symbol)
models[symbol] = model
else:
print(f"Not enough data to create a model for {symbol}")
# Save the profit and loss to a csv file
save_profit_loss(profit_loss_dict)
print(df.shape)
# The main trading loop
while True:
schedule.run_pending() # Check if the scheduled update_model function needs to run
if df is not None: # Add this condition to avoid accessing shape of None
# Get the current balances for the specified symbols
balances = get_current_balances(["USDT", "BNB", "BTC", "ETH"])
print("Current Balances:")
for symbol in symbols:
trading_asset_balance = balances.get(symbol, 0.0)
print(f"{symbol}: Free - {trading_asset_balance}")
for symbol in symbols:
# Fetch the latest price data for the symbol
current_price = get_realtime_data(symbol)
# Fetch the portfolio value from the account for live or paper trading
if paper_trading:
base_asset_balance = balances.get("USDT", 0.0)
trading_asset_balance = balances.get(symbol, 0.0)
else:
base_asset_balance = balances.get("USDT", 0.0)
trading_asset_balance = balances.get(symbol, 0.0)
# Calculate the portfolio value
portfolio_value = base_asset_balance + trading_asset_balance * current_price
# Calculate the quantity
quantity = (risk_tolerance_percentage / 100) * portfolio_value / current_price
# Round the quantity according to the tickSize for each symbol
decimals = int(-np.log10(tick_sizes[symbol]))
quantity = round(quantity, decimals)
# Perform trading using updated models
trade(models[symbol], symbol, paper_trading=False) # Set paper_trading=False for live trading
# Delay between consecutive API requests to avoid rate limiting
time.sleep(1)
```
</details>
# 答案1
**得分**: -1
```python
balance_info = balances.get(symbol, {"free": 0.0})
print(f"{symbol}: Free - {balance_info['free']}")
```
`balances`是一个字典,所以如果`symbol`在这个字典中,`balance_info`是这个符号下的余额**值**,因此在您当前的代码中是一个浮点数。在下一行中,您将`balance_info`视为字典,这会导致错误。您可能想要执行以下操作:
```python
free_balance = float(balance['free']) if balance else 0.0
balances[symbol] = {'free': free_balance} # 而不是 ... = free_balance
```
在您的获取当前余额函数中,这样在[symbol]键下实际上仍然有一个字典(而不是一个浮点数)。
<details>
<summary>英文:</summary>
```
balance_info = balances.get(symbol, {"free": 0.0})
print(f"{symbol}: Free - {balance_info['free']}")
```
`balances` is a dictionary, so if `symbol` is inside this dictionary, `balance_info` is a **value** of the balance under this symbol, and thus in your current code - a float. In the next line you treat balance_info as a dictionary, which causes an error. You probably meant to do
```
free_balance = float(balance['free']) if balance else 0.0
balances[symbol] = {'free': free_balance} # instead of ... = free_balance
```
inside your get current balance function, so that under [symbol] key you actually still have a dictionary (rather than a float).
</details>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论