├── README.md └── p_ig_TEST - Copy.py /README.md: -------------------------------------------------------------------------------- 1 | # IG-Index-Scalping-Scraping-Bot 2 | IG Index Scalping/Scraping Bot, Written in Python3/Cross Platform/REST API 3 | 4 | 5 | Discussion here - https://www.reddit.com/r/UKInvesting/comments/7lx03l/python_ig_index_bot/ 6 | 7 | USE AT YOUR OWN RISK!!! 8 | 9 | Thing's to note. 10 | 11 | This has been "Hacked" to work on Spot Gold, It have been tested on Bitcoin and because of the massive swings it is highly profitable. Not sure about Spot Gold, However I wanted to use it with something that has "Low Barriers to entry" Bitcoin and IG index, Well frequently they disable Buying etc and the margin's required and spread's are horrendous (Not limited to IG though so not their fault). This is meant to be for beginners so you can invest a small amount and grow it over time. 12 | 13 | I wrote this in Notepad++, I am telling you this because It nicely shows the line numbers so ask if you have a query about a particular bit. Plus it's nice to format code and commenting and commenting stuff is a doddle. 14 | 15 | https://notepad-plus-plus.org/ 16 | 17 | The code is here, It will output some debugging stuff to the console currently. 18 | 19 | Line(s) 28/39 - Change your Username/Password and API Key and if you want to use Real money (YOUR OWN RISK!!) or DEMO. 20 | 21 | https://labs.ig.com/faq 22 | 23 | Line 327 - This is how far to look back to get an idea of market direction. You can change this, I use 2 hours, I have tested it as high as 3 hours and as low as a minute (Which is pretty useless). 24 | 25 | 26 | Donate with PayPal 27 | 28 | 29 | Bitcoin Cash (BCH) - qpz32c4lg7x7lnk9jg6qg7s4uavdce89myax5v5nuk 30 | 31 | Ether (ETH) - 0x843d3DEC2A4705BD4f45F674F641cE2D0022c9FB 32 | 33 | Litecoin (LTC) - Lfk5y4F7KZa9oRxpazETwjQnHszEPvqPvu 34 | 35 | Bitcoin (BTC) - 14Dm7L3ABPtumPDcj3REAvs4L6w9YFRnHK 36 | -------------------------------------------------------------------------------- /p_ig_TEST - Copy.py: -------------------------------------------------------------------------------- 1 | '''THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 2 | OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 3 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND 4 | NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE 5 | DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, 6 | WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 7 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 8 | SOFTWARE.''' 9 | 10 | # Bitcoin Cash (BCH) qpz32c4lg7x7lnk9jg6qg7s4uavdce89myax5v5nuk 11 | # Ether (ETH) - 0x843d3DEC2A4705BD4f45F674F641cE2D0022c9FB 12 | # Litecoin (LTC) - Lfk5y4F7KZa9oRxpazETwjQnHszEPvqPvu 13 | # Bitcoin (BTC) - 34L8qWiQyKr8k4TnHDacfjbaSqQASbBtTd 14 | 15 | # contact :- github@jamessawyer.co.uk 16 | 17 | 18 | 19 | #IF YOU FOUND THIS USEFUL, Please Donate some Bitcoin .... 1FWt366i5PdrxCC6ydyhD8iywUHQ2C7BWC 20 | #More Info here :-https://github.com/tg12/IG-Index-Scalping-Scraping-Bot 21 | #And here :- https://www.reddit.com/r/UKInvesting/comments/7lx03l/python_ig_index_bot/ 22 | 23 | #!/usr/bin/env python 24 | # -*- coding: utf-8 -*- 25 | import time 26 | import datetime 27 | import requests 28 | import json 29 | import logging 30 | import sys 31 | import urllib 32 | from time import time, sleep 33 | import random 34 | import time as systime 35 | from statistics import mean, median 36 | 37 | 38 | #Joke here 39 | #REAL_OR_NO_REAL = 'https://api.ig.com/gateway/deal' 40 | REAL_OR_NO_REAL = 'https://demo-api.ig.com/gateway/deal' 41 | 42 | API_ENDPOINT = "https://demo-api.ig.com/gateway/deal/session" 43 | API_KEY = '*****************************' 44 | data = {"identifier":"****************","password": "****************"} 45 | 46 | # FOR REAL.... 47 | # API_ENDPOINT = "https://api.ig.com/gateway/deal/session" 48 | # API_KEY = '********************************************' 49 | # data = {"identifier":"**************************","password": "***************************"} 50 | 51 | headers = {'Content-Type':'application/json; charset=utf-8', 52 | 'Accept':'application/json; charset=utf-8', 53 | 'X-IG-API-KEY':API_KEY, 54 | 'Version':'2' 55 | } 56 | 57 | r = requests.post(API_ENDPOINT, data=json.dumps(data), headers=headers) 58 | 59 | headers_json = dict(r.headers) 60 | CST_token = headers_json["CST"] 61 | print (R"CST : " + CST_token) 62 | x_sec_token = headers_json["X-SECURITY-TOKEN"] 63 | print (R"X-SECURITY-TOKEN : " + x_sec_token) 64 | 65 | #GET ACCOUNTS 66 | base_url = REAL_OR_NO_REAL + '/accounts' 67 | authenticated_headers = {'Content-Type':'application/json; charset=utf-8', 68 | 'Accept':'application/json; charset=utf-8', 69 | 'X-IG-API-KEY':API_KEY, 70 | 'CST':CST_token, 71 | 'X-SECURITY-TOKEN':x_sec_token} 72 | 73 | auth_r = requests.get(base_url, headers=authenticated_headers) 74 | d = json.loads(auth_r.text) 75 | 76 | # print(auth_r.status_code) 77 | # print(auth_r.reason) 78 | # print (auth_r.text) 79 | 80 | for i in d['accounts']: 81 | if str(i['accountType']) == "SPREADBET": 82 | print ("Spreadbet Account ID is : " + str(i['accountId'])) 83 | spreadbet_acc_id = str(i['accountId']) 84 | 85 | #SET SPREAD BET ACCOUNT AS DEFAULT 86 | base_url = REAL_OR_NO_REAL + '/session' 87 | data = {"accountId":spreadbet_acc_id,"defaultAccount": "True"} 88 | auth_r = requests.put(base_url, data=json.dumps(data), headers=authenticated_headers) 89 | 90 | # print(auth_r.status_code) 91 | # print(auth_r.reason) 92 | # print (auth_r.text) 93 | #ERROR about account ID been the same, Ignore! 94 | 95 | #DOW RALLY EVERYDAY AT 20:40 - 21:00GMT 96 | now = datetime.datetime.now() 97 | now_time = now.time() 98 | 99 | #-------------THIS NEEDS CHANGING AT SOME POINT--------------------------- 100 | #-------------THIS NEEDS CHANGING AT SOME POINT--------------------------- 101 | #-------------THIS NEEDS CHANGING AT SOME POINT--------------------------- 102 | #-------------THIS NEEDS CHANGING AT SOME POINT--------------------------- 103 | #-------------THIS NEEDS CHANGING AT SOME POINT--------------------------- 104 | 105 | # if now_time >= datetime.time(5,30) and now_time <= datetime.time(16,30): # Day Trading 106 | # print ("CS.D.GBPUSD.TODAY.IP") 107 | # epic_id = "CS.D.GBPUSD.TODAY.IP" 108 | # elif now_time >= datetime.time(23,30) and now_time <= datetime.time(5,29): #Overnight 109 | # print ("CS.D.USCGC.TODAY.IP") 110 | # epic_id = "CS.D.USCGC.TODAY.IP" 111 | # elif now_time >= datetime.time(18,30) and now_time <= datetime.time(20,30): #Wall Street 112 | # print ("IX.D.DOW.DAILY.IP") 113 | # epic_id = "IX.D.DOW.DAILY.IP" 114 | # else: 115 | # print ("DEFAULT/NO TRADE") 116 | # epic_id = "CS.D.USCSI.TODAY.IP" 117 | 118 | #HACKY/Weekend Testing - DO NOT USE!!! UNLESS YOU KNOW WHAT YOU ARE DOING!! 119 | #epic_id = "CS.D.BITCOIN.TODAY.IP" #Bitcoin 120 | #epic_id = "IX.D.SUNFUN.DAILY.IP" #Weekend Trading 121 | #epic_id = "CS.D.ETHUSD.TODAY.IP" #Ether 122 | #epic_id = "CS.D.BCHUSD.TODAY.IP" #Bitcoin Cash 123 | 124 | #LIVE TEST 125 | #epic_id = "CS.D.USCGC.TODAY.IP" #Gold - OK, Not Great 126 | #epic_id = "CS.D.USCSI.TODAY.IP" #Silver - NOT RECOMMENDED 127 | #epic_id = "IX.D.FTSE.DAILY.IP" #FTSE 100 - Within Hours only, Profitable 128 | #epic_id = "IX.D.DOW.DAILY.IP" #Wall St - Definately Profitable between half 6 and half 8 GMT 129 | epic_id = "CS.D.GBPUSD.TODAY.IP" # - Very Profitable 130 | 131 | # PROGRAMMABLE VALUES 132 | # UNIT TEST FOR CRYPTO'S 133 | # limitDistance_value = "1" 134 | # orderType_value = "MARKET" 135 | # size_value = "5" 136 | # expiry_value = "DFB" 137 | # guaranteedStop_value = True 138 | # currencyCode_value = "GBP" 139 | # forceOpen_value = True 140 | # stopDistance_value = "250" 141 | 142 | #UNIT TEST FOR OTHER STUFF 143 | limitDistance_value = "1" 144 | orderType_value = "MARKET" 145 | size_value = "1" 146 | expiry_value = "DFB" 147 | guaranteedStop_value = True 148 | currencyCode_value = "GBP" 149 | forceOpen_value = True 150 | stopDistance_value = "20" #Initial Stop loss, Worked out later per trade 151 | 152 | base_url = REAL_OR_NO_REAL + '/markets/' + epic_id 153 | auth_r = requests.get(base_url, headers=authenticated_headers) 154 | d = json.loads(auth_r.text) 155 | 156 | #DEBUG 157 | # print(auth_r.status_code) 158 | # print(auth_r.reason) 159 | # print (auth_r.text) 160 | 161 | MARKET_ID = d['instrument']['marketId'] 162 | 163 | #******************************************************************* 164 | #******************************************************************* 165 | #******************************************************************* 166 | #******************************************************************* 167 | 168 | # #Calculate average number of pips moved per hour and take an average 169 | # #Do this on an 24 hour basis once?? OR Do it each time?? 170 | 171 | # price_list = [] 172 | # base_url = REAL_OR_NO_REAL + '/prices/'+ epic_id + '/HOUR_4/3' 173 | # # Price resolution (MINUTE, MINUTE_2, MINUTE_3, MINUTE_5, MINUTE_10, MINUTE_15, MINUTE_30, HOUR, HOUR_2, HOUR_3, HOUR_4, DAY, WEEK, MONTH) 174 | # auth_r = requests.get(base_url, headers=authenticated_headers) 175 | # d = json.loads(auth_r.text) 176 | 177 | # # print ("-----------------DEBUG-----------------") 178 | # # print(auth_r.status_code) 179 | # # print(auth_r.reason) 180 | # # print (auth_r.text) 181 | # # print ("-----------------DEBUG-----------------") 182 | 183 | # for i in d['prices']: 184 | # ask_price = i['closePrice']['ask'] 185 | # price_list.append(float(ask_price)) 186 | 187 | # avg_diff = [price_list[i+1]-price_list[i] for i in range(len(price_list)-1)] 188 | # #DEBUG 189 | # print ("AVG PIP MOVEMENT FOR EACH HOUR " + str(avg_diff)) 190 | # print ("--------------------------------------------------") 191 | # print ("--------------------------------------------------") 192 | # print ("--------------------------------------------------") 193 | # print ("MAX PIP MOVEMENT IN 24 HOURS : " + str(max(avg_diff))) 194 | # print ("--------------------------------------------------") 195 | # print ("--------------------------------------------------") 196 | # print ("--------------------------------------------------") 197 | # # STOP_LOSS_MULTIPLIER = int(max(avg_diff)) 198 | 199 | # if min(avg_diff) < 0: 200 | # STOP_LOSS_MULTIPLIER = min(avg_diff) * -1 201 | # #STOP_LOSS_MULTIPLIER = STOP_LOSS_MULTIPLIER * random.randint(3,4) #B'cos you know 202 | # STOP_LOSS_MULTIPLIER = STOP_LOSS_MULTIPLIER + int(size_value) 203 | # print ("STOP_LOSS_MULTIPLIER : " + str(STOP_LOSS_MULTIPLIER)) 204 | # else: 205 | # #STOP_LOSS_MULTIPLIER = STOP_LOSS_MULTIPLIER * random.randint(3,4) #B'cos you know 206 | # STOP_LOSS_MULTIPLIER = STOP_LOSS_MULTIPLIER + int(size_value) 207 | # print ("STOP_LOSS_MULTIPLIER : " + str(STOP_LOSS_MULTIPLIER)) 208 | 209 | 210 | # #------------------------------------ 211 | # #------------------------------------ 212 | # #------------------------------------ 213 | # #------------------------------------ 214 | 215 | #NOTE - This code works out the value from the last few hours percent change wise. Then uses that as a guide to work out the percent change. 216 | #i.e Avoid low quality trades by checking the volume traded 217 | 218 | vol_list = [] 219 | base_url = REAL_OR_NO_REAL + '/prices/'+ epic_id + '/HOUR/6' 220 | # Price resolution (MINUTE, MINUTE_2, MINUTE_3, MINUTE_5, MINUTE_10, MINUTE_15, MINUTE_30, HOUR, HOUR_2, HOUR_3, HOUR_4, DAY, WEEK, MONTH) 221 | auth_r = requests.get(base_url, headers=authenticated_headers) 222 | d = json.loads(auth_r.text) 223 | 224 | # print ("-----------------DEBUG-----------------") 225 | # print(auth_r.status_code) 226 | # print(auth_r.reason) 227 | # print (auth_r.text) 228 | # print ("-----------------DEBUG-----------------") 229 | 230 | for i in d['prices']: 231 | ltv = i['lastTradedVolume'] 232 | vol_list.append(int(ltv)) 233 | 234 | print ([((a - b) / a * 100) for a, b in zip(vol_list[::2], vol_list[1::2])]) 235 | avg_diff = ([((a - b) / a * 100) for a, b in zip(vol_list[::2], vol_list[1::2])]) 236 | #THIS IS THE CODE THAT WORKS - REF ONLY 237 | #((list price - actual price) / (list price)) * 100% 238 | 239 | #DEBUG 240 | # print ("AVG VOLUME FOR EACH HOUR " + str(avg_diff)) 241 | # print ("--------------------------------------------------") 242 | # print ("--------------------------------------------------") 243 | # print ("--------------------------------------------------") 244 | # print ("MAX VOLUME IN 24 HOURS : " + str(max(avg_diff))) 245 | # print ("MIN VOLUME IN 24 HOURS : " + str(min(avg_diff))) 246 | # print ("--------------------------------------------------") 247 | # print ("--------------------------------------------------") 248 | # print ("--------------------------------------------------") 249 | VOL_CHANGE_MULTI = mean(avg_diff) 250 | print ("VOL_CHANGE_MULTI : " + str(VOL_CHANGE_MULTI)) 251 | 252 | #******************************************************************* 253 | #******************************************************************* 254 | #******************************************************************* 255 | #******************************************************************* 256 | 257 | #TO DO: 258 | #------------- 259 | #READ IN PRICE CHANGE ON DAY FOR THESE 260 | #NEW YEARS EVE EVE TO DO: 261 | #TEST FOR NEGATIVE MOVEMENT ALL DAY THEN CONVERT 262 | 263 | #HACKY TO TEST 264 | #------------- 265 | #VOL_CHANGE_MULTI = 5 266 | #STOP_LOSS_MULTIPLIER = 50 267 | 268 | # Let's say 30 trades? Not to be too greedy..... 269 | #MAIN PROGRAM LOOP STARTS HERE 270 | #------------------------------------------------ 271 | 272 | TIME_WAIT_MULTIPLIER = 45 273 | def percentage(part, whole): 274 | return (part * whole) / 100.0 275 | 276 | for x in range(1,7): 277 | 278 | #systime.sleep(4) 279 | 280 | DO_A_THING = False 281 | while not DO_A_THING == True: 282 | try: 283 | systime.sleep(random.randint(1,9)) 284 | price_list = [] 285 | ltv_list = [] 286 | 287 | base_url = REAL_OR_NO_REAL + '/prices/'+ epic_id + '/MINUTE/' + str(random.randint(9,15)) 288 | # Price resolution (MINUTE, MINUTE_2, MINUTE_3, MINUTE_5, MINUTE_10, MINUTE_15, MINUTE_30, HOUR, HOUR_2, HOUR_3, HOUR_4, DAY, WEEK, MONTH) 289 | auth_r = requests.get(base_url, headers=authenticated_headers) 290 | d = json.loads(auth_r.text) 291 | # print ("-----------------DEBUG-----------------") 292 | # print(auth_r.status_code) 293 | # print(auth_r.reason) 294 | # print (auth_r.text) 295 | # print ("-----------------DEBUG-----------------") 296 | 297 | for i in d['prices']: 298 | ask_price = i['closePrice']['ask'] 299 | ltv = i['lastTradedVolume'] 300 | price_list.append(float(ask_price)) 301 | ltv_list.append(int(ltv)) 302 | 303 | #--------------------------------- 304 | firstValue = price_list[0] 305 | lastValue = price_list[-1] 306 | #--------------------------------- 307 | Start_Trading_Volume = ltv_list[0] 308 | End_Trading_Volume = ltv_list[-1] 309 | #--------------------------------- 310 | 311 | avg_diff = [price_list[i+1]-price_list[i] for i in range(len(price_list)-1)] 312 | #print ("AVERAGE PIP MOVEMENT IN THIS TIME PERIOD : " + str(avg_diff)) 313 | #print ("MAX PIP MOVEMENT IN THIS TIME PERIOD : " + str(max(avg_diff))) 314 | 315 | if min(avg_diff) < 0: 316 | STOP_LOSS_MULTIPLIER = STOP_LOSS_MULTIPLIER + min(avg_diff) * -1 #Convert Negative to Positive 317 | STOP_LOSS_MULTIPLIER = STOP_LOSS_MULTIPLIER + mean(avg_diff) 318 | #STOP_LOSS_MULTIPLIER = STOP_LOSS_MULTIPLIER * random.randint(3,4) #B'cos you know 319 | #STOP_LOSS_MULTIPLIER = STOP_LOSS_MULTIPLIER + int(size_value) 320 | print ("STOP_LOSS_MULTIPLIER : " + str(STOP_LOSS_MULTIPLIER)) 321 | else: 322 | STOP_LOSS_MULTIPLIER = STOP_LOSS_MULTIPLIER + mean(avg_diff) 323 | #STOP_LOSS_MULTIPLIER = STOP_LOSS_MULTIPLIER * random.randint(3,4) #B'cos you know 324 | #STOP_LOSS_MULTIPLIER = STOP_LOSS_MULTIPLIER + int(size_value) 325 | print ("STOP_LOSS_MULTIPLIER : " + str(STOP_LOSS_MULTIPLIER)) 326 | 327 | 328 | 329 | #DEBUG 330 | print ("-----------------") 331 | print (firstValue) 332 | print (lastValue) 333 | print ("-----------------") 334 | print ("Trade Volume : " + str(Start_Trading_Volume)) 335 | print ("Trade Volume : " + str(End_Trading_Volume)) 336 | print ("-----------------") 337 | 338 | #NOTE :- 339 | #Rule to add If volume increases when the price moves up or down, it is considered a price movement with strength. 340 | #Already Covered 341 | # if Start_Trading_Volume <= End_Trading_Volume and firstValue <= lastValue: 342 | # print ("Higher Volume") 343 | # print ("Higher Price") 344 | # #Go Long 345 | 346 | if Start_Trading_Volume < End_Trading_Volume and firstValue > lastValue: 347 | vol_percent = percentage(Start_Trading_Volume, End_Trading_Volume) 348 | #price_percent = percentage(firstValue, lastValue) 349 | price_percent = 100 * (float(lastValue) - float(firstValue)) / float(lastValue) 350 | price_percent = 100 * (float(firstValue) - float(lastValue)) / float(firstValue) 351 | #DEBUG - PRINT PERCENT CHANGE 352 | print ("Volume Change Percent : " + str(vol_percent)) 353 | print ("Price Change Percent : " + str(price_percent)) 354 | print ("Higher Volume") 355 | print ("Lower Price") 356 | print ("DIRECTION IS DOWN (SHORT)") 357 | 358 | if vol_percent > VOL_CHANGE_MULTI: 359 | DIRECTION_TO_TRADE = "SELL" 360 | DIRECTION_TO_CLOSE = "BUY" 361 | DIRECTION_TO_COMPARE = 'offer' 362 | DO_A_THING = True 363 | 364 | elif Start_Trading_Volume < End_Trading_Volume and firstValue < lastValue: 365 | vol_percent = percentage(Start_Trading_Volume, End_Trading_Volume) 366 | #price_percent = percentage(firstValue, lastValue) 367 | price_percent = 100 * (float(lastValue) - float(firstValue)) / float(lastValue) 368 | price_percent = 100 * (float(firstValue) - float(lastValue)) / float(firstValue) 369 | #DEBUG - PRINT PERCENT CHANGE 370 | print ("Volume Change Percent : " + str(vol_percent)) 371 | print ("Price Change Percent : " + str(price_percent)) 372 | #Long Candidate, Buyers require increasing numbers and increasing enthusiasm in order to keep pushing prices higher. 373 | print ("Higher Volume") 374 | print ("Higher Price") 375 | print ("DIRECTION IS UP (LONG)") 376 | 377 | if vol_percent > VOL_CHANGE_MULTI: 378 | DIRECTION_TO_TRADE = "BUY" 379 | DIRECTION_TO_CLOSE = "SELL" 380 | DIRECTION_TO_COMPARE = 'bid' 381 | DO_A_THING = True 382 | elif int(Start_Trading_Volume) > int(End_Trading_Volume) and firstValue < lastValue: 383 | vol_percent = percentage(Start_Trading_Volume, End_Trading_Volume) 384 | #price_percent = percentage(lastValue, firstValue) 385 | price_percent = 100 * (float(lastValue) - float(firstValue)) / float(lastValue) 386 | price_percent = 100 * (float(firstValue) - float(lastValue)) / float(firstValue) 387 | #DEBUG - PRINT PERCENT CHANGE 388 | print ("Volume Change Percent : " + str(vol_percent)) 389 | print ("Price Change Percent : " + str(price_percent)) 390 | #Increasing price and decreasing volume show lack of interest, and this is a warning of a potential reversal. 391 | print ("Higher Price") 392 | print ("Lower Volume") 393 | print ("DIRECTION IS DOWN (SHORT)") 394 | 395 | if vol_percent > VOL_CHANGE_MULTI: 396 | DIRECTION_TO_TRADE = "SELL" 397 | DIRECTION_TO_CLOSE = "BUY" 398 | DIRECTION_TO_COMPARE = 'offer' 399 | DO_A_THING = True 400 | else: 401 | DO_A_THING = False 402 | print ("NO TRADE") 403 | systime.sleep(4) 404 | #DO NOT TRADE 405 | # print ("No Clear Direction of Trade/Trade on Client Sentiment") 406 | # base_url = REAL_OR_NO_REAL + '/clientsentiment/'+ MARKET_ID 407 | # auth_r = requests.get(base_url, headers=authenticated_headers) 408 | # d = json.loads(auth_r.text) 409 | # # DEBUG!!!! 410 | # print(auth_r.status_code) 411 | # print(auth_r.reason) 412 | # print (auth_r.text) 413 | # long_sent = d['longPositionPercentage'] 414 | # short_sent = d['shortPositionPercentage'] 415 | # if long_sent > short_sent: 416 | # DIRECTION_TO_TRADE = "BUY" 417 | # DIRECTION_TO_CLOSE = "SELL" 418 | # DIRECTION_TO_COMPARE = 'bid' 419 | # else: 420 | # DIRECTION_TO_TRADE = "SELL" 421 | # DIRECTION_TO_CLOSE = "BUY" 422 | # DIRECTION_TO_COMPARE = 'offer' 423 | 424 | #--------------------------------- 425 | #--------------------------------- 426 | #--------------------------------- 427 | #--------------------------------- 428 | 429 | except Exception as e: 430 | #print (e) 431 | DO_A_THING = False 432 | print ("ERROR READING PRICE - NO TRADE") 433 | systime.sleep(4) 434 | 435 | 436 | base_url = REAL_OR_NO_REAL + '/positions/otc' 437 | authenticated_headers = {'Content-Type':'application/json; charset=utf-8', 438 | 'Accept':'application/json; charset=utf-8', 439 | 'X-IG-API-KEY':API_KEY, 440 | 'CST':CST_token, 441 | 'X-SECURITY-TOKEN':x_sec_token} 442 | 443 | data = {"direction":DIRECTION_TO_TRADE,"epic": epic_id, "limitDistance":limitDistance_value, "orderType":orderType_value, "size":size_value,"expiry":expiry_value,"guaranteedStop":guaranteedStop_value,"currencyCode":currencyCode_value,"forceOpen":forceOpen_value,"stopDistance":stopDistance_value} 444 | r = requests.post(base_url, data=json.dumps(data), headers=authenticated_headers) 445 | # MAKE AN ORDER 446 | d = json.loads(r.text) 447 | deal_ref = d['dealReference'] 448 | #CONFIRM MARKET ORDER 449 | base_url = REAL_OR_NO_REAL + '/confirms/'+ deal_ref 450 | auth_r = requests.get(base_url, headers=authenticated_headers) 451 | d = json.loads(auth_r.text) 452 | DEAL_ID = d['dealId'] 453 | print("DEAL ID : " + str(d['dealId'])) 454 | print(d['dealStatus']) 455 | print(d['reason']) 456 | systime.sleep(2) #For some reason sleep here, Maybe just delay on IG Side?? 457 | 458 | # the trade will only break even once the price of the asset being traded has surpassed the sell price (for long trades) or buy price (for short trades). 459 | #READ IN INITIAL PROFIT 460 | 461 | base_url = REAL_OR_NO_REAL + '/positions/'+ DEAL_ID 462 | auth_r = requests.get(base_url, headers=authenticated_headers) 463 | d = json.loads(auth_r.text) 464 | 465 | 466 | # DEBUG 467 | # print(auth_r.status_code) 468 | # print(auth_r.reason) 469 | # print (auth_r.text) 470 | 471 | if DIRECTION_TO_TRADE == "SELL": 472 | PROFIT_OR_LOSS = float(d['position']['openLevel']) - float(d['market'][DIRECTION_TO_COMPARE]) 473 | PROFIT_OR_LOSS = PROFIT_OR_LOSS * float(size_value) 474 | print ("Deal Number : " + str(x) + " Profit/Loss : " + str(PROFIT_OR_LOSS)) 475 | else: 476 | PROFIT_OR_LOSS = float(d['market'][DIRECTION_TO_COMPARE] - float(d['position']['openLevel'])) 477 | PROFIT_OR_LOSS = PROFIT_OR_LOSS * float(size_value) 478 | print ("Deal Number : " + str(x) + " Profit/Loss : " + str(PROFIT_OR_LOSS)) 479 | 480 | 481 | #KEEP READING IN FOR PROFIT 482 | try: 483 | while PROFIT_OR_LOSS < 0.1: #Over 10p otherwise not worth it and price could move 484 | base_url = REAL_OR_NO_REAL + '/positions/'+ DEAL_ID 485 | auth_r = requests.get(base_url, headers=authenticated_headers) 486 | d = json.loads(auth_r.text) 487 | 488 | if DIRECTION_TO_TRADE == "SELL": 489 | PROFIT_OR_LOSS = float(d['position']['openLevel']) - float(d['market'][DIRECTION_TO_COMPARE]) 490 | PROFIT_OR_LOSS = float(PROFIT_OR_LOSS * float(size_value)) 491 | print ("Deal Number : " + str(x) + " Profit/Loss : " + str(PROFIT_OR_LOSS)) 492 | systime.sleep(2) #Don't be too keen to read price 493 | else: 494 | PROFIT_OR_LOSS = float(d['market'][DIRECTION_TO_COMPARE] - float(d['position']['openLevel'])) 495 | PROFIT_OR_LOSS = float(PROFIT_OR_LOSS * float(size_value)) 496 | print ("Deal Number : " + str(x) + " Profit/Loss : " + str(PROFIT_OR_LOSS)) 497 | systime.sleep(2) #Don't be too keen to read price 498 | 499 | ARTIFICIAL_STOP_LOSS = int(size_value) * STOP_LOSS_MULTIPLIER 500 | ARTIFICIAL_STOP_LOSS = ARTIFICIAL_STOP_LOSS * -1 #Make Negative, DO NOT REMOVE!! 501 | # print (PROFIT_OR_LOSS) 502 | # print (ARTIFICIAL_STOP_LOSS) 503 | 504 | if PROFIT_OR_LOSS < ARTIFICIAL_STOP_LOSS: 505 | #CLOSE TRADE/GTFO 506 | print ("WARNING!! POTENTIAL DIRECTION CHANGE!!") 507 | SIZE = size_value 508 | ORDER_TYPE = orderType_value 509 | base_url = REAL_OR_NO_REAL + '/positions/otc' 510 | data = {"dealId":DEAL_ID,"direction":DIRECTION_TO_CLOSE,"size":SIZE,"orderType":ORDER_TYPE} 511 | #authenticated_headers_delete IS HACKY AF WORK AROUND!! AS PER .... https://labs.ig.com/node/36 512 | authenticated_headers_delete = {'Content-Type':'application/json; charset=utf-8', 513 | 'Accept':'application/json; charset=utf-8', 514 | 'X-IG-API-KEY':API_KEY, 515 | 'CST':CST_token, 516 | 'X-SECURITY-TOKEN':x_sec_token, 517 | '_method':"DELETE"} 518 | auth_r = requests.post(base_url, data=json.dumps(data), headers=authenticated_headers_delete) 519 | #DEBUG 520 | print(r.status_code) 521 | print(r.reason) 522 | print (r.text) 523 | systime.sleep(random.randint(1, TIME_WAIT_MULTIPLIER)) #Obligatory Wait before doing next order 524 | 525 | except Exception as e: 526 | #print(e) #Yeah, I know now. 527 | print ("ERROR : ORDER MIGHT NOT BE OPEN FOR WHATEVER REASON") 528 | #WOAH CALM DOWN! WAIT .... STOP LOSS MIGHT HAVE BEEN HIT 529 | systime.sleep(random.randint(1, TIME_WAIT_MULTIPLIER)) 530 | pass 531 | 532 | #systime.sleep(1) 533 | 534 | if PROFIT_OR_LOSS > 0: 535 | print ("ASSUME PROFIT!!") 536 | SIZE = size_value 537 | ORDER_TYPE = orderType_value 538 | 539 | base_url = REAL_OR_NO_REAL + '/positions/otc' 540 | data = {"dealId":DEAL_ID,"direction":DIRECTION_TO_CLOSE,"size":SIZE,"orderType":ORDER_TYPE} 541 | #authenticated_headers_delete IS HACKY AF WORK AROUND!! AS PER .... https://labs.ig.com/node/36 542 | authenticated_headers_delete = {'Content-Type':'application/json; charset=utf-8', 543 | 'Accept':'application/json; charset=utf-8', 544 | 'X-IG-API-KEY':API_KEY, 545 | 'CST':CST_token, 546 | 'X-SECURITY-TOKEN':x_sec_token, 547 | '_method':"DELETE"} 548 | 549 | auth_r = requests.post(base_url, data=json.dumps(data), headers=authenticated_headers_delete) 550 | #CLOSE TRADE 551 | print(r.status_code) 552 | print(r.reason) 553 | print (r.text) 554 | 555 | # #CONFIRM CLOSE - FUTURE 556 | # base_url = REAL_OR_NO_REAL + '/confirms/'+ deal_ref 557 | # auth_r = requests.get(base_url, headers=authenticated_headers) 558 | # d = json.loads(auth_r.text) 559 | # DEAL_ID = d['dealId'] 560 | # print("DEAL ID : " + str(d['dealId'])) 561 | # print(d['dealStatus']) 562 | # print(d['reason']) 563 | 564 | systime.sleep(random.randint(1, TIME_WAIT_MULTIPLIER)) #Obligatory Wait before doing next order 565 | --------------------------------------------------------------------------------