I am trying to get test data from two CSV files. However whenever I put a test case in for example:
val = Test_data("AAPL.csv", "close", 25)
print (val)
I get:
Open.append(temp[1])
IndexError: list index out of range
I have tried changing the file to read, readlines, and readline.
def main():
pass
if __name__ == '__main__':
main()
def test_data(filename, col, day):
"""A test function to query the data you loaded into your program.
Args:
filename: A string for the filename containing the stock data,
in CSV format.
col: A string of either "date", "open", "high", "low", "close",
"volume", or "adj_close" for the column of stock market data to
look into.
The string arguments MUST be LOWERCASE!
day: An integer reflecting the absolute number of the day in the
data to look up, e.g. day 1, 15, or 1200 is row 1, 15, or 1200
in the file.
Returns:
A value selected for the stock on some particular day, in some
column col. The returned value *must* be of the appropriate type,
such as float, int or str.
"""
Date = list()
Open = list()
High = list()
Low = list()
Close = list()
AdjClose = list()
Volume = list()
file = open(filename, "r")
x= file.read()
for line in x:
temp = line.split(",")
Date.append(temp[0])
Open.append(temp[1])
High.append(temp[2])
Low.append(temp[3])
Close.append(temp[4])
AdjClose.append(temp[5])
Volume.append(temp[6])
if col == 'Date':
return Date[day - 1]
elif col == 'Open':
return Open[day - 1]
elif col == 'High':
return High[day - 1]
elif col == 'Low':
return Low[day - 1]
elif col == 'Close':
return Close[day - 1]
elif col == 'Adj close':
return AdjClose[day - 1]
elif col == 'Volume':
return Volume[day - 1]
def transact(funds, stocks, qty, price, buy=False, sell=False):
"""A bookkeeping function to help make stock transactions.
Args:
funds: An account balance, a float; it is a value of how much money you have,
currently.
stocks: An int, representing the number of stock you currently own.
qty: An int, representing how many stock you wish to buy or sell.
price: An float reflecting a price of a single stock.
buy: This option parameter, if set to true, will initiate a buy.
sell: This option parameter, if set to true, will initiate a sell.
Returns:
Two values *must* be returned. The first (a float) is the new
account balance (funds) as the transaction is completed. The second
is the number of stock now owned (an int) after the transaction is
complete.
Error condition #1: If the `buy` and `sell` keyword parameters are both set to true,
or both false. You *must* print an error message, and then return
the `funds` and `stocks` parameters unaltered. This is an ambiguous
transaction request!
Error condition #2: If you buy, or sell without enough funds or
stocks to sell, respectively. You *must* print an error message,
and then return the `funds` and `stocks` parameters unaltered. This
is an ambiguous transaction request!
"""
if buy == sell:
# print("Ambigious transaction! Can't determine whether to buy or sell. No action performed.")
return funds, stocks
elif buy and funds >= qty * price:
funds -= qty * price
stocks += qty
# print("Insufficient funds")
return funds, stocks
elif sell and stocks >= qty:
funds += qty * price
stocks -= qty
# print("Insufficient stock")
return funds, stocks
Error:
import project
cash_balance = 1000
stocks_owned = 25
price = test_data("AAPL.csv", "close", 42)
Traceback (most recent call last):
File "<input>", line 1, in <module>
NameError: name 'test_data' is not defined
What Im supposed to get:
>>> cash_balance = 1000
>>> stocks_owned = 25
>>> price = test_data("AAPL.csv", "close", 42)
>>> price
4.357143
I don't know if the problem is because it is not reading my data.
Aren't you supposed to do project.test_data()?
Or from project import test_data?
Related
i try to put some orders at a specific price.
For example i would like to put 20 dollars to buy some ETHUSDT at 800 usdt but it gives me this error:
binance.exceptions.BinanceAPIException: APIError(code=-1106): Parameter 'quoteOrderQty' sent when not required.
there is my call function:
buy_order = client.create_order(
symbol = "ETHUSDT",
price = 800,
quoteOrderQty = 25,
side = client.SIDE_BUY,
type = client.ORDER_TYPE_LIMIT,
timeInForce = client.TIME_IN_FORCE_GTC)
but i dont have any error when i put this :
buy_order = client.create_test_order(symbol="ETHUSDT", side='BUY', type='MARKET', quoteOrderQty=10)
to be honnest actually i do that:
def putOrderBuy_at_price(self, symbol, amount, price):
monney_price = self.client.get_symbol_ticker(symbol=symbol)
# Calculate how much ETH $200 can buy
print(monney_price['price'])
i = 10
while i != 0:
try:
buy_quantity = round(amount / float(price), i)
print("-----------", buy_quantity)
#ETHUSDT
buy_order = self.client.create_order(
symbol = symbol,
price = price,
quantity = buy_quantity,
side = self.client.SIDE_BUY,
type = self.client.ORDER_TYPE_LIMIT,
timeInForce = self.client.TIME_IN_FORCE_GTC)
break
except Exception:
print(i)
i -= 1
And i think there is a better way for that.
Thanks for yours answers
quoteOrderQty is only for MARKET order.
Here is my code:
chosen_year = int(input("Enter the year of interest: "))
print("")
min_life_exp = 999.9
max_life_exp = -1.1
min_life_entity = ""
max_life_entity = ""
min_year = 9999
max_year = -1
chosen_min_life_exp = 999.9
chosen_max_life_exp = -1.1
chosen_min_life_entity = ""
chosen_max_life_entity = ""
with open("life-expectancy.csv") as life_file:
for line in life_file:
parts = line.split(",")
entity = parts[0]
code = parts[1]
year = int(parts[2])
life_exp = float(parts[3])
if max_life_exp < life_exp:
max_life_exp = life_exp
max_life_entity = entity
max_year = year
if min_life_exp > life_exp:
min_life_exp = life_exp
min_life_entity = entity
min_year = year
if chosen_year == year:
avg_life_exp = sum(life_exp) / len(life_exp)
if chosen_max_life_exp < life_exp:
chosen_max_life_exp = life_exp
chosen_max_life_entity = entity
if chosen_min_life_exp > life_exp:
chosen_min_life_exp = life_exp
chosen_min_life_entity = entity
print(f"The overall max life expectancy is: {max_life_exp} from {max_life_entity} in {max_year}")
print(f"The overall max life expectancy is: {min_life_exp} from {min_life_entity} in {min_year}")
print("")
print(f"For the year {chosen_year}:")
print(f"The average life expectancy across all countries was {avg_life_exp:.2f}")
print(f"The max life expectancy was in {chosen_max_life_entity} with {chosen_max_life_exp}")
print(f"The max life expectancy was in {chosen_min_life_entity} with {chosen_min_life_exp}")
I get this error when I run it:
line 38, in <module>
avg_life_exp = sum(life_exp) / len(life_exp)
TypeError: 'float' object is not iterable
how do I change my avg_life_exp to get an average of the life expectancies in the year the user asks for?
To fix this current error, you just need to remove the sum() function Since life_exp is a currently a float. However, I’m guessing you want all of the life_exp in a list, then get the sum of them. To fo this, have the “sum” chunk of the code after reading the lines from the file, since you want to add everything up /after/ you get all the life_exp in each line in the list. If you’d like more specifics, please clarify your question and the expected output.
import config
import robin_stocks as r
r.login(config.USERNAME,config.PASSWORD)
#specify criteria to search for options of a given symbol and its exp date
symbol = 'F'
expirationDate = '2020-06-19'
So the code searches for an option with the highest implied volatility.
search_option = r.find_options_for_stock_by_expiration(symbol,expirationDate,optionType='call')
#identify option with highest implied volatility
highest_IV, highest_idx = 0, None
for idx, option in enumerate(search_option):
if option['implied_volatility'] and highest_IV < float(option['implied_volatility']):
highest_IV = float(option['implied_volatility'])
highest_idx = idx
if highest_idx is not None:
print("Strike Price: {strike_price}, Ask: {ask_price}, Bid: {bid_price}, Delta: {delta}, IV: {implied_volatility}, Order ID: {id}".format(**search_option[highest_idx]))
It then gives me this output:
Strike Price: 1.5000, Ask: 4.900000, Bid: 4.800000, Delta: 0.990127, IV: 9.900301, Order ID: 08bd63f8-2716-4d0a-af09-b2980b933a20
My only problem is, how can I save this output into separate variables?
So it should look something like:
order_strike = 1.5000
order_ask = 4.900000
order_bid = 4.800000
.....
Note: strike, ask, bid, delta and implied volatility have to be integers but order ID has to be a string.
I tried tackling the problem by adding the following code:
order_strike = option.get('strike_price')
order_ask = option.get('ask_price')
order_bid = option.get('bid_price')
order_delta = option.get('delta')
order_IV = option.get('implied_volatility')
order_id = option.get('id')
print('Strike: ', order_strike)
print('Ask Price: ', order_ask)
....
....
But I got this output instead (which clearly does not match the output found in search_option, i.e, Strike: 1.500 etc.):
Strike: 17.0000
Ask Price: 0.010000
Bid Price: 0.000000
Delta: 0.012675
IV: 5.472782
ID: dbcccdb0-cbaa-49f7-b57d-df171bf1e9cf
Any ideas?
When trying to place a buy or sell order with the python-binance api I got the following error:
APIError(code=-1013): Filter failure: LOT_SIZE.
Now I've seen at iceberg_parts that this means there is probably something wrong with my buying or selling quantity. I've tried to increase the quantity by a factor 10 but this only gives me another related error:
APIError(code=-1013): Filter failure: MIN_NOTIONAL.
Here's some of my code:
diff = current_price - prev_price
if diff <= 0.0001:
order = client.order_market_buy(symbol = market , quantity = '0.0001')
print('buy order')
if diff >= 0.00040:
order = client.order_market_sell(symbol =market, quantity ='0.0001')
print('sell order')
Do you know how to fix this?
This error appears because you are trying to create an order with a quantity lower than the minimun required.
You can access the minimun required of a specific pair with:
info = client.get_symbol_info('ETHUSDT')
print(info)
Output a dictionary with information about that pair.
Now you can access the minimun quantity required with:
print(info['filters'][2]['minQty'])
# 0.00001
The buying or selling quantity has to be >= 10.3 USD or 10.3/price, pass the quantity and price to these decimal settings/filters with the amounts set with decimal
from decimal import Decimal as D, ROUND_DOWN, ROUND_UP
import decimal
info = client.get_symbol_info(symbol=pair)
price_filter = float(info['filters'][0]['tickSize'])
ticker = client.get_symbol_ticker(symbol=pair)
price = float(ticker['price'])
price = D.from_float(price).quantize(D(str(price_filter)))
minimum = float(info['filters'][2]['minQty']) # 'minQty'
quant = D.from_float(quantity).quantize(D(str(minimum))) # if quantity >= 10.3/price
I've just gone through this same problem. As a noob, some of the code in these answers seem quite complicated so I came up with a solution.
Code:
def check_decimals(symbol):
info = client.get_symbol_info(symbol)
val = info['filters'][2]['stepSize']
decimal = 0
is_dec = False
for c in val:
if is_dec is True:
decimal += 1
if c == '1':
break
if c == '.':
is_dec = True
return decimal
then when you place the order, just do for ex:
(make sure qty is a float or decimal)
B_order = round(qty / symbol_price, decimal)
order = client.order_market_buy(
symbol=symbol_name,
quantity=B_order)
Maybe this can explain why the server returns this error.
Filters
From the endpoint GET /api/v3/exchangeInfo, you can find all details regarding the trading symbols. It includes many filters that clients need to follow to place an order. For example, the BTCUSDT has the filters as of today(2022-08-31)
"filters": [
{
"filterType": "PRICE_FILTER",
"minPrice": "0.01000000",
"maxPrice": "1000000.00000000",
"tickSize": "0.01000000"
},
{
"filterType": "PERCENT_PRICE",
"multiplierUp": "5",
"multiplierDown": "0.2",
"avgPriceMins": 5
},
{
"filterType": "LOT_SIZE",
"minQty": "0.00001000",
"maxQty": "9000.00000000",
"stepSize": "0.00001000"
},
{
"filterType": "MIN_NOTIONAL",
"minNotional": "10.00000000",
"applyToMarket": true,
"avgPriceMins": 5
},
{
"filterType": "ICEBERG_PARTS",
"limit": 10
},
{
"filterType": "MARKET_LOT_SIZE",
"minQty": "0.00000000",
"maxQty": "282.39806510",
"stepSize": "0.00000000"
},
{
"filterType": "TRAILING_DELTA",
"minTrailingAboveDelta": 10,
"maxTrailingAboveDelta": 2000,
"minTrailingBelowDelta": 10,
"maxTrailingBelowDelta": 2000
},
{
"filterType": "MAX_NUM_ORDERS",
"maxNumOrders": 200
},
{
"filterType": "MAX_NUM_ALGO_ORDERS",
"maxNumAlgoOrders": 5
}
]
LOT_SIZE validation
minQty
If you place an order on this BTCUSDT with parameters:
price=19000
side=BUY
type=LIMIT
quantity=0.000005
that is a LIMIT BUY order with price of $19,000, but the quantity is less than minQty in the LOT_SIZE:
0.000005 < 0.00001000
then the server will reject the order, because the request can't pass this filter validation.
✗ LOT_SIZE.minQty
stepSize
Can I place an order with the same parameters but only change the quantity to 0.000015? That is:
price=19000
side=BUY
type=LIMIT
quantity=0.000015
You will still receive this error, because the quantity is not able to pass the stepSize size validation: (quantity- minQty) % stepSize == 0
(0.000015 - 0.00001) % 0.00001 != 0
✓ LOT_SIZE.minQty
✗ LOT_SIZE.stepSize
MIN_NOTIONAL Validation
Alright, let us change the quantity to 0.00002, with same parameters:
price=19000
side=BUY
type=LIMIT
quantity=0.00002
The order will still be rejected with a different error because it can't pass the filter MIN_NOTIONAL validation.
19000 x 0.00002 = 0.38 < 10 (MIN_NOTIONAL.minNotional)
Note:
minNotional defines the minimum notional value that required for each order.
For MARKET order, the average price is used over the last avgPriceMins minutes.
✓ LOT_SIZE.minQty
✓ LOT_SIZE.stepSize
✗ MIN_NOTIONAL.minNotional
Here is some code.
def round_down(self, coin, number):
info = self.client.get_symbol_info('%sUSDT' % coin)
step_size = [float(_['stepSize']) for _ in info['filters'] if _['filterType'] == 'LOT_SIZE'][0]
step_size = '%.8f' % step_size
step_size = step_size.rstrip('0')
decimals = len(step_size.split('.')[1])
return math.floor(number * 10 ** decimals) / 10 ** decimals
https://python-binance.readthedocs.io/en/latest/account.html
from binance.helpers import round_step_size
# to get a lot size
def getLotSize(self):
info = self.apiCall(lambda: self.client.get_symbol_info(self.pair))
lotSize = float(info['filters'][2]['minQty'])
return lotSize
# get ceiling value and correct format for a lot size
def getCeilingVal(self):
pairData = self.apiCall(lambda:
self.client.get_symbol_ticker(symbol=self.pair))
pairPrice = pairData["price"]
ceilingVal = float(self.dInv) / float(pairPrice)
aLotSize = self.getLotSize()
rounded_amount = round_step_size(ceilingVal, aLotSize)
return rounded_amount
Here's a very helpful code using binance-python package
...
// Full code: https://github.com/ndiecodes/binance-trading-bot/blob/main/main.py
def get_round_step_quantity(self, qty):
info = self.client.get_symbol_info(Config.TRADESYMBOL)
for x in info["filters"]:
if x["filterType"] == "LOT_SIZE":
self.minQty = float(x["minQty"])
self.maxQty = float(x["maxQty"])
self.stepSize= float(x["stepSize"])
if qty < self.minQty:
qty = self.minQty
return round_step_size(quantity=qty, step_size=self.stepSize)
I have read through all of these forum questions and no one has mentioned the fact that Binance charges a 0.1% fee on all transactions. Meaning you do not have your original buying quantity available to sell back when the sell is triggered.
I have attempted to solve this with:
buy_quantity = round(buy_amount * 0.999, len(str(lotsize).split('.')[1]))
Multiplying my original purchase quantity by 0.999 should reduce it by the amount needed to be able to sell it back.
Hi adding a bit further to #stack if I've 20 dollars to buy then my quantity would be as below
I've done like below
decimal_places=abs(Decimal(symbl_info['filters'][2]["stepSize"]).normalize().as_tuple().exponent)
print("DECIMAL PLACES {0}".format(decimal_places))
buy_qauntity= round((20/order_input["askPrice"].values[0]),decimal_places)
print(buy_qauntity)
I write a function like that. It's working for me.
def getPriceLotFormat(self, priceOrg, quantityOrg):
price = float(priceOrg)
quantity = float(quantityOrg)
response = self.get_symbol_info(car.pair) #self is client btw
priceFilterFloat = format(float(response["filters"][0]["tickSize"]), '.20f')
lotSizeFloat = format(float(response["filters"][2]["stepSize"]), '.20f')
# PriceFilter
numberAfterDot = str(priceFilterFloat.split(".")[1])
indexOfOne = numberAfterDot.find("1")
if indexOfOne == -1:
price = int(price)
else:
price = round(float(price), int(indexOfOne - 1))
# LotSize
numberAfterDotLot = str(lotSizeFloat.split(".")[1])
indexOfOneLot = numberAfterDotLot.find("1")
if indexOfOneLot == -1:
quantity = int(quantity)
else:
quantity = round(float(quantity), int(indexOfOneLot))
print(f"""
##### SELL #####
Pair : {str(car.pair)}
Cash : {str(car.price)}
Quantity : {str(car.quantity)}
Price : {str(car.price)}
""")
We can use the Log10 function to get rounding precision from the Binance /api/v3/exchangeinfo endpoint data.
CurrencyRoundNum = int(math.Abs(math.Log10(stepSize)))
PriceRoundNum = int(math.Abs(math.Log10(tickSize)))
The full version on golang is here, or at go playground. I'm sorry that code is not on python.
So I was struggling with the LOT_SIZE error myself.
Previously I was using the round_step_size function from the python-binance library, however, I had to edit this function to deal with this API error.
Here is a function that I use:
from decimal import Decimal, ROUND_DOWN
import math
from typing import Union
def round_step_size(quantity: Union[float, Decimal], step_size: Union[float, Decimal]) -> float:
if step_size == 1.0:
return math.floor(quantity)
elif step_size < 1.0:
return Decimal(f'{quantity}').quantize(Decimal(f'{step_size}'), rounding=ROUND_DOWN)
I would like to get whole trade history from Poloniex about BTC to USD in Python.
I have entered my key and secret.
I have got the code like below:
import urllib
import urllib2
import json
import time
import hmac,hashlib
def createTimeStamp(datestr, format="%Y-%m-%d %H:%M:%S"):
return time.mktime(time.strptime(datestr, format))
class poloniex:
def __init__(self, APIKey, Secret):
self.APIKey = APIKey
self.Secret = Secret
def post_process(self, before):
after = before
# Add timestamps if there isnt one but is a datetime
if('return' in after):
if(isinstance(after['return'], list)):
for x in xrange(0, len(after['return'])):
if(isinstance(after['return'][x], dict)):
if('datetime' in after['return'][x] and 'timestamp' not in after['return'][x]):
after['return'][x]['timestamp'] = float(createTimeStamp(after['return'][x]['datetime']))
return after
def api_query(self, command, req={}):
if(command == "returnTicker" or command == "return24Volume"):
ret = urllib2.urlopen(urllib2.Request('https://poloniex.com/public?command=' + command))
return json.loads(ret.read())
elif(command == "returnOrderBook"):
ret = urllib2.urlopen(urllib2.Request('https://poloniex.com/public?command=' + command + '¤cyPair=' + str(req['currencyPair'])))
return json.loads(ret.read())
elif(command == "returnMarketTradeHistory"):
ret = urllib2.urlopen(urllib2.Request('https://poloniex.com/public?command=' + "returnTradeHistory" + '¤cyPair=' + str(req['currencyPair'])))
return json.loads(ret.read())
else:
req['command'] = command
req['nonce'] = int(time.time()*1000)
post_data = urllib.urlencode(req)
sign = hmac.new(self.Secret, post_data, hashlib.sha512).hexdigest()
headers = {
'Sign': sign,
'Key': self.APIKey
}
ret = urllib2.urlopen(urllib2.Request('https://poloniex.com/tradingApi', post_data, headers))
jsonRet = json.loads(ret.read())
return self.post_process(jsonRet)
def returnTicker(self):
return self.api_query("returnTicker")
def return24Volume(self):
return self.api_query("return24Volume")
def returnOrderBook (self, currencyPair):
return self.api_query("returnOrderBook", {'currencyPair': currencyPair})
def returnMarketTradeHistory (self, currencyPair):
return self.api_query("returnMarketTradeHistory", {'currencyPair': currencyPair})
# Returns all of your balances.
# Outputs:
# {"BTC":"0.59098578","LTC":"3.31117268", ... }
def returnBalances(self):
return self.api_query('returnBalances')
# Returns your open orders for a given market, specified by the "currencyPair" POST parameter, e.g. "BTC_XCP"
# Inputs:
# currencyPair The currency pair e.g. "BTC_XCP"
# Outputs:
# orderNumber The order number
# type sell or buy
# rate Price the order is selling or buying at
# Amount Quantity of order
# total Total value of order (price * quantity)
def returnOpenOrders(self,currencyPair):
return self.api_query('returnOpenOrders',{"currencyPair":currencyPair})
# Returns your trade history for a given market, specified by the "currencyPair" POST parameter
# Inputs:
# currencyPair The currency pair e.g. "BTC_XCP"
# Outputs:
# date Date in the form: "2014-02-19 03:44:59"
# rate Price the order is selling or buying at
# amount Quantity of order
# total Total value of order (price * quantity)
# type sell or buy
def returnTradeHistory(self,currencyPair):
return self.api_query('returnTradeHistory',{"currencyPair":currencyPair})
# Places a buy order in a given market. Required POST parameters are "currencyPair", "rate", and "amount". If successful, the method will return the order number.
# Inputs:
# currencyPair The curreny pair
# rate price the order is buying at
# amount Amount of coins to buy
# Outputs:
# orderNumber The order number
def buy(self,currencyPair,rate,amount):
return self.api_query('buy',{"currencyPair":currencyPair,"rate":rate,"amount":amount})
# Places a sell order in a given market. Required POST parameters are "currencyPair", "rate", and "amount". If successful, the method will return the order number.
# Inputs:
# currencyPair The curreny pair
# rate price the order is selling at
# amount Amount of coins to sell
# Outputs:
# orderNumber The order number
def sell(self,currencyPair,rate,amount):
return self.api_query('sell',{"currencyPair":currencyPair,"rate":rate,"amount":amount})
# Cancels an order you have placed in a given market. Required POST parameters are "currencyPair" and "orderNumber".
# Inputs:
# currencyPair The curreny pair
# orderNumber The order number to cancel
# Outputs:
# succes 1 or 0
def cancel(self,currencyPair,orderNumber):
return self.api_query('cancelOrder',{"currencyPair":currencyPair,"orderNumber":orderNumber})
# Immediately places a withdrawal for a given currency, with no email confirmation. In order to use this method, the withdrawal privilege must be enabled for your API key. Required POST parameters are "currency", "amount", and "address". Sample output: {"response":"Withdrew 2398 NXT."}
# Inputs:
# currency The currency to withdraw
# amount The amount of this coin to withdraw
# address The withdrawal address
# Outputs:
# response Text containing message about the withdrawal
def withdraw(self, currency, amount, address):
return self.api_query('withdraw',{"currency":currency, "amount":amount, "address":address})
polo = poloniex('my_key', 'my_security')
print(polo.returnTradeHistory('BTC_ETH'))
#print(polo.returnTradeHistory('BTC_USDT))
I have used method like:
print(polo.returnTradeHistory('BTC_ETH'))
but I get empty array [], I don't know why?
Could you also tell me how can I get this trade history and get info about BTC to USD, because something like BTC_USD hasn't worked.
Make sure you can open the returnTradeHistory-call with your browser (https://poloniex.com/public?command=returnTradeHistory¤cyPair=BTC_ETH)
If your browser shows you the recent trade history, everything is fine. If you need to complete a captcha, your IP address is blocked/marked. If you need to complete the captcha everytime opening the site, you need to contact support.
Poloniex does not support exchanging cryptocurrencies to fiat money, therefore you are not able to find a direct exchange for something like BTC_USD. Youi'll need to get the exchange ratio from another site.
The function your are using (returnTradeHistory) returns your personal history. If you haven't traded anything yet, it will be empty. If you want to get the global trade history, you need to use returnMarketTradeHistory