Olá pessoal, tudo bem?
Estou escrevendo um programa pra me ajudar a enviar ordens de compra e venda de ações na B3. Situação atual: escrevo dados de compra ou venda em um arquivo no Google Drive (de qualquer máquina) e o AHK lê esse arquivo e executa ordens de compra e venda sobre o programa ProfitChart, em um computador que fica ligado direto em casa.
Preciso implementar um Trailing Stop, e para isso, pretendo usar o DDE do ProfitChart diretamente no AHK. O DDE do Profit abre normalmente no excel (na mesma máquina) e atualiza certinho. Preciso que o AHK pegue esses dados diretamente do Profitchart (AHK e Profitchart estão na mesma máquina).
O valor da célula on excel tem esse padrão "=profitchart|cot!RLOG3.MAX" ou "=profitchart|cot!RLOG3.MIN" etc. (sem aspas), e essa célula possui um valor (10.54 por exemplo).
É possível o AHK receber ou pegar esses dados diretamente do profitchart?
Pegar dados DDE do ProfitChart na mesma máquina
Moderator: Gio
-
- Posts: 6
- Joined: 04 Oct 2019, 09:17
Re: Pegar dados DDE do ProfitChart na mesma máquina
Bom dia Luetkmeyer.
Seja bem-vindo ao fórum da comunidade do AutoHotkey.
Encontrei uma biblioteca de funções DDE do usuário Majkinetor. Talvez você possa usá-la para conexão ao Profitchart.
Link do Projeto: https://code.google.com/archive/p/multi-rename-script/
Seja bem-vindo ao fórum da comunidade do AutoHotkey.
Encontrei uma biblioteca de funções DDE do usuário Majkinetor. Talvez você possa usá-la para conexão ao Profitchart.
Code: Select all
; Copyright 2019 Majkinetor
;Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
;1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
;2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
;3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
;THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/*
DDE_Callback(nType, nFormat, hConv, hString1, hString2, hData, nData1, nData2)
{
}
*/
DDE_Initialize(idInst = 0, pCallback = 0, nFlags = 0)
{
If DllCall("DdeInitialize", "UintP", idInst, "Uint", pCallback, "Uint", nFlags, "Uint", 0)=0
Return idInst
}
DDE_Uninitialize(idInst)
{
Return DllCall("DdeUninitialize", "Uint", idInst)
}
DDE_GetLastError(idInst)
{
Return DllCall("DdeGetLastError", "Uint", idInst)
}
DDE_NameService(idInst, sServ = "", nCmd = 1)
{
Return DllCall("DdeNameService", "Uint", idInst, "Uint", hServ:=sServ="" ? 0 : DDE_CreateStringHandle(idInst,sServ), "Uint", 0, "Uint", nCmd), hServ ? DDE_FreeStringHandle(idInst,hServ) : ""
}
DDE_EnableCallback(idInst, hConv = 0, nCmd = 0)
{
Return DllCall("DdeEnableCallback", "Uint", idInst, "Uint", hConv, "Uint", nCmd)
}
DDE_PostAdvise(idInst, sTopic = "", sItem = "")
{
Return DllCall("DdePostAdvise", "Uint", idInst, "Uint", hTopic:=sTopic="" ? 0 : DDE_CreateStringHandle(idInst,sTopic), "Uint", hItem:=sItem="" ? 0 : DDE_CreateStringHandle(idInst,sItem))
, hTopic ? DDE_FreeStringHandle(idInst,hTopic) : ""
, hItem ? DDE_FreeStringHandle(idInst,hItem) : ""
}
DDE_ClientTransaction(idInst, hConv, sType = "EXECUTE", sItem = "", pData = 0, cbData = 0, CF_Format = 1, bAsync = False){
static XTYP_ADVSTART := 0x1030, XTYP_ADVSTOP := 0x8040, XTYP_EXECUTE := 0x4050, XTYP_POKE := 0x4090, XTYP_REQUEST := 0x20B0
Return DllCall("DdeClientTransaction", "Uint", pData, "Uint", cbData, "Uint", hConv, "Uint", hItem:=sItem="" ? 0 : DDE_CreateStringHandle(idInst,sItem), "Uint", CF_Format, "Uint", XTYP_%sType%, "Uint", bAsync ? TIMEOUT_ASYNC:=-1 : 10000, "UintP", nResult), hItem ? DDE_FreeStringHandle(idInst,hItem) : ""
}
DDE_AbandonTransaction(idInst, hConv = 0, idTransaction = 0)
{
Return DllCall("DdeAbandonTransaction", "Uint", idInst, "Uint", hConv, "Uint", idTransaction)
}
DDE_Connect(idInst, sServ = "", sTopic = "", pCC = 0)
{
Return DllCall("DdeConnect", "Uint", idInst, "Uint", hServ:=sServ="" ? 0 : DDE_CreateStringHandle(idInst,sServ), "Uint", hTopic:=sTopic="" ? 0 : DDE_CreateStringHandle(idInst,sTopic), "Uint", pCC)
, hTopic ? DDE_FreeStringHandle(idInst,hTopic) : ""
, hServ ? DDE_FreeStringHandle(idInst,hServ) : ""
}
DDE_Reconnect(hConv)
{
Return DllCall("DdeReconnect", "Uint", hConv)
}
DDE_Disconnect(hConv)
{
Return DllCall("DdeDisconnect", "Uint", hConv)
}
DDE_ConnectList(idInst, sServ = "", sTopic = "", hConvList = 0, pCC = 0)
{
Return DllCall("DdeConnectList", "Uint", idInst, "Uint", hServ:=sServ="" ? 0 : DDE_CreateStringHandle(idInst,sServ), "Uint", hTopic:=sTopic="" ? 0 : DDE_CreateStringHandle(idInst,sTopic), "Uint", hConvList, "Uint", pCC)
, hTopic ? DDE_FreeStringHandle(idInst,hTopic) : ""
, hServ ? DDE_FreeStringHandle(idInst,hServ) : ""
}
DDE_DisconnectList(hConvList)
{
Return DllCall("DdeDisconnectList", "Uint", hConvList)
}
DDE_QueryNextServer(hConvList, hConvPrev = 0)
{
Return DllCall("DdeQueryNextServer", "Uint", hConvList, "Uint", hConvPrev)
}
DDE_QueryConvInfo(hConv, idTransaction = -1, ByRef ci = "") ; QID_SYNC=-1
{
Return DllCall("DdeQueryConvInfo", "Uint", hConv, "Uint", idTransaction, "Uint", NumPut(VarSetCapacity(ci,64,0),ci)-4)
}
DDE_AccessData(hData, ByRef cbData = "")
{
Return DllCall("DdeAccessData", "Uint", hData, "UintP", cbData)
}
DDE_UnaccessData(hData)
{
Return DllCall("DdeUnaccessData", "Uint", hData)
}
DDE_AddData(hData, pData, cbData, cbOff = 0)
{
Return DllCall("DdeAddData", "Uint", hData, "Uint", pData, "Uint", cbData, "Uint", cbOff)
}
DDE_GetData(hData, ByRef sData = "", cbOff = 0)
{
cb := DllCall("DdeGetData", "Uint", hData, "Uint", 0, "Uint", 0, "Uint", cbOff)
VarSetCapacity(sData, cb)
If DllCall("DdeGetData", "Uint", hData, "str", sData, "Uint", cb, "Uint", cbOff)
Return sData
}
DDE_QueryString(idInst, hString, nCodePage = 1004) ; CP_WINANSI = 1004, CP_WINUNICODE = 1200
{
cch := DllCall("DdeQueryString", "Uint", idInst, "Uint", hString, "Uint", 0, "Uint", 0, "int", nCodePage)
VarSetCapacity(sString, cch)
If DllCall("DdeQueryString", "Uint", idInst, "Uint", hString, "str", sString, "Uint", cch+1, "int", nCodePage)
Return sString
}
DDE_CreateDataHandle(idInst, sItem = "", pData = 0, cbData = 0, cbOff = 0, CF_Format = 1, bOwned = True)
{
Return DllCall("DdeCreateDataHandle", "Uint", idInst, "Uint", pData, "Uint", cbData, "Uint", cbOff, "Uint", hItem:=sItem="" ? 0 : DDE_CreateStringHandle(idInst,sItem), "Uint", CF_Format, "Uint", bOwned ? HDATA_APPOWNED:=1 : 0), hItem ? DDE_FreeStringHandle(idInst,hItem) : ""
}
DDE_FreeDataHandle(hData)
{
Return DllCall("DdeFreeDataHandle", "Uint", hData)
}
DDE_CreateStringHandle(idInst, sString, nCodePage = 1004)
{
Return DllCall("DdeCreateStringHandle", "Uint", idInst, "Uint", &sString, "int", nCodePage)
}
DDE_KeepStringHandle(idInst, hString)
{
If DllCall("DdeKeepStringHandle", "Uint", idInst, "UintP", hString)
Return hString
}
DDE_FreeStringHandle(idInst, hString)
{
Return DllCall("DdeFreeStringHandle", "Uint", idInst, "Uint", hString)
}
DDE_CmpStringHandles(hString1, hString2)
{
Return DllCall("DdeCmpStringHandles", "Uint", hString1, "Uint", hString2)
}
DDE_SetUserHandle(hConv, hUser)
{
Return DllCall("DdeSetUserHandle", "Uint", hConv, "Uint", -1, "Uint", hUser)
}
"What is suitable automation? Whatever saves your day for the greater matters."
Barcoder - Create QR Codes and other Barcodes using only Autohotkey !!
Archmage Gray - A fantasy shooter game fully coded in AutoHotkey
Barcoder - Create QR Codes and other Barcodes using only Autohotkey !!
Archmage Gray - A fantasy shooter game fully coded in AutoHotkey
-
- Posts: 6
- Joined: 04 Oct 2019, 09:17
Re: Pegar dados DDE do ProfitChart na mesma máquina
Vou tentar, muito obrigado.
Re: Pegar dados DDE do ProfitChart na mesma máquina
Bom dia.
Infelizmente não consegui fazer funcionar. Não entendo o suficiente de funções pra fazer isso.
Você conhece alguma comunidade que tem desenvolvedor AHK pra fazer esse serviço pago?
Novamente agradeço.
Infelizmente não consegui fazer funcionar. Não entendo o suficiente de funções pra fazer isso.
Você conhece alguma comunidade que tem desenvolvedor AHK pra fazer esse serviço pago?
Novamente agradeço.
-
- Posts: 6
- Joined: 04 Oct 2019, 09:17
Re: Pegar dados DDE do ProfitChart na mesma máquina
Continuo tentando, ainda sem sucesso.
Você conseguiria verificar o link da referência que me enviou? Preciso encontrar um pouco mais de informações, aprender a usar essa função. Estou precisando muito.
Aproveitando, conhece alguém que conseguiria me ajudar, mesmo que eu pague?
Novamente agradeço.
Você conseguiria verificar o link da referência que me enviou? Preciso encontrar um pouco mais de informações, aprender a usar essa função. Estou precisando muito.
Aproveitando, conhece alguém que conseguiria me ajudar, mesmo que eu pague?
Novamente agradeço.
Re: Pegar dados DDE do ProfitChart na mesma máquina
Tentei esse: https://autohotkey.com/board/topic/23467-dde-server-for-single-instance-file-association-std-lib/
Com esse código:
Tentei esse: https://autohotkey.com/board/topic/20174-ahk-dde-functions-including-asyncbatchmulti-channel/
Com esse código:
Nenhuma variação funcionou, a resposta é sempre o mesmo número 199532
E esse:
com o DDE lib by Majkinetor, indicado aqui.
Não consegui com nenhum deles.
Alguma ideia?
Com esse código:
Code: Select all
; Initialize the DDE server.
result := DDE_InitServer("profitchart", "cot", "BTOW3.MAX")
MsgBox % result
; Let the user know if command-line args were specified.
n = 1
if 0 > 0 ; var '0' contains the number of args
MsgBox % "args: " %n% ; access arg '1' indirectly via 'n'
return
; When you double-click a file (or select the appropriate action from the
; context menu), assuming the file type is associated correctly the script will
; call this sub-routine.
DDE_Command:
; For now just show what command was received.
MsgBox %DDE_Cmd%
return
Tentei esse: https://autohotkey.com/board/topic/20174-ahk-dde-functions-including-asyncbatchmulti-channel/
Com esse código:
Code: Select all
connect := DDE_Connect("profitchart","cot")
try1 := DDE_Execute("BTOW3")
try2 := DDE_Execute("BTOW3.MAX")
try3 := DDE_Execute(BTOW3.MAX)
;try4 := DDE_Execute("=profitchart|cot!BTOW3.MAX")
;try2 := DDE_Request("BTOW3.MAX")
try5 := DDE_Poke("BTOW3.MAX", "cot")
try6 := DDE_Poke("BTOW3", "MAX")
;DDE_Poke("[COMMAND]", "[DATASET FOR COMMAND]",
try=
Loop, 6
try .= "`n" try%a_index%
msgbox connect = %connect%`n`n%try%`n
msgbox 1%try1%`n2%try2%`n3%try3%`n4%try4%`n5%try5%`n6%try6%
; profitchart|cot!BTOW3.MAX
msgbox % DDE_Request("BTOW3.MAX") "`n" DDE_Request("[BTOW3.MAX]")
msgbox % DDE_Poke("[BTOW3.MAX]", "[cot]")
msgbox % DDE_Poke("[BTOW3]", "[MAX]")
msgbox % DDE_Execute("[""BTOW3.MAX""]")
DDE_KILL()
ExitApp
E esse:
Code: Select all
idInst := DDE_Initialize(0, RegisterCallback("DDE_Callback"))
hConv := DDE_Connect(idInst,"profitchart","cot")
tick := DDE_ClientTransaction(idInst, hConv, "EXECUTE")
; not sure where "BID!GBPUSD" request goes, maybe in DDE_AccessData()?
w := DDE_AccessData("BTOW3.MAX")
DDE_Uninitialize(idInst)
msgbox idInst = %idInst%`nhConv = %hConv%`n%tick%`n`nw = %w%
Não consegui com nenhum deles.
Alguma ideia?
Re: Pegar dados DDE do ProfitChart na mesma máquina
Bom dia Luetkmeyer.
Andei pesquisando um pouco mais sobre a tecnologia DDE. É uma tecnologia antiga, precursora até mesmo do modelo COM. É considerada em desuso, mas a boa notícia é que o Windows mantém suporte a ela por questões de compatibilidade com sistemas antigos.
Vejo que as discussões acerca da implementação da tecnologia em AutoHotkey são bem antigas também. Isso traz alguns problemas, pois até 2010 usávamos a versão 1.0 do programa, que tinha uma sintaxe um pouco diferente da versão atual (1.1+) em alguns aspectos. Por isso alguns códigos antigos não funcionam.
Tem um tópico com uma discussão maior sobre o tema neste link. Pelo que entendi, eles parecem estar usando a sintaxe do AutoHokey _L (que mais tarde veio a se tornar o AutoHotkey 1.1+), o que pode ajudar. O problema é que o assunto não é pequeno, e pelo que está escrito nos posts é necessário alterar algumas chaves de registro para que os códigos funcionem (e para completar os códigos foram testados em Windows XP).
Também não tenho acesso nem utilizo o programa ProfitChart (na verdade nem mexo com DayTrade) então nesse quesito fica difícil para mim realizar algum teste.
Mas fiquei pensando, será mesmo que o DDE é a única forma de implementar o TrailingStop que você busca? E porque exatamente você quer remover a conexão via o Excel?
Andei pesquisando um pouco mais sobre a tecnologia DDE. É uma tecnologia antiga, precursora até mesmo do modelo COM. É considerada em desuso, mas a boa notícia é que o Windows mantém suporte a ela por questões de compatibilidade com sistemas antigos.
Vejo que as discussões acerca da implementação da tecnologia em AutoHotkey são bem antigas também. Isso traz alguns problemas, pois até 2010 usávamos a versão 1.0 do programa, que tinha uma sintaxe um pouco diferente da versão atual (1.1+) em alguns aspectos. Por isso alguns códigos antigos não funcionam.
Tem um tópico com uma discussão maior sobre o tema neste link. Pelo que entendi, eles parecem estar usando a sintaxe do AutoHokey _L (que mais tarde veio a se tornar o AutoHotkey 1.1+), o que pode ajudar. O problema é que o assunto não é pequeno, e pelo que está escrito nos posts é necessário alterar algumas chaves de registro para que os códigos funcionem (e para completar os códigos foram testados em Windows XP).
Também não tenho acesso nem utilizo o programa ProfitChart (na verdade nem mexo com DayTrade) então nesse quesito fica difícil para mim realizar algum teste.
Mas fiquei pensando, será mesmo que o DDE é a única forma de implementar o TrailingStop que você busca? E porque exatamente você quer remover a conexão via o Excel?
"What is suitable automation? Whatever saves your day for the greater matters."
Barcoder - Create QR Codes and other Barcodes using only Autohotkey !!
Archmage Gray - A fantasy shooter game fully coded in AutoHotkey
Barcoder - Create QR Codes and other Barcodes using only Autohotkey !!
Archmage Gray - A fantasy shooter game fully coded in AutoHotkey
Re: Pegar dados DDE do ProfitChart na mesma máquina
Legal Gio, muito obrigado pela sua resposta.
Vou analisar o link e tentar implementar.
Fiz um script usando COM pra copiar do excel (que atualiza dados via DDE como stream), mas "fica pesado" pra máquina rodar o dia inteiro (o comando COM fica copiando a cada 10 seg e o ahk faz a análise matemática que preciso). Se eu conseguisse pegar o DDE direto com o ahk, ficaria MUITO mais leve (eu poderia até colocar uma frequência de cálculo maior que os 10 segundos). A ideia é fazer trailingstop automático em Swing Trade (quando chegar em 2, 3% de lucro na semana).
Alternativamente, tentei de todas as formas pegar dados da janela ativa (wingettext, winget, controlget, controlget list, etc. etc.), mas não sei o porque, não fica visível para o ahk.
Novamente agradeço a ajuda, irei procurar mais sobre.
Vou analisar o link e tentar implementar.
Fiz um script usando COM pra copiar do excel (que atualiza dados via DDE como stream), mas "fica pesado" pra máquina rodar o dia inteiro (o comando COM fica copiando a cada 10 seg e o ahk faz a análise matemática que preciso). Se eu conseguisse pegar o DDE direto com o ahk, ficaria MUITO mais leve (eu poderia até colocar uma frequência de cálculo maior que os 10 segundos). A ideia é fazer trailingstop automático em Swing Trade (quando chegar em 2, 3% de lucro na semana).
Alternativamente, tentei de todas as formas pegar dados da janela ativa (wingettext, winget, controlget, controlget list, etc. etc.), mas não sei o porque, não fica visível para o ahk.
Novamente agradeço a ajuda, irei procurar mais sobre.
Re: Pegar dados DDE do ProfitChart na mesma máquina
mas "fica pesado" pra máquina rodar o dia inteiro ... Se eu conseguisse ... eu poderia até colocar uma frequência de cálculo maior que os 10 segundos
Já está usando o SetBatchLines, -1 no início do seu script?
Outra questão: como está coletando os dados da planilha?
Você pode criar um objeto 2D com os dados de um intervalo inteiro da planilha usando uma seleção. Dessa forma, apenas 1 comando COM é executado a cada vez que precise recuperar os dados da planilha.
Exemplo: criar um objeto 2D da célula A2 até a célula G10 e depois exibir os valores célula por célula:
Code: Select all
; Considerando abaixo que X1 já contém o resultado da chamada ComObjActive() à planilha alvo do Excel.
X1.Range( "A2:G10" ).Select ; Ajuste aqui o intervalo das células relevantes.
OBJETO_TABELA := X1.Selection.Value
Loop % OBJETO_TABELA.MaxIndex()
{
LINHA_ATUAL := A_Index
Loop % OBJETO_TABELA[1].MaxIndex()
{
msgbox % OBJETO_TABELA[LINHA_ATUAL, A_Index]
}
}
"What is suitable automation? Whatever saves your day for the greater matters."
Barcoder - Create QR Codes and other Barcodes using only Autohotkey !!
Archmage Gray - A fantasy shooter game fully coded in AutoHotkey
Barcoder - Create QR Codes and other Barcodes using only Autohotkey !!
Archmage Gray - A fantasy shooter game fully coded in AutoHotkey
Re: Pegar dados DDE do ProfitChart na mesma máquina
Uhm, boa estratégia, vou testar. Muito obrigado.
-
- Posts: 6
- Joined: 04 Oct 2019, 09:17
Re: Pegar dados DDE do ProfitChart na mesma máquina
Olá.
A estratégia que você recomendou funcionou muito bem, melhorou o desempenho e estou usando atualização a cada 10 segundos sem pesar a máquina. Muito obrigado!!!
A estratégia que você recomendou funcionou muito bem, melhorou o desempenho e estou usando atualização a cada 10 segundos sem pesar a máquina. Muito obrigado!!!
Return to “Ajuda e Suporte Geral”
Who is online
Users browsing this forum: No registered users and 32 guests