first commit
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,25 @@
|
||||
# account details for export
|
||||
|
||||
from oandapyV20 import API
|
||||
from oandapyV20.endpoints.accounts import AccountSummary
|
||||
from .config import accountID, token
|
||||
|
||||
api = API(token)
|
||||
|
||||
r = AccountSummary(accountID)
|
||||
summary = api.request(r) # base dict
|
||||
account = summary['account'] # item containing dict of account data
|
||||
|
||||
account_summary = dict()
|
||||
|
||||
balance = account['balance']
|
||||
open_trades = account['openTradeCount']
|
||||
open_positions = account['openPositionCount']
|
||||
pnl = account['pl']
|
||||
carrying_costs = account['financing']
|
||||
open_pnl = account['unrealizedPL']
|
||||
nav = account['NAV']
|
||||
margin_used = account['marginUsed']
|
||||
margin_available = account['marginAvailable']
|
||||
margin_call_pct = account['marginCallPercent']
|
||||
margin_rate = account['marginRate']
|
||||
@@ -0,0 +1,20 @@
|
||||
# contains settings and common lists of assets to trade
|
||||
|
||||
# basic account/environment details
|
||||
accountID = '101-011-4913967-001'
|
||||
token = '88899e549cd4edf80ddcf7e4f8a57f60-f7067b6e2e3c2ef5ba5de3116e7ae5e2'
|
||||
env = 'practice' # change this to 'live' when you're ready
|
||||
|
||||
# major portfolios
|
||||
|
||||
currencies = ['EUR_USD', 'GBP_USD', 'USD_JPY', 'AUD_USD', 'NZD_USD',
|
||||
'USD_CHF', 'USD_CAD', 'XAU_USD', 'AUD_JPY', 'EUR_JPY',
|
||||
'GBP_JPY']
|
||||
|
||||
indicies = ['SPX500_USD', 'AU200_AUD', 'CN50_USD', 'EU50_EUR', 'FR40_EUR',
|
||||
'DE30_EUR', 'HK33_HKD', 'IN50_USD', 'JP225_USD', 'NL25_EUR',
|
||||
'SG30_SGD', 'TWIX_USD', 'UK100_GBP', 'US30_USD', 'NAS100_USD',
|
||||
'US2000_USD']
|
||||
|
||||
commodities = ['BCO_USD', 'XCU_USD', 'CORN_USD', 'NATGAS_USD', 'SOYBN_USD',
|
||||
'SUGAR_USD', 'WTICO_USD', 'WHEAT_USD']
|
||||
@@ -0,0 +1,112 @@
|
||||
# short list of trading indicators
|
||||
import numpy as np
|
||||
import pandas as pd
|
||||
from sklearn import ensemble, tree
|
||||
from sklearn.model_selection import train_test_split
|
||||
|
||||
def sma(series, window):
|
||||
mavg = series.rolling(window=window, min_periods=window).mean()
|
||||
return mavg
|
||||
|
||||
# exponential weighted moving average
|
||||
def ewma(series, span):
|
||||
ema = pd.ewma(series, span=span)
|
||||
return ema
|
||||
|
||||
def pivotPoints(df):
|
||||
n = len(df) - 1 # pivotPoints would be based on the last candle
|
||||
pp = (df['High'] + df['Low'] + df['Close']) / 3
|
||||
r1 = (2 * pp) - df['Low']
|
||||
s1 = (2 * pp) - df['High']
|
||||
r2 = (pp - s1) + r1
|
||||
s2 = pp - (r1 - s1)
|
||||
r3 = (pp - s2) + r2
|
||||
s3 = pp - (r2 - s2)
|
||||
|
||||
pivots = {'PP': pp, 'R1': r1, 'R2': r2, 'R3': r3,
|
||||
'S1': s1, 'S2': s2, 'S3': s3}
|
||||
|
||||
return pivots
|
||||
|
||||
# rate of change, applied directly to the dataframe
|
||||
def roc(df):
|
||||
closes = df['Close'].apply(float)
|
||||
df['ROC'] = closes.diff() * 100
|
||||
df['ROC'].fillna(0)
|
||||
return df
|
||||
|
||||
# stochastic oscillator, applied directly to the dataframe
|
||||
def stoch(df, period_K, period_D, graph=False):
|
||||
df['Low'] = pd.to_numeric(df['Low'], errors='coerce')
|
||||
df['Lstoch'] = df['Low'].rolling(window=period_K).min()
|
||||
df['High'] = pd.to_numeric(df['High'], errors='coerce')
|
||||
df['Hstoch'] = df['High'].rolling(window=period_K).max()
|
||||
df['Close'] = pd.to_numeric(df['Close'], errors='coerce')
|
||||
df['%K'] = 100*((df['Close'] - df['Lstoch']) / (df['Hstoch'] - df['Lstoch']))
|
||||
df['%D'] = df['%K'].rolling(window=period_D).mean()
|
||||
|
||||
if graph == True:
|
||||
fig, axes = plt.subplots(nrows=2, ncols=1, figsize=(20,10))
|
||||
df['Close'].plot(ax=axes[0])#, title='Close'
|
||||
df[['K', 'D']].plot(ax=axes[1])#, title='Oscillator'
|
||||
plt.show()
|
||||
|
||||
return df
|
||||
|
||||
# bollinger bands, applied directly to the dataframe
|
||||
def bollBands(df, window, n_std, graph=False):
|
||||
close = df['Close']
|
||||
rolling_mean = close.rolling(window).mean()
|
||||
rolling_std = close.rolling(window).std()
|
||||
|
||||
df['rolling_mean'] = rolling_mean
|
||||
df['boll_high'] = rolling_mean + (rolling_std * n_std)
|
||||
df['boll_low'] = rolling_mean - (rolling_std * n_std)
|
||||
|
||||
if graph == True:
|
||||
plt.plot(close)
|
||||
plt.plot(df['Rolling Mean'])
|
||||
plt.plot(df['Bollinger High'])
|
||||
plt.plot(df['Bollinger Low'])
|
||||
plt.show()
|
||||
|
||||
return df
|
||||
|
||||
# AdaBoostRegressor with Decision Tree base, uses most of the standard df
|
||||
def AdaBoost(df):
|
||||
# clean the data
|
||||
n = len(df)
|
||||
X = np.asarray(df[['Open','High','Low','Volume']][:n-1]) # add or subtract input data columns here
|
||||
X = X.reshape(n-1, 4) # adjust '4' to match the number of input columns used above
|
||||
y = np.asarray(df[['Close']][1:])
|
||||
# build and score the model
|
||||
split = 0.8
|
||||
X_train, X_test, y_train, y_test = train_test_split(X, y, train_size=split)
|
||||
dtree = tree.DecisionTreeRegressor(max_depth=1000)
|
||||
model = ensemble.AdaBoostRegressor(n_estimators=5000, learning_rate=2.0, base_estimator=dtree)
|
||||
model.fit(X_train, y_train)
|
||||
score = model.score(X_test, y_test)
|
||||
#print("Model1 accuracy: ", score)
|
||||
# make a prediction
|
||||
prediction = model.predict(df[['Open','High','Low','Volume']][n-1:])
|
||||
#print("AdaBoost predicted close for next candle: ", prediction)
|
||||
return prediction
|
||||
|
||||
# RandomForestRegressor with Decision Tree base, uses most of the standard df
|
||||
def RandomForest(df):
|
||||
# clean the data
|
||||
n = len(df)
|
||||
X = np.asarray(df[['Open','High','Low','Volume']][:n-1]) # add or subtract input data columns here
|
||||
X = X.reshape(n-1, 4) # adjust '4' to match the number of input columns used above
|
||||
y = np.asarray(df[['Close']][1:])
|
||||
# build and score the model
|
||||
split = 0.8
|
||||
X_train, X_test, y_train, y_test = train_test_split(X, y, train_size=split)
|
||||
model = ensemble.RandomForestRegressor(n_estimators=10000, max_depth=1000)
|
||||
model.fit(X_train, y_train)
|
||||
score = model.score(X_test, y_test)
|
||||
#print("Model2 accuracy: ", score)
|
||||
# make a prediction
|
||||
prediction = model.predict(df[['Open','High','Low','Volume']][n-1:])
|
||||
#print("RandomForest predicted close for next candle: ", prediction)
|
||||
return prediction
|
||||
@@ -0,0 +1,77 @@
|
||||
# class to support opening and closing trades
|
||||
import json
|
||||
from .config import accountID, token
|
||||
from oandapyV20 import API
|
||||
import oandapyV20.endpoints.trades as trades
|
||||
import oandapyV20.endpoints.orders as orders
|
||||
from oandapyV20.contrib.requests import TradeCloseRequest
|
||||
from oandapyV20.exceptions import V20Error
|
||||
from .account import margin_available, margin_rate
|
||||
from oandapyV20.contrib.requests import (MarketOrderRequest,
|
||||
TakeProfitDetails,
|
||||
StopLossDetails,
|
||||
TrailingStopLossOrderRequest)
|
||||
|
||||
api = API(token)
|
||||
|
||||
def weight(price, allocation):
|
||||
trade_margin = float(margin_available) * allocation
|
||||
trade_value = trade_margin / float(margin_rate)
|
||||
w = round((trade_value/float(price)), 0)
|
||||
return w
|
||||
|
||||
def order(instrument, weight, price, TP, SL):
|
||||
|
||||
if weight > 0:
|
||||
mktOrder = MarketOrderRequest(
|
||||
instrument=instrument,
|
||||
units=weight,
|
||||
takeProfitOnFill=TakeProfitDetails(price=TP).data,
|
||||
stopLossOnFill=StopLossDetails(price=SL).data)
|
||||
r = orders.OrderCreate(accountID, data=mktOrder.data)
|
||||
|
||||
try:
|
||||
rv = api.request(r)
|
||||
#print(r.status_code)
|
||||
except V20Error as e:
|
||||
print(r.status_code, e)
|
||||
else:
|
||||
#print(json.dumps(rv, indent=4))
|
||||
pass
|
||||
|
||||
else:
|
||||
mktOrder = MarketOrderRequest(
|
||||
instrument=instrument,
|
||||
units=weight,
|
||||
takeProfitOnFill=TakeProfitDetails(price=TP).data,
|
||||
stopLossOnFill=StopLossDetails(price=SL).data)
|
||||
r = orders.OrderCreate(accountID, data=mktOrder.data)
|
||||
|
||||
try:
|
||||
rv = api.request(r)
|
||||
#print(r.status_code)
|
||||
except V20Error as e:
|
||||
print(r.status_code, e)
|
||||
else:
|
||||
#print(json.dumps(rv, indent=4))
|
||||
pass
|
||||
|
||||
return r.response
|
||||
|
||||
def trailingStop(tradeID, distance=0.1):
|
||||
activeStop = TrailingStopLossOrderRequest(tradeID=tradeID,
|
||||
r = orders.OrderCreate(accountID,
|
||||
data=activeStop.data))
|
||||
api.request(r)
|
||||
return r.response
|
||||
|
||||
def close(tradeID):
|
||||
close_trade = TradeCloseRequest()
|
||||
r = trades.TradeClose(accountID, tradeID, data=close_trade.data)
|
||||
api.request(r)
|
||||
return r.response
|
||||
|
||||
def closeAll(tradeID_list):
|
||||
for trade in tradeID_list:
|
||||
close(trade)
|
||||
print(trade, "Closed")
|
||||
@@ -0,0 +1,57 @@
|
||||
# price history or stream functions
|
||||
|
||||
from .config import token, accountID, env
|
||||
from oandapyV20 import API
|
||||
from oandapyV20.endpoints.instruments import InstrumentsCandles
|
||||
from oandapyV20.endpoints.pricing import PricingStream
|
||||
import pandas as pd
|
||||
import time
|
||||
|
||||
api = API(token)
|
||||
|
||||
# returns the last 500 OHLCV candles for an instrument
|
||||
# maximum count is 500
|
||||
# window: M1, M5, M15, H, H4, D, etc.
|
||||
def history(instrument, window, collection=False):
|
||||
instrument = instrument
|
||||
data = list()
|
||||
client = API(token)
|
||||
params = {"count": 500, "granularity": window}
|
||||
r = InstrumentsCandles(instrument, params)
|
||||
client.request(r)
|
||||
resp = r.response
|
||||
for candle in resp.get('candles'):
|
||||
dt = candle['time']
|
||||
Open = candle['mid']['o']
|
||||
High = candle['mid']['h']
|
||||
Low = candle['mid']['l']
|
||||
Close = candle['mid']['c']
|
||||
Volume = candle['volume']
|
||||
update = [dt, Open, High, Low, Close, Volume]
|
||||
data.append(update)
|
||||
df = pd.DataFrame(data, columns=['dt','Open','High','Low','Close','Volume'])
|
||||
# collect data, useful for research and weekends/holidays when the market isn't open
|
||||
if collection == True:
|
||||
title = 'data/%s_%s_history.csv' % (instrument, window)
|
||||
df.to_csv(title)
|
||||
|
||||
return df
|
||||
|
||||
# creates a pricing stream,
|
||||
def stream(instrument, window):
|
||||
request_params = {"timeout":100}
|
||||
params = {"instruments":instrument, "granularity":window}
|
||||
api = API(access_token=token,environment=env, request_params=request_params)
|
||||
r = PricingStream(accountID=accountID, params=params)
|
||||
|
||||
while True:
|
||||
try:
|
||||
api.request(r)
|
||||
for R in r.response:
|
||||
time = R['time']
|
||||
ask = R['asks'][0]['price']
|
||||
bid = R['bids'][0]['price']
|
||||
return time, ask, bid
|
||||
except Exception as e:
|
||||
print(e)
|
||||
continue
|
||||
@@ -0,0 +1,51 @@
|
||||
"""
|
||||
script that runs continuously and collects pricing and technical indicators data,
|
||||
entering the data into instrument/window data tables.
|
||||
"""
|
||||
import sqlite3
|
||||
import sqlalchemy
|
||||
import pandas as pd
|
||||
from datetime import datetime
|
||||
from backend.pricing import history
|
||||
from backend.config import currencies
|
||||
from backend.indicators import sma, stoch, pivotPoints, bollBands
|
||||
|
||||
|
||||
windows = ['M5', 'M15', 'H1', 'H4', 'D']
|
||||
for instr in currencies:
|
||||
for w in windows:
|
||||
LiteCurrencyDB(instr, w)
|
||||
|
||||
def LiteCurrencyDB(instr, w):
|
||||
# connect to the DB
|
||||
db = sqlite3.connect('liteDB/currencies.db')
|
||||
c = db.cursor()
|
||||
table_name = "%s_%s" % (instr, w)
|
||||
# get last 500 data points
|
||||
df = history(instr, w)
|
||||
prices = df['Close']
|
||||
# set the dataframe with our technical indicators
|
||||
df['fast_sma'] = sma(prices, 6)
|
||||
df['slow_sma'] = sma(prices, 10)
|
||||
df = stoch(df, 6, 3)
|
||||
df = bollBands(df, 5, 0.5)
|
||||
pp = pd.DataFrame(data=pivotPoints(df))
|
||||
df = pd.concat([df,pp], axis=1, join_axes=[df.index])
|
||||
inputs = list(tuple(row for idx, row in df.iterrows()))
|
||||
# insert them into the dedicated table for this currency and timeframe
|
||||
c.execute('''CREATE TABLE IF NOT EXISTS {}(
|
||||
dt TEXT, Open REAL, High REAL, Low REAL, Close REAL,
|
||||
Volume INTEGER, fast_sma REAL, slow_sma REAL, Lstoch REAL,
|
||||
Hstoch REAL, K REAL, D REAL, rolling_mean REAL, boll_high REAL,
|
||||
boll_low REAL, PP REAL, R1 REAL, R2 REAL, R3 REAL, S1 REAL,
|
||||
S2 REAL, S3 REAL
|
||||
)'''.format(table_name))
|
||||
c.executemany('''INSERT INTO {}(
|
||||
dt, Open, High, Low, Close, Volume, fast_sma, slow_sma, Lstoch,
|
||||
Hstoch, K, D, rolling_mean, boll_high, boll_low, PP, R1, R2, R3,
|
||||
S1, S2, S3
|
||||
) VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)'''
|
||||
.format(table_name), inputs)
|
||||
db.commit()
|
||||
print('table created successfully')
|
||||
return db, df
|
||||
Binary file not shown.
Reference in New Issue
Block a user