Блог им. 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>
694 | ★3
3 комментария
Если топик наберет хотя бы 8 лайков, добавлю валютный рынок и индексы, а может даже срочку. Ставь скорее не хватает только твоего… 🙂
avatar
С таким роботом можно все деньги с рынка выкачать
avatar
Tema ☑️, потом обратно закачать и опять выкачать, но уже побольше.
avatar

Читайте на SMART-LAB:
Фото
BRENT: Дипломатия Трампа против "бычьего десанта" — кто блефует?
После сенсационного заявления Трампа о достижении двухнедельного перемирия с Ираном нефть открыла торги в среду с мощным гэпом вниз. Цена...
Фото
🔴 Эфир начинается через 5 минут
Уже совсем скоро, в 11:00 начнём эфир, посвящённый финансовым результатам Группы МГКЛ по МСФО за 12 месяцев 2025 года. Разберём ключевые...
АПРИ продолжает строительство всесезонного мультикурорта «ФанПарк»
АПРИ продолжает строительство всесезонного мультикурорта «ФанПарк» «ФанПарк» – это мультифункциональный всесезонный курорт на...
Фото
Кто сейчас самый дешевый сбыт? Сводный пост по сбытовым компаниям по отчетам РСБУ за 2025г.
Волгоградэнергосбыт Ставропольэнергосбыт Самараэнерго Мордовэнергосбыт Пермэнергосбыт Новосибирскэнергосбыт...

теги блога Nekto Finkelmaer

....все тэги



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