Блог им. NektoFinkelmaer

Робот для торговли спреда внутри канала, пробоя или отбоя от уровня (с исходниками на Java Script)

Скрипт в руки — деньги в карман.

Инструкция:
1. Бери «Скрипт».
2. Пиши «Тикер» из фондовой секции ММВБ.
3. Жми «График».
Вуаля… ваш брокерский счет наливается прибылью.

Чем жирнее цена, тем жирнее уровень.
Пользуйся и твоя эквити будет гладкая и больше чем вчера.

Робот для торговли спреда внутри канала, пробоя или отбоя от уровня (с исходниками на Java Script)

ПС: График влево.
Данные ММВБ с задержкой 15 минут.

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
</head>
<body>

<form name="search">
    <input type="text" name="key" placeholder="Тикер" id="key"/>
    <input type="button" name="buttonChart" value="График" />
</form>
<div id="printBlock"></div>
<canvas id="chart" width="4000" height="600"></canvas>
<script>
const keyBox = document.search.key;
const keyButton = document.search.buttonChart;
 
 function DrawChart(prices,minPrice,maxPrice,maxVolume,ZZ,ZZDay){

	var chart = document.getElementById("chart");
	
	
	if (chart.getContext) {
		var ctx = chart.getContext("2d");
		ctx.lineWidth=1;
		Point = 0;
		for (let i = prices. <a name="cut"></a> length-1; i >= 0; i--) { 
			var K=600/(maxPrice-minPrice);
			var pOpen = Math.trunc((prices[i].Open-minPrice)*K);
			var pClose = Math.trunc((prices[i].Close-minPrice)*K);
			
			var pMin = Math.trunc((prices[i].Low-minPrice)*K);
			var pMax = Math.trunc((prices[i].High-minPrice)*K);
			
			var dStart = 600-Math.max(pOpen,pClose);
			var dFinish = 600-Math.min(pOpen,pClose);
			
			var dMin = 600-pMin;
			var dMax = 600-pMax;
			
			var pVolume = Math.trunc((prices[i].Volume)/maxVolume*100);
			var dVolume = 600-pVolume;
			
			var AA = prices[i].Close - prices[i].Open;
			
			//ctx.beginPath();
			if (pOpen==pClose) {
				
				ctx.fillStyle = "rgb(0,0,0)";
				dFinish = dStart+1;
				//console.log("-"+(Point*4)+" "+dStart+" "+dFinish + " "+AA+" "+pOpen+" "+pClose+" "+K);
				
			}
			else {
				
				if (prices[i].Open>prices[i].Close) {
					ctx.fillStyle = "rgb(200,0,0)";
				}
				else{
					ctx.fillStyle = "rgb(0,200,0)";
				}
				
			}
			
			
			if (Point==0) {
				ctx.fillRect(Point, dStart, 40, 1);
				
				ctx.textBaseline = "bottom";
				ctx.font = "bold 8px Arial";
				
				ctx.fillText(prices[i].Close, Point, dStart-2);
				
				Point = Point+11;
			}
			
			//console.log(""+(Point*4)+" "+dStart+" "+dFinish + " "+AA+" "+pOpen+" "+pClose+" "+K);
			ctx.fillRect(Point*4, dStart, 3, dFinish-dStart);
			
			ctx.fillStyle = ctx.fillStyle.replace(")",",0.7)");
			
			//console.log(""+prices[i].Volume+" "+maxVolume + " "+pVolume+" "+dVolume+" "+ctx.fillStyle);
			
			ctx.fillRect(Point*4, dVolume, 3, 600-dVolume);
			
			ctx.fillStyle = "rgb(0,0,0)";
			ctx.fillRect(Point*4+1, dMax, 1, dStart-dMax);
			ctx.fillRect(Point*4+1, dFinish, 1, dMin-dFinish);
			Point ++;
		}
		
		
		
		DrawZZ(ZZ,ctx,prices,maxPrice,minPrice);
		ctx.lineWidth=2;
		DrawZZ(ZZDay,ctx,prices,maxPrice,minPrice);
		
		var priceLevel = [];
		
		ctx.lineWidth=1;
		ctx.strokeStyle = "rgb(0,0,200,0.3)";
		DrawK(ZZ,ctx,prices,maxPrice,minPrice,1,3,priceLevel);
		DrawK(ZZ,ctx,prices,maxPrice,minPrice,3,5,priceLevel);
		DrawK(ZZ,ctx,prices,maxPrice,minPrice,1,5,priceLevel);
		
		DrawK(ZZ,ctx,prices,maxPrice,minPrice,2,4,priceLevel);
		DrawK(ZZ,ctx,prices,maxPrice,minPrice,4,6,priceLevel);
		DrawK(ZZ,ctx,prices,maxPrice,minPrice,2,6,priceLevel);
		
		ctx.lineWidth=2;
		
		DrawK(ZZDay,ctx,prices,maxPrice,minPrice,1,3,priceLevel);
		DrawK(ZZDay,ctx,prices,maxPrice,minPrice,3,5,priceLevel);
		DrawK(ZZDay,ctx,prices,maxPrice,minPrice,1,5,priceLevel);
		
		DrawK(ZZDay,ctx,prices,maxPrice,minPrice,2,4,priceLevel);
		DrawK(ZZDay,ctx,prices,maxPrice,minPrice,4,6,priceLevel);
		DrawK(ZZDay,ctx,prices,maxPrice,minPrice,2,6,priceLevel);
		
		priceLevel.sort(function(a,b){ 
							if (a.Price<b.Price) return -1; else if (a.Price>b.Price) return 1; else return 0;
						});
		
		
		priceLevelGroup = [];
		maxVolume = 0;
		for (let i = 0; i < priceLevel.length; i++) {
			
			console.log(""+priceLevel[i].Price+" "+priceLevel[i].Volume);
			
			if (i==0) {
				priceLevelGroup[0] = {Price:priceLevel[i].Price,Volume:priceLevel[i].Volume};
				
			}
			else{
				if (priceLevel[i].Price/priceLevelGroup[priceLevelGroup.length-1].Price-1<0.003) {
					
						priceLevelGroup[priceLevelGroup.length-1].Price = 
											(priceLevel[i].Volume*priceLevel[i].Price
											+priceLevelGroup[priceLevelGroup.length-1].Volume*priceLevelGroup[priceLevelGroup.length-1].Price)
											/(priceLevel[i].Volume+priceLevelGroup[priceLevelGroup.length-1].Volume);
						priceLevelGroup[priceLevelGroup.length-1].Volume = priceLevelGroup[priceLevelGroup.length-1].Volume+priceLevel[i].Volume;
						
				}
				else{
					priceLevelGroup[priceLevelGroup.length] = {Price:priceLevel[i].Price,Volume:priceLevel[i].Volume};
				}
						
			};
			if (priceLevelGroup[priceLevelGroup.length-1].Volume>maxVolume){
				maxVolume = priceLevelGroup[priceLevelGroup.length-1].Volume;
			}
			
		}
		
		for (let i = 0; i < priceLevelGroup.length; i++) {
			
			
			pOpen = Math.trunc((priceLevelGroup[i].Price-minPrice)*K);
			
			dStart = 600-pOpen;
			
			ctx.fillRect(0, dStart, 40, 1);
				
			ctx.textBaseline = "bottom";
			
			ctx.font = ""+(Math.trunc(priceLevelGroup[i].Volume/maxVolume*12)+6)+"px Arial";
			
			console.log("g "+maxVolume+" "+priceLevelGroup[i].Volume+" "+ctx.font+" "+(Math.trunc(priceLevelGroup[i].Volume/maxVolume*12)+6));
			
			//console.log("g "+priceLevelGroup[i].Price+" "+priceLevelGroup[i].Volume+" "+ctx.font+" "+(Math.trunc(priceLevelGroup[i].Volume/maxVolume*12)+6));
			
			percent = Math.trunc((prices[prices.length-1].Close - priceLevelGroup[i].Price)/prices[prices.length-1].Close*10000)/100;
			if (percent<0) {percent=-percent;ctx.fillStyle = "rgb(100,150,100)";}
			else {ctx.fillStyle = "rgb(150,100,100)"};
			ctx.fillText(""+Math.trunc(priceLevelGroup[i].Price*100)/100+" ("+percent+"%)", 0, dStart-1);
				
		}
		
	}
 }
 
 function DrawZZ(ZZ,ctx,prices,maxPrice,minPrice){
		
		ctx.fillStyle = "rgb(0,0,0,0.7)";
		ctx.beginPath();
		
		for (let i = 0; i < ZZ.length; i++) {
			
			Point = (prices.length - ZZ[i].Point+10)*4+1;
			var K=600/(maxPrice-minPrice);
			pPrice = Math.trunc((ZZ[i].price-minPrice)*K);
			dStart = 600-pPrice;
			
			//console.log(""+ZZ[i].price+" "+dStart+ " "+ZZ[i].Point+" "+ZZ[i].T);
			
			if (i==0) {
				ctx.moveTo(Point,dStart);
			} else {
				ctx.lineTo(Point,dStart);
			}
		}
		ctx.stroke();
 }

function DrawK(ZZ,ctx,prices,maxPrice,minPrice,p1,p2,priceLevel){
		
		
		if (ZZ.length-p1<0 || ZZ.length-p2<0) {return};
		
		var K=600/(maxPrice-minPrice);
		
		first = ZZ.length - p1;
		second = ZZ.length - p2;
		
		//console.log(""+first+" "+second+" "+ZZ.length);
		
		fPoint = (prices.length-ZZ[first].Point+10)*4+1;
		sPoint = (prices.length-ZZ[second].Point+10)*4+1;
			
		ePrice=ZZ[second].price+(prices.length-ZZ[second].Point)*(ZZ[first].price-ZZ[second].price)/(ZZ[first].Point-ZZ[second].Point)
		
		priceLevel[priceLevel.length] = {Price:ePrice,Volume:(ZZ[second].Volume+ZZ[first].Volume)};
		priceLevel[priceLevel.length] = {Price:ZZ[first].price,Volume:(ZZ[first].Volume)};
		priceLevel[priceLevel.length] = {Price:ZZ[second].price,Volume:(ZZ[second].Volume)};
		
		
		//console.log(""+ZZ[first].Point+" "+ZZ[second].Point+" "+" "+prices.length+" "+ZZ[first].price+" "+ZZ[second].price+" "+ePrice);
		
		fPrice = Math.trunc((ZZ[first].price-minPrice)*K);
		sPrice = Math.trunc((ZZ[second].price-minPrice)*K);
		ePrice = Math.trunc((ePrice-minPrice)*K);
		
		dStart = 600-sPrice;
		dFinish = 600-ePrice;
		
		
		//console.log(""+first+" "+second+" "+fPrice+" "+sPrice+" "+ePrice);
		
		//ctx.fillStyle = "rgb(0,0,255,0.7)";
		//console.log(""+ctx.fillStyle);
		ctx.beginPath();
		ctx.moveTo(sPoint,dStart);
		ctx.lineTo(40,dFinish);
		ctx.stroke();
		
		ctx.beginPath();
		ctx.moveTo(sPoint,dStart);
		ctx.lineTo(40,dStart);
		ctx.stroke();
		
		ctx.beginPath();
		ctx.moveTo(fPoint,600-fPrice);
		ctx.lineTo(40,600-fPrice);
		ctx.stroke();
		
 }
 
 function FillArray (data){

	var prices = [];
	var pricesDay = [];
	var ZZ = [];
	var ZZDay = [];
	var minPrice = 9999999;
	var maxPrice = 0;
	var maxVolume = 0;
	
	let md = data['candles']['data'];
	 
	for (let i = 0; i < md.length; i++) {
		var cl = prices.length;
		prices[cl] = [];
		prices[cl] = {Period:md[i][6], Open:md[i][0], Close:md[i][1],Low:md[i][3], High:md[i][2], Volume:md[i][5], Period:md[i][6]}
		if (minPrice>prices[cl].Low) {
				minPrice = prices[cl].Low;
		}
		if (maxPrice<prices[cl].High) {
				maxPrice = prices[cl].High;
		}
		if (maxVolume<prices[cl].Volume) {
				maxVolume = prices[cl].Volume;
		}
		
		var cDay = prices[cl].Period;
		cDay = cDay.substring(0,10);
		
		
		PosDay=pricesDay.findIndex(item => item.Period == cDay);
		if (PosDay==-1) {PosDay=pricesDay.length; pricesDay[PosDay]={Period:cDay,High:prices[cl].High,Low:prices[cl].Low,PeriodHi:i,PeriodLow:i,Volume:prices[cl].Volume}}
		if (pricesDay[PosDay].High<prices[cl].High) {pricesDay[PosDay].High=prices[cl].High;pricesDay[PosDay].PeriodHi=cl;}
		if (pricesDay[PosDay].Low>prices[cl].Low) {pricesDay[PosDay].Low=prices[cl].Low;pricesDay[PosDay].PeriodLow=cl;}
		pricesDay[PosDay].Volume = pricesDay[PosDay].Volume+prices[cl].Volume;
		
		if (cl>1) {
			if (ZZ.length == 0) {
				ZZ[0] = {price:(prices[cl-2].Open>prices[cl].Close ? prices[cl-2].High:prices[cl-2].Low), 
								Point:cl-2, 
								T:(prices[cl-2].Open>prices[cl].Close ? -1:1),
								Volume:prices[cl-2].Volume}
				
				//console.log("f "+ZZ[ZZ.length-1].price+" "+" "+ZZ[ZZ.length-1].Point+" "+ZZ[ZZ.length-1].T);
				
			} else {
				if (ZZ[ZZ.length-1].T == 1) { 
					//console.log("up "+ZZ[ZZ.length-1].price+" "+" "+ZZ[ZZ.length-1].Point+" "+ZZ[ZZ.length-1].T);
				
					if (prices[cl-2].High<prices[cl].High || prices[cl-1].High<prices[cl].High || prices[cl-2].Low<prices[cl].Low || prices[cl-1].Low<prices[cl].Low) {}
					else {
							ZZ[ZZ.length]={price:(Math.max(prices[cl-2].High,prices[cl-1].High)),
									       Point:(prices[cl-2].High>prices[cl-1].High ? cl-2:cl-1),
										   T:-1,
										   Volume:(prices[cl-2].High>prices[cl-1].High ? prices[cl-2].Volume:prices[cl-1].Volume)}
							
							//console.log("up "+ZZ[ZZ.length-1].price+" "+" "+ZZ[ZZ.length-1].Point+" "+ZZ[ZZ.length-1].T);
						}
					} 
				else {
					if (ZZ[ZZ.length-1].T == -1) { 
						if (prices[cl-2].Low>prices[cl].Low || prices[cl-1].Low>prices[cl].Low || prices[cl-2].High>prices[cl].High || prices[cl-1].High>prices[cl].High) {}
						else {
							ZZ[ZZ.length]={price:(Math.min(prices[cl-2].Low,prices[cl-1].Low)),
										   Point:(prices[cl-2].Low<prices[cl-1].Low ? cl-2:cl-1),
										   T:1,
										   Volume:(prices[cl-2].Low<prices[cl-1].Low ? prices[cl-2].Volume:prices[cl-1].Volume)}
							//console.log("dw "+ZZ[ZZ.length-1].price+" "+" "+ZZ[ZZ.length-1].Point+" "+ZZ[ZZ.length-1].T);
						}
						 
					}
				}
				
			}
		}
	}
	
	for (let cl = 0; cl < pricesDay.length; cl++) {
		//console.log(""+pricesDay[cl].Period+" "+pricesDay[cl].High+" "+pricesDay[cl].Low+" "+pricesDay[cl].Volume+" "+pricesDay[cl].PeriodHi+" "+pricesDay[cl].PeriodLow);
		
		if (cl>1) {
			if (ZZDay.length == 0) {
				ZZDay[0] = {price:(pricesDay[cl-2].Open>pricesDay[cl].Close ? pricesDay[cl-2].High:pricesDay[cl-2].Low), 
							Point:(pricesDay[cl-2].Open>pricesDay[cl].Close ? pricesDay[cl-2].PeriodHi:pricesDay[cl-2].PeriodLow), 
							T:(pricesDay[cl-2].Open>pricesDay[cl].Close ? -1:1),
							Volume:prices[cl-2].Volume}
				
				//console.log("f "+ZZDay[ZZDay.length-1].price+" "+" "+ZZDay[ZZDay.length-1].Point+" "+ZZDay[ZZDay.length-1].T);
				
			} else {
				if (ZZDay[ZZDay.length-1].T == 1) { 
					//console.log("up "+ZZDay[ZZDay.length-1].price+" "+" "+ZZDay[ZZDay.length-1].Point+" "+ZZDay[ZZDay.length-1].T);
				
					if (pricesDay[cl-2].High<pricesDay[cl].High || pricesDay[cl-1].High<pricesDay[cl].High || pricesDay[cl-2].Low<pricesDay[cl].Low || pricesDay[cl-1].Low<pricesDay[cl].Low) {}
					else {
							ZZDay[ZZDay.length]={price:(Math.max(pricesDay[cl-2].High,pricesDay[cl-1].High)),
											     Point:(pricesDay[cl-2].High>pricesDay[cl-1].High ? pricesDay[cl-2].PeriodHi:pricesDay[cl-1].PeriodHi),
												 T:-1,
												 Volume:(pricesDay[cl-2].High>pricesDay[cl-1].High ? pricesDay[cl-2].Volume:pricesDay[cl-1].Volume)}
							
							//console.log("up "+ZZDay[ZZDay.length-1].price+" "+" "+ZZDay[ZZDay.length-1].Point+" "+ZZDay[ZZDay.length-1].T);
						}
					} 
				else {
					if (ZZDay[ZZDay.length-1].T == -1) { 
						if (pricesDay[cl-2].Low>pricesDay[cl].Low || pricesDay[cl-1].Low>pricesDay[cl].Low || pricesDay[cl-2].High>pricesDay[cl].High || pricesDay[cl-1].High>pricesDay[cl].High) {}
						else {
							ZZDay[ZZDay.length]={price:(Math.min(pricesDay[cl-2].Low,pricesDay[cl-1].Low)),
												 Point:(pricesDay[cl-2].Low<pricesDay[cl-1].Low ? pricesDay[cl-2].PeriodLow:pricesDay[cl-1].PeriodLow),
												 T:1,
												 Volume:(pricesDay[cl-2].Low<pricesDay[cl-1].Low ? pricesDay[cl-2].Volume:pricesDay[cl-1].Volume)}
							//console.log("dw "+ZZDay[ZZDay.length-1].price+" "+" "+ZZDay[ZZDay.length-1].Point+" "+ZZDay[ZZDay.length-1].T);
						}
						 
					}
				}
				
			}
		}
	}
	
	DrawChart(prices,minPrice,maxPrice,maxVolume,ZZ,ZZDay);
	return prices;
 }
 
 function strRight(n,str){
   return str.substring(str.length-n,str.length);
 }  
// обработчик изменения текста
function onchange(e){
    // получаем элемент printBlock
    const printBlock = document.getElementById("printBlock");
	const tiker = document.getElementById("key").value;
    // получаем новое значение
    const val = tiker;
    // установка значения
    printBlock.textContent = printBlock.textContent+" "+tiker;
	
	
	var URL = "https://iss.moex.com/iss/engines/stock/markets/shares/securities/<TIKER>/candles.json?from=<DateFrom>&interval=60";
	
	URL = URL.replace("<TIKER>", val);
	
	var now = new Date();
	now.setDate(now.getDate() - 45);
	console.log(now);

	var Month=now.getMonth()+1;
	var year=now.getFullYear();
	
	//if (Month<0) {Month=12+Month+1; year--;};
	var startdata = (year).toString()+"-"+strRight(2,"0"+Month.toString())+"-"+strRight(2,"0"+now.getDate().toString());
	
	URL = URL.replace("<DateFrom>", startdata);
	console.log(URL);
	fetch(URL)
		.then(function (response) {
			return response.json();
		})
		.then(function (data) {
			
			FillArray(data);
			
		})
  
}


//keyBox.addEventListener("change", onchange);
keyButton.addEventListener("click", onchange);
</script>
</body>
</html>
Данная публикация является личным мнением автора. Мнение владельца сайта может не совпадать с мнением автора.
704 | ★3
3 комментария
Если топик наберет хотя бы 8 лайков, добавлю валютный рынок и индексы, а может даже срочку. Ставь скорее не хватает только твоего… 🙂
avatar
С таким роботом можно все деньги с рынка выкачать
avatar
Tema ☑️, потом обратно закачать и опять выкачать, но уже побольше.
avatar

Читайте на SMART-LAB:
Фото
EUR/USD: Быки ещё не сказали своё последнее слово?
Единая валюта так и не пробила линию шеи разворотной фигуры «голова и плечи», а также уровень поддержки 1.1411. Это может означать лишь временный...
Опрос инвесторов от Займера
Дорогие друзья! Мы проводим короткое исследование среди инвесторов. Хотим понять, как инвесторы воспринимают нашу компанию, сектор МФО,...
Фото
Разбор эмитента. Татнефть: после коррекции бумаги вновь выглядят интересно
После падения на 20% Татнефть торгуется с хорошим дисконтом к историческим уровням с 2023 г. Даже с учетом снижения дивидендов до 50% и...
Фото
Сетевые компании. Изменение целевых цен и смена рейтинга!
Я последнее время наблюдаю такую тенденцию — у компании дивидендный гэп, но акции продолжают отвесно падать, это и произошло с сетевыми...

теги блога Nekto Finkelmaer

....все тэги



UPDONW
Новый дизайн