Hello,
For a given pair in a flashloan arbitrage operation, taking the example of uniswap and sushiswap as the selected DEX´s for executing an arbitrage opportunity, and for 1INCH/WETH token pair, sushiswap WETH price is cheaper than uniswap (despite having larger reserve volumes in comparison).
The problem lies when I execute the following two lines of code in my `uniswapV2call `method:
uint amountToRepay = UniswapV2Library.getAmountsIn(factory, _amount, path)[0];
uint amountReceived = router.swapExactTokensForTokens(
_amount,
amountToRepay,
path,
msg.sender,
(block.timestamp + 300))[1];
and it returns **amountToRepay > amountReceived** when I was expecting the result to be other way round owing to spotted price difference opportunity under arbitrage operation.
**Output console.log (from my back-end smart contract)**
_getAmountsIn() results.......
path[0] 0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2
path[1] 0x111111111117dc0aa78b770fa6a738034120c302
amountBorrowed 2497817866881194385864
**amountToRepay 964334905750628563**
getAmountsOut() results.......
path[0] 0x111111111117dc0aa78b770fa6a738034120c302
path[1] 0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2
**amountReceived 950114205093874394**_
**Output error message**
Error: VM Exception while processing transaction: **reverted with reason string 'UniswapV2Router: INSUFFICIENT_OUTPUT_AMOUNT'**
at <UnrecognizedContract>.<unknown> (0x7a250d5630b4cf539739df2c5dacb4c659f2488d)
at FlashloanerArbitrage.uniswapV2Call (contracts/FlashloanerArbitrage.sol:261)
at <UnrecognizedContract>.<unknown> (0x86f518368e0d49d5916e2bd9eb162e9952b7b04d)
at FlashloanerArbitrage.startSwap (contracts/FlashloanerArbitrage.sol:180)
at processTicksAndRejections (node:internal/process/task_queues:96:5)
at EthModule._estimateGasAction (C:\Samuel\Blockchain\Flashloan-arbitrage-bot-uniswapV2_hardhat\node_modules\hardhat\src\internal\hardhat-network\provider\modules\eth.ts:429:7)
at HardhatNetworkProvider._sendWithLogging (C:\Samuel\Blockchain\Flashloan-arbitrage-bot-uniswapV2_hardhat\node_modules\hardhat\src\internal\hardhat-network\provider\provider.ts:139:22)
at HardhatNetworkProvider.request (C:\Samuel\Blockchain\Flashloan-arbitrage-bot-uniswapV2_hardhat\node_modules\hardhat\src\internal\hardhat-network\provider\provider.ts:116:18)
at JsonRpcHandler._handleRequest (C:\Samuel\Blockchain\Flashloan-arbitrage-bot-uniswapV2_hardhat\node_modules\hardhat\src\internal\hardhat-network\jsonrpc\handler.ts:188:20)
at JsonRpcHandler._handleSingleRequest (C:\Samuel\Blockchain\Flashloan-arbitrage-bot-uniswapV2_hardhat\node_modules\hardhat\src\internal\hardhat-network\jsonrpc\handler.ts:167:17)
at Server.JsonRpcHandler.handleHttp (C:\Samuel\Blockchain\Flashloan-arbitrage-bot-uniswapV2_hardhat\node_modules\hardhat\src\internal\hardhat-network\jsonrpc\handler.ts:52:21)
Where am I going wrong here as this issue has been troubling me for several weeks now.
I have tried implementing other_ pricing oracle methods but it comes back to this very same issue.
Any help or suggestions would be greatly appreciated.
Thank you
Expected the output value from getAmountsIn to be less returned value from getAmountsOut in a spotted arbitrage price difference opportunity.
Related
I'm trying to send request using Postman to test Klarna payment, According to this API DOC, We use POST /checkout/v3/orders to send a request so that we can create order (For the testing environment they use https://api.playground.klarna.com/ + rest of url), But when i'm trying to send the given example in the above link(on the right side), It says that
{ "error_code" : "BAD_VALUE", "error_messages" : [ "Bad value: order_tax_amount" ], "correlation_id" : "12255531-ffcb-4a91-a375-04577fca78e5" }
When i read what does it require in the documentation, It says that the value should be formatted in some formula ±1 of total_amount - total_amount * 10000 / (10000 + tax_rate), When i calculate that the result 4545.4545 when i change the value in the request and try again, It gives the same error.
Can anybody help me with that?
Thanks
The docs you've linked say that order_tax_amount should be an integer of minor currency units, so it sounds like 4545.4545 isn't a valid value!
You should choose which direction you want to round in, then send an integer value instead.
I found the problem, I should change both total_tax_amount and order_tax_amount to be 4545, What a mistake, I think they should update this in their documentation so people be more familiar with it.
I'm trying to use the Google AdWords bid simulator system to try and get some insights out of the AdWords bid simulator. More specifically I'm using the AdGroupBidLandscape() functionality, but it's returning 'No Campaigns Found', but we definitely have campaigns where the Bid Simulator tool works through the AdWords web page interface, so I'm a bit confused. Here is the code I'm running, and yes I know I'm only retrieving a single field - I'm just trying to keep things as simple as possible.
from googleads import adwords
import logging
import time
CHUNK_SIZE = 16 * 1024
PAGE_SIZE = 100
logging.basicConfig(level=logging.INFO)
logging.getLogger('suds.transport').setLevel(logging.DEBUG)
adwords_client = adwords.AdWordsClient.LoadFromStorage()
dataService = adwords_client.GetService('DataService', version='v201710')
offset = 0
selector = {'fields':['Bid'], #'impressions', 'promotedImpressions', 'requiredBudget', 'bidModifier', 'totalLocalImpressions', 'totalLocalClicks', 'totalLocalCost', 'totalLocalPromotedImpressions'],
'paging': {
'startIndex': str(offset),
'numberResults': str(PAGE_SIZE)
}
}
more_pages = True
while more_pages:
page = dataService.getAdGroupBidLandscape(selector)
# Display results.
if 'entries' in page:
for campaign in page['entries']:
print ('Campaign with id "%s", name "%s", and status "%s" was '
'found.' % (campaign['id'], campaign['name'],
campaign['status']))
else:
print 'No campaigns were found.'
offset += PAGE_SIZE
selector['paging']['startIndex'] = str(offset)
more_pages = offset < int(page['totalNumEntries'])
time.sleep(1)
We have several different accounts attachd to AdWords. My account is the only one that has developer API access, so I sort of wonder if the problem is that my account isn't the primary account associated with the campaigns- I just have one of the few administrator accounts. Can anyone provide some insights about this for me?
Thanks,
Brad
The solution I found to this problem was to add a predicate to the selector specifying a particular CampaignId. While that doesn't make any sense to me that it would fix it, because it should really just be filtering the data with that if I understand things correctly, it seems to have. I don't have a good explanation for that, but I thought someone else might find this useful. If I come to realize this wasn't the fix to the problem I had, I will come back and update this answer.
My problem is the following:
I have one report called Y5000112.
My colleagues always execute it manually once with selection screen variant V1 and then execute it a second time with variant V2 adding the results of the first execution to the selection.
Those results in this case are PERNR.
My goal:
Automate this - execute that query twice with one click and automatically fill the PERNR selection of the second execution with the PERNR results of the first execution.
I found out how to trigger a report execution and after that another one, how to set it to a certain variant and got this far - [EDIT] after the first answer I got a bit further but I still have no idea how to loop through my results and put them into the next Report submit:
DATA: t_list TYPE TABLE OF abaplist.
* lt_seltab TYPE TABLE OF rsparams,
* ls_selline LIKE LINE OF lt_seltab.
SUBMIT Y5000114
USING SELECTION-SET 'MA OPLAN TEST'
EXPORTING LIST TO MEMORY
AND RETURN.
CALL FUNCTION 'LIST_FROM_MEMORY'
TABLES
listobject = t_list
EXCEPTIONS
not_found = 1
OTHERS = 2.
IF sy-subrc <> 0.
WRITE 'Unable to get list from memory'.
ELSE.
* I want to fill ls_seltab here with all pernr (table pa0020) but I haven't got a clue how to do this
* LOOP AT t_list.
* WRITE /t_list.
* ENDLOOP.
SUBMIT Y5000114
* WITH-SELECTION-TABLE ls_seltab
USING SELECTION-SET 'MA OPLAN TEST2'
AND RETURN.
ENDIF.
P.S.
I'm not very familiar with ABAP so if I didn't provide enough Information just let me know in the comments and I'll try to find out whatever you need to know in order to solve this.
Here's my imaginary JS-Code that can express very generally what I'm trying to accomplish.
function submitAndReturnExport(Reportname,VariantName,OptionalPernrSelection)
{...return resultObject;}
var t_list = submitAndReturnExport("Y5000114","MA OPLAN TEST");
var pernrArr = [];
for (var i in t_list)
{
pernrArr.push(t_list[i]["pernr"]);
}
submitAndReturnExport("Y5000114","MA OPLAN TEST2",pernrArr);
It's not that easy as it supposed to, so there won't be any one-line snippet. There is no standard way of getting results from report. Try EXPORTING LIST TO MEMORY clause, but consider that the report may need to be adapted:
SUBMIT [report_name]
WITH SELECTION-TABLE [rspar_tab]
EXPORTING LIST TO MEMORY
AND RETURN.
The result of the above statement should be read from memory and adapted for output:
call function 'LIST_FROM_MEMORY'
TABLES
listobject = t_list
EXCEPTIONS
not_found = 1
others = 2.
if sy-subrc <> 0.
message 'Unable to get list from memory' type 'E'.
endif.
call function 'WRITE_LIST'
TABLES
listobject = t_list
EXCEPTIONS
EMPTY_LIST = 1
OTHERS = 2
.
if sy-subrc <> 0.
message 'Unable to write list' type 'E'.
endif.
Another (and more efficient approach, IMHO) is to gain access to resulting grid via class cl_salv_bs_runtime_info. See the example here
P.S. Executing the same report with different parameters which are mutually-dependent (output pars of 1st iteration = input pars for the 2nd) is definitely a bad design, and those manipulations should be done internally. As for me one'd better rethink the whole architecture of the report.
We are running application in Spring context using DataNucleus as our ORM mapping and mysql as our database.
Our application have a daily import job of some data feed into our database. The size of the data feed translate into around 1 millions row of insert/update. The performance of the import start out to be very good but then it degrade overtime (as the number of executed query increase) and at some point the application freeze or stop responding. We will have to wait for the whole job to complete before the application response again.
This behavior looks very like a memory leak to us and we have been looking hard at our code to catch any potential problem, however the problem didn't go away. One interesting thing we found from the heap dump is that org.datanucleus.ExecutionContextThreadedImpl (or the HashSet/HashMap) hold 90% of our memory (5GB) during the import. (I have attahed the screenshot of the dump below). My research on the internet said this reference is the Level1 Cache (not sure am i correct). My question is during a large import, how can i limit/control the size of the level1 cache. May be ask DN to not cache during my import?
If that's not the L1 cache, what's the possible cause of my memory issue?
Our code use a transaction for every insert to prevent locking of large chunk of data in the database. It's call the flush method every 2000 insert
As a temporary fix, we moved our import process to run overnight when no one is using our app. Obviously, this cannot go on forever. Please could someone at least point us in the right direction so that we can do more research and hoping we can find a fixes.
Would be good if someone have knowledge of decoding the heap dump
Your help would be very much appreciated by all of us here. Many thanks!
https://s3-ap-southeast-1.amazonaws.com/public-external/datanucleus_heap_dump.png
https://s3-ap-southeast-1.amazonaws.com/public-external/datanucleus_dump2.png
Code Below - Caller of this method does not have a transaction. This method will process one import object per call, and we need to process around 100K of these object daily
#Override
#PreAuthorize("(hasUserRole('ROLE_ADMIN')")
#Transactional(propagation = Propagation.REQUIRED)
public void processImport(ImportInvestorAccountUpdate account, String advisorCompanyKey) {
ImportInvestorAccountDescriptor invAccDesc = account
.getInvestorAccount();
InvestorAccount invAcc = getInvestorAccountByImportDescriptor(
invAccDesc, advisorCompanyKey);
try {
ParseReportingData parseReportingData = ctx
.getBean(ParseReportingData.class);
String baseCCY = invAcc.getBaseCurrency();
Date valueDate = account.getValueDate();
ArrayList<InvestorAccountInformationILAS> infoList = parseReportingData
.getInvestorAccountInformationILAS(null, invAcc, valueDate,
baseCCY);
InvestorAccountInformationILAS info = infoList.get(0);
PositionSnapshot snapshot = new PositionSnapshot();
ArrayList<Position> posList = new ArrayList<Position>();
Double totalValueInBase = 0.0;
double totalQty = 0.0;
for (ImportPosition importPos : account.getPositions()) {
Asset asset = getAssetByImportDescriptor(importPos
.getTicker());
PositionInsurance pos = new PositionInsurance();
pos.setAsset(asset);
pos.setQuantity(importPos.getUnits());
pos.setQuantityType(Position.QUANTITY_TYPE_UNITS);
posList.add(pos);
}
snapshot.setPositions(posList);
info.setHoldings(snapshot);
log.info("persisting a new investorAccountInformation(source:"
+ invAcc.getReportSource() + ") on " + valueDate
+ " of InvestorAccount(key:" + invAcc.getKey() + ")");
persistenceService.updateManagementEntity(invAcc);
} catch (Exception e) {
throw new DataImportException(invAcc == null ? null : invAcc.getKey(), advisorCompanyKey,
e.getMessage());
}
}
Do you use the same pm for the entire job?
If so, you may want to try to close and create new ones once in a while.
If not, this could be the L2 cache. What setting do you have for datanucleus.cache.level2.type? It think it's a weak map by default. You may want to try none for testing.
I'm writing a program where the user must enter a 'yes' or 'no' value. The following is the code that will be executed when the message {createPatient,PatientName} is received.
{createPatient, PatientName} ->
Pid = spawn(patient,newPatient,[PatientName]),
register(PatientName,Pid),
io:format("*--- New Patient with name - ~w~n", [PatientName]),
Result = io:read("Yes/No> "),
{_,Input} = Result,
if(Input==yes) ->
io:format("OK")
end,
loop(PatientRecords, DoctorPatientLinks, DoctorsOnline, CurrentPatientRequests, WaitingOfflineDoctorRequests);
When executed ,the line "New Patient with name..." is displayed however the line Yes/No is not displayed and the program sort of crashes because if another message is sent, then the execution of that message will not occur. Is there a different way to solve this problem please?
There are a number of points I would like to make here:
The io:read/1 function reads a term, not just a line, so you have to terminate input with a '.' (like in the shell).
io:read/1 returns {ok,Term} or {error,Reason} or eof so you code should check for these values, for example with a case.
As #AlexeyRomanov mentioned, io:get_line/1 might be a better choice for input.
The if expression must handle all cases even the ones in which you don't want to do anything, otherwise you will get an error. This can be combined with the case testing the read value.
You spawn the function patient:newPatient/1 before you ask if the name is a new patient, this seems a little strange. What does the newpatient function do? Is it in anyway also doing io to the user which might be interfering with functions here?
The main problem seems to be work out what is being done where, and when.
This is very artificial problem. In erlang any communication is usually inter-process and exchanging strings wouldn't make any sense - you ask question in context of process A and you would like to post answer in context of process B (shell probably).
Anyways, consider asking question and waiting in receive block in order to get an answer.
When question pops out in shell, call a function which will send the answer to 'asking' process with your answer.
So:
io:format("*--- New Patient with name - ~w~n", [PatientName]),
receive
{answer, yes} -> do_something();
{answer, no} -> do_something()
end
The 'answering' function would look like that:
answer(PatientName, Answer) ->
PatientName ! {answer, Answer}.
And shell action:
$> *--- New Patient with name - User1036032
$> somemodule:answer('User1036032', yes).
It is possible to create some dialog with shell (even unix shell), but to be honest it is used so rare that I do not remember those I/O tricks with read and write. http://trapexit.com/ used to have cookbook with this stuff.
Use io:get_line("Yes/No> ") instead.