Your IP : 216.73.216.79


Current Path : /var/www/html/aipa/backend/modules/cryptoaverage/views/crypto-average/
Upload File :
Current File : /var/www/html/aipa/backend/modules/cryptoaverage/views/crypto-average/index.php

<?php

use yii\helpers\Html;
use yii\helpers\Url;
use yii\bootstrap\Modal;
use backend\modules\cryptoaverage\models\CryptoParameter;
/* @var $this yii\web\View */
/* @var $searchModel backend\models\CryptoAverageSearch */
/* @var $dataProvider yii\data\ActiveDataProvider */
/* @var $data yii\data\ActiveDataProvider */
/* @var $coin backend\controllers\CryptoAverageController */

$this->title = Yii::t('app', 'Crypto Averages');
$this->params['breadcrumbs'][] = $this->title;

$this->registerJsFile('https://bossanova.uk/jspreadsheet/v4/jexcel.js');
$this->registerJsFile('https://jsuites.net/v4/jsuites.js');
$this->registerJsFile('https://cdn.jsdelivr.net/gh/alpinejs/alpine@v2.x.x/dist/alpine.min.js');

$this->params['extra-asset']['CSS'][] = 'plugins/toastr/toastr.min.css';
$this->params['extra-asset']['JS'][] = 'plugins/toastr/toastr.min.js';

$url = Url::to(['/cryptoaverage/crypto-average']);
$urlFormula = Url::to(['/cryptoaverage/crypto-average/formula-template']);
$urlSave = Url::to(['/cryptoaverage/crypto-average/save-spread']);
$urlPull = Url::to(['/cryptoaverage/crypto-average/api']);

$this->registerJs(
<<<JS

var changed = function(instance, cell, x, y, value) {
    var cellName = jexcel.getColumnNameFromId([x,y]);
    $('#log').append('New change on cell ' + cellName + ' to: ' + value + '<br>');
}

var beforeChange = function(instance, cell, x, y, value) {
//     spread.setValue(cell, value)
    var cellName = jexcel.getColumnNameFromId([x,y]);
    $('#log').append('The cell ' + cellName + ' will be changed<br>');
}

var insertedRow = function(el, rowNumber, numOfRows, rowRecords, insertBefore) {
    $('#log').append('Row added<br>');
}

var insertedColumn = function(instance) {
    $('#log').append('Column added<br>');
}

var deletedRow = function(instance) {
    $('#log').append('Row deleted<br>');
}

var deletedColumn = function(instance) {
    $('#log').append('Column deleted<br>');
}

var sort = function(instance, cellNum, order) {
    var order = (order) ? 'desc' : 'asc';
    $('#log').append('The column  ' + cellNum + ' sorted by ' + order + '<br>');
}

var resizeColumn = function(instance, cell, width) {
    $('#log').append('The column  ' + cell + ' resized to width ' + width + ' px<br>');
}

var resizeRow = function(instance, cell, height) {
    $('#log').append('The row  ' + cell + ' resized to height ' + height + ' px<br>');
}

var selectionActive = function(instance, x1, y1, x2, y2, origin) {
    var cellName1 = jexcel.getColumnNameFromId([x1, y1]);
    var cellName2 = jexcel.getColumnNameFromId([x2, y2]);
    $('#log').append('The selection from ' + cellName1 + ' to ' + cellName2 + '<br>');
}

var loaded = function(instance) {
    $('#log').append('New data is loaded<br>');
    $('.jexcel_content').css('box-shadow', 'none')
}

var moveRow = function(instance, from, to) {
    $('#log').append('The row ' + from + ' was move to the position of ' + to + ' <br>');
}

var moveColumn = function(instance, from, to) {
    $('#log').append('The col ' + from + ' was move to the position of ' + to + ' <br>');
}

var blur = function(instance) {
    $('#log').append('The table ' + $(instance).prop('id') + ' is blur<br>');
}

var focus = function(instance) {
    $('#log').append('The table ' + $(instance).prop('id') + ' is focus<br>');
}

var paste = function(instance, data) {
    $('#log').append('Paste on the table ' + $(instance).prop('id') + '<br>');
}

// var data = [
//     ['2021-03-04 00:00:00', 0.045243, 237, 'BUY', '=IF(D1=="BUY",(B1*C1),0)', '=IF(D1=="SELL",(B1*C1),0)', '=IF(D1=="BUY",C1,0-C1)', '=E1-F1', '=IF(D1=="BUY",B1,"")', '=IF(D1=="BUY",C1,"")', '=IF((H1/G1)<MIN(I1:I2),"-",(H1/G1))', 0],
//     ['2021-03-04 00:01:00', 0.044741, 224, 'BUY', '=IF(D1=="BUY",(B2*C2),0)', '=IF(D2=="SELL",(B2*C2),0)', '=IF(D2=="BUY",C2+G1,G1-C2)', '=H1+(E2-F2)', '=IF(D2=="BUY",B2,"")', '=IF(D2=="BUY",C2,"")', '=IF((H2/G2)<MIN(I1:I2),"-",(H2/G2))', '=IF(D2=="SELL",F2-(K1*C2),0)'],
// ];

var data = [];

var w = $('.wrapper-content').width() - 20;
var spread = jspreadsheet(document.getElementById('spreadsheet'), {
        data:data,
        rowResize:false,
        columnDrag:false,
        tableOverflow: true,
        tableWidth:w + 'px',
        copyCompatibility:true,
        allowInsertRow: true,
        allowManualInsertRow: false,
        columns: [
            { title: 'Date Time', type: 'calendar', width:'150', options: { format:'DD/MM/YYYY HH24:MI', time:1 } },
            { title: 'Price', type: 'numeric', width:'100' },
            { title: 'Qty', type: 'numeric', width:'80' },
            { title: 'Type', type: 'dropdown', width:'80', source:[ "BUY", "SELL"] },
            { title: 'Buy', type: 'numeric', width:'80' },
            { title: 'Sell', type: 'numeric', width:'80', readOnly:false },
            { title: 'Net', type: 'numeric', width:'80' },
            { title: 'Cumulative', type: 'numeric', width:'90' },
            { title: 'Buy Price', type: 'numeric', width:'80' },
            { title: 'Buy Qty', type: 'numeric', width:'80' },
            { title: 'Average', type: 'numeric', width:'80' },
            { title: 'Profit/Loss', type: 'numeric', width:'0' },
            { title: 'ID', type: 'numeric', width:'0', readOnly:true},
            { title: 'OrderId', type: 'numeric', width:'100' },
        ],
        onchange: changed,
        onbeforechange: beforeChange,
        oninsertrow: insertedRow,
        oninsertcolumn: insertedColumn,
        ondeleterow: deletedRow,
        ondeletecolumn: deletedColumn,
        onselection: selectionActive,
        onsort: sort,
        onresizerow: resizeRow,
        onresizecolumn: resizeColumn,
        onmoverow: moveRow,
        onmovecolumn: moveColumn,
        onload: loaded,
        onblur: blur,
        onfocus: focus,
        onpaste: paste,
        onbeforeinsertcolumn: function(a,b,c) {
        },
        contextMenu: function(obj, x, y, e) {
         var items = [];
 
         if (y == null) {
         } else {
             // Insert new row
             if (obj.options.allowInsertRow == true) {
                var max = obj.getData().length;
                var row = obj.getData().length + 1;
                 
                 items.push({
                     title:'Add new row',
                     onclick:function() {
                          $.get('$urlFormula' + '?row=' + parseInt(row) + '&prev=' + (parseInt(row) - 1) + '&max=' + parseInt(row), (res) => {
                            //obj.data.push(res)
                            console.log(parseInt(row))
                            obj.insertRow(1, parseInt(row));
                            obj.setRowData(max, res)
                          })
                     }
                 });
             } 

             if (obj.options.allowDeleteRow == true) {
                 items.push({
                     title:obj.options.text.deleteSelectedRows,
                     onclick:function() {
                         obj.deleteRow(obj.getSelectedRows().length ? undefined : parseInt(y));
                         //obj.refresh();
                     }
                 });
             }
 
             if (x) {
                 if (obj.options.allowComments == true) {
                     items.push({ type:'line' });
 
                     var title = obj.records[y][x].getAttribute('title') || '';
 
                     items.push({
                         title: title ? obj.options.text.editComments : obj.options.text.addComments,
                         onclick:function() {
                             obj.setComments([ x, y ], prompt(obj.options.text.comments, title));
                         }
                     });
 
                     if (title) {
                         items.push({
                             title:obj.options.text.clearComments,
                             onclick:function() {
                                 obj.setComments([ x, y ], '');
                             }
                         });
                     }
                 }
             }

             // Save
             if (obj.options.allowExport) {
                 items.push({
                     title: 'Save',
                     shortcut: 'Ctrl + S',
                     onclick: function () {
                         obj.download();
                     }
                 });
             }
         
        }
 
         // Line
         items.push({ type:'line' });
 
         return items;
     }        
});
    
window.spread = spread

//wait for formula loaded
setTimeout(function() {
    window.spread.setData($data)
}, 500);

$('.coin-drop').change(function(){
    window.location = '$url?coin=' + this.value
})

$('#save').click(()=>{
    var data = spread.getData()
    
    $.post('$urlSave?coin=$coin', {data: JSON.stringify(data)}, (res) => {
        if(res.success){
            toastr["success"]("Data saved")
            //reload page
            window.location.reload()
        }
    });
})
JS
);

$this->registerJs(
<<<JS
//----formula-----
const PRICE_COL = 'B';
const QTY_COL = 'C';
const TYPE_COL = 'D';
const BUY_COL = 'E';
const SELL_COL = 'F';
const NET_COL = 'G';
const CUM_COL = 'H';
const BUY_PRICE_COL = 'I';
const BUY_QTY_COL = 'J';
const AVERAGE_COL = 'K';
const PROFIT_COL = 'L';

var BUY = function(row) {
		
	var price = window.spread.getValue(PRICE_COL + row);
	var qty = window.spread.getValue(QTY_COL + row);
	var type = window.spread.getValue(TYPE_COL + row);
	if (type == 'BUY') {
		return (price * qty)
	}
    return 0;
}

var SELL = function(row) {
	var price = window.spread.getValue(PRICE_COL + row);
	var qty = window.spread.getValue(QTY_COL + row);
	var type = window.spread.getValue(TYPE_COL + row);	
	if (type === 'SELL') {
		return (price * qty)
	}
	return 0;
}

var NET = function(row) {
	
	var type = window.spread.getValue(TYPE_COL + row);
	var qty = window.spread.getValue(QTY_COL + row);
	var pnet = window.spread.getValue(NET_COL + (row - 1));
	
	if (type === 'BUY') {
		if (row == 1) {
			return qty
		}
		return parseInt(qty) + parseInt(pnet)
	} else {
		if (row == 1) {
			return 0 - qty
		}
		//negatif
// 		if(pnet < 0) {
// 			return parseInt(pnet) + parseInt(qty)
// 		}
		return parseInt(pnet) - parseInt(qty)
	}
	return 0;
}

var CUM = function(row) {

	var buy = window.spread.getValue(BUY_COL + row);
	var sell = window.spread.getValue(SELL_COL + row);
	var pcum = window.spread.getValue(CUM_COL + (row - 1));
	
	if (row == 1) {
		return buy - sell
	} else {
		return parseFloat(pcum) + parseFloat(buy - sell)
	}
}

var BUY_PRICE = function(row) {
	var type = window.spread.getValue(TYPE_COL + row);
	if(type == 'BUY') {
		return window.spread.getValue(PRICE_COL + row);
	}
	return 0
}

var BUY_QTY = function(row) {	
	var type = window.spread.getValue(TYPE_COL + row);
	if(type == 'BUY') {
		return window.spread.getValue(QTY_COL + row);
	}
	return 0;
}

var buyprice = 0 ;
var CAVERAGE = function(row, min) {	
	var cum = window.spread.getValue(CUM_COL + row);
    var prevavg = window.spread.getValue(AVERAGE_COL + (row - 1));
    var type = window.spread.getValue(TYPE_COL + row);
	var net = window.spread.getValue(NET_COL + row);
    var sell = window.spread.getValue(SELL_COL + row);
	
	var buyprice = spread.getColumnData(1);
	var min = Math.min(...buyprice)
    
    if(type == 'BUY') {
        return parseFloat(cum) / parseFloat(net)
    } else if(type == 'SELL') {
        return (prevavg * cum) / (cum - sell) 
    }

    return 0;
    	
// 	if( (cum/net) < min ) {
// 		return 0;
// 	} else {
//		return parseFloat(cum) / parseFloat(net)
// 	}
}

var PROFIT = function(row, min) {
	
	var fcol = [
    	BUY_COL + row,
    	SELL_COL + row,
    	NET_COL + row,
    	CUM_COL + row,
    	BUY_PRICE_COL + row,
    	BUY_QTY_COL + row,
    	AVERAGE_COL + row,
    	PROFIT_COL + row
	]
	spread.formula[QTY_COL + row] = fcol
	spread.formula[TYPE_COL + row] = fcol 
	spread.formula[PRICE_COL + row] = fcol
    spread.formula[CUM_COL + (row - 1)] = [
        CUM_COL + row,
        AVERAGE_COL + row
    ];
    spread.formula[AVERAGE_COL + (row - 1)] = [PROFIT_COL + row]
	
	var type = window.spread.getValue(TYPE_COL + row);
	var sell = window.spread.getValue(SELL_COL + row);
	var qty = window.spread.getValue(QTY_COL + row);
	var pave = window.spread.getValue(AVERAGE_COL + (row - 1));

	if(type == 'SELL') {
		if(row > 1) {
			return sell - parseFloat(pave * qty)
		}
	}
	return 0
}
JS
,
YII::$app->view::POS_HEAD
);
?>

<link rel="stylesheet" href="https://bossanova.uk/jspreadsheet/v4/jexcel.css" type="text/css" />
<link rel="stylesheet" href="https://jsuites.net/v4/jsuites.css" type="text/css" />
<link rel="stylesheet" href="https://bossanova.uk/jspreadsheet/v4/jexcel.themes.css" type="text/css" />
<!-- <link rel="stylesheet" href="https://bossanova.uk/jspreadsheet/v4/jexcel.datatables.css" type="text/css" /> -->


<style>
.mail-search {
	max-width: 500px;
}

#dropSearch_chosen>.chosen-single {
	min-width: 200px;
	height: 30px !important;
}

.pagination {
	float: right;
}

#w0-filters {
    display:none;
}

.tr-item {
    cursor:pointer;
}

.table td {
    white-space: nowrap;
}

.jexcel > tbody > tr > td.readonly {
    color:blue;
}

.coin-drop {
    width:150px;
/*     max-width:min-content; */
    display:inline-block;
    vertical-align: top;
}

.coin-label{
   vertical-align: super;
}

.btn-default.m-b{
   line-height: 23px;
}

.jexcel_content::-webkit-scrollbar-thumb {
    border-radius: 10px;
    background:gray;
}


:root {
    --jexcel_header_color: #000;
    --jexcel_header_color_highlighted: #000;
    --jexcel_header_background: #f3f3f4;
    --jexcel_header_background_highlighted: #90caf9;
    --jexcel_content_color: #000;
    --jexcel_content_color_highlighted: #000;
    --jexcel_content_background: #fff;
    --jexcel_content_background_highlighted: rgba(0,0,0,0.05);
    --jexcel_menu_background: #fff;
    --jexcel_menu_background_highlighted: #ebebeb;
    --jexcel_menu_color: #555;
    --jexcel_menu_color_highlighted: #555;
    --jexcel_menu_box_shadow: 2px 2px 2px 0px rgba(143, 144, 145, 1);
    --jexcel_border_color: #ccc;
    --jexcel_border_color_highlighted: #000;
    --active_color: #007aff;
}

.jexcel > tbody > tr > td, .jexcel > thead > tr > td {
    padding:10px;
    font-weight:100;    
}

.jexcel > tbody > tr > td:nth-child(3),
.jexcel > tbody > tr > td:nth-child(4),
.jexcel > tbody > tr > td:nth-child(5) {
    color:#2196f3
}
</style>
<div class="wrapper wrapper-content">
	<div x-data="loadData()">
	<span class="coin-label">SYMBOL :- </span>
	<?= Html::dropDownList('crypto', $coin, CryptoParameter::getSymbol(), ['prompt' => '--Select--','class' => 'form-control coin-drop', 'x-model'=> 'symbol'])?> 
    <?= Html::button('<i class="fa fa-refresh"></i> '. Yii::t('app', 'Pull record'), ['class' => 'btn btn-sm btn-default m-b', 'id' => 'pull-record', '@click'=>"openModal()" , 'disabled' => empty($_GET['coin'])]) ?>
	<?= Html::button('<i class="fa fa-save"></i> '. Yii::t('app', 'Save record'), ['class' => 'btn btn-sm btn-primary m-b', 'id' => 'save']) ?>
	
	<div class="alert alert-info" x-show="!symbol"> Please Select Symbol First</div>
	
	<?php
    /* start modal */
    Modal::begin([
        'header' => Yii::t('app', '<h4>Add Record From Binance</h4>'),
        'size' => 'modal-lg',
        'id' => 'add-modal' 
    ]);
    ?>
    <div class="row">
    		<!-- <div class="col-md-5">
    			<div class="form-group">
                    <label class="font-normal">Start Date</label>
                    <input type="datetime-local" class="form-control" x-model="startTime">
        		</div>
    		</div>
    		<div class="col-md-5">
    			<div class="form-group">
                    <label class="font-normal">End Date</label>
                    <input type="datetime-local" class="form-control" x-model="endTime">
				</div>
    		</div>
    		<div class="col-md-2" style="line-height:76px;">
  				<button class="btn btn-default" @click="pullData()">Pull Record</button>
    		</div> --> 
    		<div class="col-md-12" style="text-align: right">
        		<button class="btn btn-success" @click="selectAll()"><i class="fa fa-check"></i> Select all</button>
        		<button class="btn btn-warning" @click="deselectAll()"><i class="fa fa-times"></i> Deselect all</button>
        		<button class="btn btn-primary" @click="addRecord()"><i class="fa fa-plus"></i> Add Record</button>
    		</div>
    	</div>
    <div class="table-responsive">
        <table class="table table-striped">
            <thead>
            <tr>
                <th></th>
                <th>Symbol </th>
                <th>OrderId </th>
                <th>Price</th>
                <th>Quantity</th>
                <th>Quote</th>
                <th>Side</th>
                <th>Time</th>
            </tr>
            </thead>
            <tbody>
            <template x-for="(item, index) in items" :key="index">
                <tr x-show="existData.indexOf(item.orderId) == -1">
                    <td><input type="checkbox" class="checks" name="checkbox[]" :value="JSON.stringify(item)"></td>
                    <td><small  x-text="item.symbol"></small></td>
                    <td><small  x-text="item.orderId"></small></td>
                    <td><small  x-text="item.price"></small></td>
                    <td><small  x-text="item.qty"></small></td>
                    <td><small  x-text="item.quoteQty"></small></td>
                    <td><small  x-text="item.isBuyer ? 'BUY' : 'SELL'"></small></td>
                    <td><small  x-text="item.time"></small></td>
            	</tr>
    		</template>
			<tr x-show="noRecord">
                <td colspan="7" align="center"> No records founds</td>
        	</tr>
            </tbody>
        </table>
    </div>
    <script type="text/javascript">
	function loadData(){
		let data = <?= $data ?>;
		let	exist = data.map(v => v[v.length - 1]);
    	return {
    		items: [],
    		startTime: null,
    		endTime: null,
    		noRecord: true,
    		symbol: '<?= $coin ?>',
    		existData: exist,
    		openModal() {
    			$('#add-modal').modal('show')
    			this.pullData()
    		},
    		deselectAll() {
    			$('.checks').each( (i, v)=> {
    				v.checked = false;
				})
    		},
    		selectAll() {
    			$('.checks').each( (i, v)=> {
    				v.checked = true;
				})
    		},
    		addRecord(){
    			let record = []
    			let exist = spread.getJson()
				
				if(!exist) {
					return
				}
				
				record = exist;
				
    			$('.checks').each( (i, v) => {
                    if(v.checked) {
                    	let r = [];
                    	let j = JSON.parse(v.value)
						let side = j.isBuyer ? 'BUY' : 'SELL'
						r.push(j.time);
						r.push(j.price);
						r.push(j.qty);
						r.push(side);
                    	r.push('=BUY(ROW())')
                    	r.push('=SELL(ROW())')
                    	r.push('=NET(ROW())')
                    	r.push('=CUM(ROW())')
                    	r.push('=BUY_PRICE(ROW())')
                    	r.push('=BUY_QTY(ROW())')
                    	r.push('=CAVERAGE(ROW())')
                    	r.push('=PROFIT(ROW())')
                    	r.push(null)
                    	r.push(j.orderId)
                        record.push(r)
                    }
				})
		
				window.spread.setData(record)
    		},
    		pullData() {
    			
    		    $.ajax('<?= $urlPull ?>?symbol=<?= $coin ?>', {
                    type: 'POST',
                    dataType: 'json',
                    contentType: 'application/json',
                    data: JSON.stringify({ orderId: 1234})
                })
                .done(data => {
                    $('#add-modal').modal('show')
                    
                    if(!data.success){
                    	alert('Failed to get response from the server');
                    	return;
                    }
                    
                    if(data.data.length > 0) {
                    	this.noRecord = false
                    }
                    
                    const record = data.data.filter( (v) => true)
                    
                    this.items = record
                })
                .fail((e) => {
                    console.error('Fail to connect the data server:', e.statusText);
                });
    		}
    	}
    }
    </script>	
    <?php Modal::end(); ?>
	</div>
	<div class="ibox <?= empty($_GET['coin']) ? 'hide' : '' ?>" >
		<div class="mail-box b-r-md" style="padding:10px">
			<div id="spreadsheet"></div>
		</div>
	</div>
<!-- 	<div id="log"></div> -->
</div>