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